From 19ab7bb2a3b05e1878b53ff0f989fc0349aba667 Mon Sep 17 00:00:00 2001 From: Brett Nash Date: Wed, 13 Nov 2024 07:41:58 -0800 Subject: [PATCH] RolemasterUnified Official: Spell lists on sheets and improved creation - Add description to each step of the Charactermancer buttons - Clear ranks on specialised skills if 0. Previously worked for non specilised skills, this fixes specialised skills as well (@ixs) - Add base lists selection in charactermancer. Useful for professions with base lists. Additionally base lists are now stored on the sheet. So they persist. - Add control to stop progression until you have entered all data on the sheet required. - Bump sheet version 7 - Existing charaacters will have their base lists updated on the main sheet. --- .../rolemasterunified.css | 12 + .../rolemasterunified.html | 228 ++++++++++++++++-- RolemasterUnified_Official/sheet.json | 2 +- RolemasterUnified_Official/updates.md | 11 + 4 files changed, 237 insertions(+), 16 deletions(-) diff --git a/RolemasterUnified_Official/rolemasterunified.css b/RolemasterUnified_Official/rolemasterunified.css index 054827b7a3e5..95eed9ba6b6c 100644 --- a/RolemasterUnified_Official/rolemasterunified.css +++ b/RolemasterUnified_Official/rolemasterunified.css @@ -8,6 +8,10 @@ display: block; } +span.choice-showing { + display: inline; +} + @font-face { @@ -109,6 +113,10 @@ h3 { box-shadow: 3px 3px 2px 1px rgba(0,0,0,0.4); } +.fancybutton.disabled { + background: linear-gradient(to top left, #c4c5c7 0%, #dcdddf 52%, #ebebeb 100%); +} + .fancybutton:hover { box-shadow: rgba(0, 0, 0, .3) 2px 8px 8px -5px; transform: translate3d(0, 2px, 0); @@ -740,6 +748,10 @@ div.repcontrol { border-radius: 255px 15px 225px 15px/15px 225px 15px 255px; } +.cmbaselistcount:not([value="6"]) + button { + pointer-events: none; + background: grey; +} /* * Levelup DP box. Starts in the usual spot but sticks to the top so we can see costs all diff --git a/RolemasterUnified_Official/rolemasterunified.html b/RolemasterUnified_Official/rolemasterunified.html index 5a22a538724d..8534bb49dd1f 100644 --- a/RolemasterUnified_Official/rolemasterunified.html +++ b/RolemasterUnified_Official/rolemasterunified.html @@ -390,10 +390,47 @@

Profession

- + +
+

Base Lists

+ + + + + +
+




















+ +Lists Selected / 6 + +
+ +
+ Your chosen profession has six base lists.
+ + List Name
List Name
List Name
List Name
List Name
List Name
+ +
+ + + +
+ Your chosen profession has no base lists. +
+ + - + + + + + + + + + +
@@ -5306,7 +5343,7 @@

Custom Spell List


-Revision 163d394d6154b2284a7ac62c3e0f702660786091 +Revision 232ac6239a389a9fff6ffa1fcb511c5f307cc398
@@ -6921,7 +6958,6 @@

Custom Spell List

let trickerybonus = {}; addPendingFunction("Update Grace & Trickery", () => prepareGraceTrickery(gracebonus, trickerybonus)); addPendingFunction("Update Spells", () => { - console.log(gracebonus, trickerybonus); updateSpells(gracebonus, trickerybonus) }); addPendingFunction("Update favorites", RMUSkills.updateFavorites); @@ -7033,12 +7069,14 @@

Custom Spell List

skill.specializations.forEach((spec) => { let bestbonus = -100; const aname = spec.aname; - getAttrs([aname + "_ranks_misc", aname + "_misc"], (attrs) => { + getAttrs([aname + "_ranks_misc", aname + "_misc", aname + "_ranks"], (attrs) => { let [bonus, ranks, slog] = calculateSpecBonus(skill, attrs[aname + '_ranks_misc'], attrs[aname + '_misc'], spec.stat, pbonus, catbonus, log); let update = {[aname + "_bonus"]: bonus, [aname + "_info"]: slog}; - if (ranks > 0) { + if (ranks != 0) { update[aname + "_ranks"] = ranks; + } else if (attrs[aname + "_ranks"] && attrs[name + "_ranks"] != "") { + update[aname + "_ranks"] = " "; // So there is something there; so set space } if ((bonus - 25) > bestbonus) { bestbonus = bonus - 25; @@ -7074,8 +7112,10 @@

Custom Spell List

let toget = [] toget.push(basename + "_ranks_misc"); toget.push(basename + "_misc"); + toget.push(basename + "_ranks"); getAttrsPending(toget, (attrs) => { + const aname = skill.aname; let [bonus, ranks, slog] = calculateSpecBonus(skill, attrs[basename + '_ranks_misc'], attrs[basename + '_misc'], false, pbonus, catbonus, log); @@ -7085,9 +7125,11 @@

Custom Spell List

} let update = {[basename + "_bonus"]: bonus, [basename + "_info"]: slog}; - if (ranks > 0) { - update[basename + "_ranks"] = ranks; - } + if (ranks != 0) { + update[aname + "_ranks"] = ranks; + } else if (attrs[aname + "_ranks"] && attrs[name + "_ranks"] != "") { + update[aname + "_ranks"] = " "; // So there is something there; so set space + } setAttrsPending(update); }); } @@ -7580,7 +7622,7 @@

Custom Spell List

}); } -// listranks is a dictinary of ranks indexed by the spell list name +// listranks is a dictionary of ranks indexed by the spell list name function initSpellListsCM(savedlists, profession, realm, costs, listranks) { const cmdata = getCharmancerData(); const lu = cmdata?.levelup; @@ -7611,7 +7653,7 @@

Custom Spell List

if (realm.indexOf('/') > -1) { // Hybrid: Two realms realms = realm.split('/'); - addPendingFunction("Hyrid realm 1 open lists",()=> { + addPendingFunction("Hybrid realm 1 open lists",()=> { _spellDoQuery(previousranks, `ListType:*${realms[0]} Open*`, '', 'open', costs['Open'], listranks ); }); addPendingFunction("Hybrid realm 2 open lists",()=> { @@ -7696,8 +7738,7 @@

Custom Spell List

function updateSpellCategory(spellgroup, bonus, gracebonus, trickerybonus) { getAttrsPending(["customspelllists"], (ev) => { - let customlists = ev.customspelllists; - console.log("customlists", customlists); + let customlists = ev.customspelllists || {}; getSectionIDsPending(`repeating_spelllistspell${spellgroup}`, (ids) => { @@ -7718,7 +7759,6 @@

Custom Spell List

let mastery = realmstat + realmstat + RMUSkills.getStat('me') + RMUSkills.getSkillBonus(ranks); - console.log(gracebonus, trickerybonus); setAttrsPending({ [`${basename}_ranks`]: ranks, [`${basename}_scr`]: scrbonus + ranks + bonus, @@ -10081,6 +10121,108 @@

Custom Spell List

}); + + +onCheck("page:baselists", () => { + const cmdata = getCharmancerData(); + const profession = cleanCompendiumName(cmdata?.profession?.values?.profession); + getCompendiumQuery(`Category:SpellList ListType:${profession} Base`, (lists) => { + if (!lists || lists[0].expansion == 0) { + // No spell lists + showChoices(['cmbaselistsnolists', 'baselistsalwaysallow']) + hideChoices(['cmbaselistlists', 'cmbaselistfixed', 'baselistsave', 'baselistnosave']); + return; + } + + const textupdates = {}; + const hideupdates = []; + const showupdates = []; + const attrupdates = {}; + hideupdates.push('cmbaselistsnolists'); + if (lists.length == 6) { + showupdates.push('cmbaselistfixed'); + hideupdates.push('cmbaselistlists', 'baselistsalwaysallow', 'baselistsave', 'baselistnosave'); + // Select the first 6 automatically and move on. + for (let i = 0 ; i < 6 ; i ++) { + attrupdates['cmbaselistselected' + i] = 'on'; + } + } else { + showupdates.push('cmbaselistlists', 'baselistsave'); + hideupdates.push('cmbaselistfixed', 'baselistnosave', 'baselistsalwaysallow'); + } + let i = 0; + for (i = 0 ; i < lists.length ; i ++) { + let list = lists[i]; + textupdates[`cmbaselist${i}name`] = list.name; + showupdates.push(`cmbaselist${i}show`); + attrupdates['cmbaselistname' + i] = list.name; + } + if (i > 20) { + rmuerror("Too many base lists for this profession", profession); + i = 20; + } + for ( ; i < 20 ; i ++) { + hideupdates.push(`cmbaselist${i}show`); + attrupdates['cmbaselistselected' + i] = 'off'; + } + setCharmancerText(textupdates); + showChoices(showupdates); + console.log("hide", hideupdates, "show", showupdates); + hideChoices(hideupdates); + setAttrs(attrupdates); + }); +}); + +function createBaseListsCount(cmdata) { + const values = cmdata.baselists.values; + let count = 0; + for (let i = 0 ; i < 21 ; i ++) { + const value = values['cmbaselistselected' + i]; + count += (value == 'on') ? 1 : 0; + } + return count; +} + +/* On the baselists selection page, someone selected or cleared a selector + * for a baselist. Update the count and show or hide the next button based + * on the the value (ie 6) */ +onCheck(Array.from({length: 21}).map((_,i) => "mancerchange:cmbaselistselected" + i).join(' '), (_) => { + // Get them all and count + const cmdata = getCharmancerData(); + const count = createBaseListsCount(cmdata); + const updates = {} + if (count == 6) { + showChoices(["baselistsave"]); + hideChoices(["baselistnosave"]); + } else { + hideChoices(["baselistsave"]); + showChoices(["baselistnosave"]); + } + updates.cmbaselistcount = count; + setAttrs(updates); +}); + +onCheck("clicked:baselistsdone", () => { + const count = createBaseListsCount(getCharmancerData()); + if (count == 6) { + changeCharmancerPage("stats"); + } +}); + +function createSaveBaseLists() { + const cmdata = getCharmancerData(); + const values = cmdata.baselists.values; + const updates = {}; + for (let i = 0 ; i < 21 ; i ++) { + const value = values['cmbaselistselected' + i]; + if (value == 'on') { + const rowid = generateRowID(); + updates[`repeating_spelllistspellownbase_${rowid}_name`] = values['cmbaselistname' + i]; + } + } + setAttrs(updates); +} + onCheck("page:stats", () => { const cmdata = getCharmancerData(); console.log("stats page"); @@ -10691,6 +10833,8 @@

Custom Spell List

} }); + addPendingFunction("CMFinish: Save base lists", createSaveBaseLists); + addPendingFunction("CMFinish: update all skills", RMUSkills.updateAllSkills); addPendingFunction("CMFinish: Front page", updateFrontPage); @@ -14712,10 +14856,15 @@

Custom Spell List

} if (version == 5) { - addPendingFunction("Force skill update from missing update in 5", RMUSkills.updateAllSkills); + addPendingFunction("Upgrade to 6: Force skill update from missing update in 5", RMUSkills.updateAllSkills); version = 6; } + if (version == 6) { + addPendingFunction("Upgrade to 7: Save baselists on sheet", upgradeV6to7); + version = 7; + } + if (oldversion != version) { addPendingFunction(`Version update to ${version}`, () => { setAttrsPending({version: version}); @@ -14839,6 +14988,55 @@

Custom Spell List

}); } +// Since treasure law requires you to pick base lists, we are going to store them on +// the sheet itself going forward. +// +// We only need to apply this change if they have a profession. So newly created +// characters are skipped. +function upgradeV6to7() { + getAttrsPending(["profession"], (prof) => { + if (!prof.profession) { + //New character; done! + console.log("Character not created; skipping"); + return; + } + console.log("get existing base lists"); + getSectionIDsPending("repeating_spelllistspellownbase", (ids) => { + if (ids.length == 6) { + console.log("if 6... we are done"); + // We have enough; stop. + return; + } + const toget = [] + for (id of ids) { + toget.push(`repeating_spelllistspellownbase_${id}_name`); + } + getAttrsPending(toget, (listnames) => { + // FIXME: This is a set. + const names = {}; + for (name in listnames) { + names[listnames[name]] = true; + } + getCompendiumQueryPending(`Category:SpellList ListType:*${prof.profession} Base*`, (lists) => { + const toupdate = {}; + for (ind in lists) { + const list = lists[ind]; + if (names[list.name]) { + continue; + } + const rowid = generateRowID(); + toupdate[`repeating_spelllistspellownbase_${rowid}_name`] = list.name; + } + + setAttrsPending(toupdate); + }); + }); + }); + }); + + +} + diff --git a/RolemasterUnified_Official/sheet.json b/RolemasterUnified_Official/sheet.json index ee11cb9c47c3..7508c8676523 100644 --- a/RolemasterUnified_Official/sheet.json +++ b/RolemasterUnified_Official/sheet.json @@ -8,5 +8,5 @@ "legacy": false, "printable": true, "compendium": "RMU", - "version": "1730910133" + "version": "1731512507" } diff --git a/RolemasterUnified_Official/updates.md b/RolemasterUnified_Official/updates.md index 51f0cac42b94..33b53c75f4f7 100644 --- a/RolemasterUnified_Official/updates.md +++ b/RolemasterUnified_Official/updates.md @@ -1,3 +1,14 @@ +# 2024-11-14 + +- Add description to each step of the Charactermancer buttons +- Clear ranks on specialised skills if 0. Previously worked for non specilised skills, this fixes + specialised skills as well (@ixs) +- Add base lists selection in charactermancer. Useful for professions with base lists. Additionally +base lists are now stored on the sheet. So they persist. +- Add control to stop progression until you have entered all data on the sheet required. +- Bump sheet version 7 + - Existing charaacters will have their base lists updated on the main sheet. + # 2024-11-7 - Sheet version to 6. Funny how lots happen at once.