diff --git a/src/js/SlaveState.js b/src/js/SlaveState.js index 1c810000a9cd3181ec45c562efeb15cb01851b58..b920ae803e62e057b227247edc2d4eaa60fa8ecb 100644 --- a/src/js/SlaveState.js +++ b/src/js/SlaveState.js @@ -723,9 +723,13 @@ App.Entity.SlaveState = class SlaveState { * * 7000-7499 - X-cup * * 7500-7999 - Y-cup * * 8000-8499 - Z-cup - * * 8500-19999 - obscenely massive - * * 20000-29999 - beanbag sized - * * 30000-48000 - room filling + * * 8500-14999 - obscenely massive + * * 15000-24999 - arm filling + * * 25000-39999 - figure dominating + * * 40000-54999 - beanbag sized + * * 55000-69999 - door jamming + * * 70000-89999 - hall clearing + * * 90000-100000 - hall jamming */ this.boobs = 0; /** breast engorgement from unmilked tits */ diff --git a/src/js/datatypeCleanupJS.js b/src/js/datatypeCleanupJS.js index e4c82a737cccef1698efc17877c3179f3dafe5c2..910e581b39796acfa693b60d9d8926a5da94fc28 100644 --- a/src/js/datatypeCleanupJS.js +++ b/src/js/datatypeCleanupJS.js @@ -1978,10 +1978,10 @@ App.Entity.Utils.RARuleDatatypeCleanup = function() { function replaceDefaultValues(o) { for (const k in o) { const v = o[k]; - if (typeof v === 'object') { - replaceDefaultValues(v); - } else if (v === "no default setting") { + if (v === "no default setting" || v === undefined) { o[k] = null; + } else if (typeof v === 'object') { + replaceDefaultValues(v); } } } diff --git a/src/js/rulesAssistant.js b/src/js/rulesAssistant.js index 9e9fc8ceb82d6709dc4ac43df4379421d811e2c1..e801b1f6897df32b128ec81099b63b1a106d0bfa 100644 --- a/src/js/rulesAssistant.js +++ b/src/js/rulesAssistant.js @@ -408,52 +408,99 @@ window.RulesDeconfliction = function RulesDeconfliction(slave) { * Creates a table to summarize RA * @returns {string} */ -window.RASummaryCell = function RASummaryCell() { +window.RASummaryCell = function() { + /** + * @param {object[]} objects + * @param {string[]} member + */ + function collectMemberFromObjects(objects, member) { + let r = []; + for (const o of objects) { + let to = o; + for (const m of member) { + to = to[m]; + } + r.push(to); + } + return r; + } + + /** + * @callback ObjectWalker + * @param {object} obj + * @param {string[]} memberPath + */ + + /** + * @param {object} obj + * @param {ObjectWalker} walker + * @param {string[]} path + */ + function walkObject(obj, walker, path) { + for (const prop in obj) { + const v = obj[prop]; + const vp = path.concat([prop]); + if (v !== null && typeof v === 'object') { + walkObject(v, walker, vp); + } else { + walker(obj, vp); + } + } + } + + /** + * @param {string[]} path + * @param {Array} cells + * @param {string[]} table + */ + function addRow(path, cells, table) { + if (!cells.some(v => v !== null)) { // skip empty rows + return; + } + + function ruleSetValueToString(v) { + if (typeof v === 'object' && v.hasOwnProperty('cond') && v.hasOwnProperty('val')) { + return `${v.cond} ${v.val}`; + } + return `${v}`; + } + + let r = `<td>${path.join('.')}</td>`; + for (const cell of cells) { + r += cell !== null ? `<td>${ruleSetValueToString(cell)}</td>` : '<td/>'; + } + table.push(r); + } + const V = State.variables; + /** @type {App.RA.Rule[]} */ + const rules = V.defaultRules; let r = ""; - let i; - let j; - let rules = Object.keys(V.defaultRules); /* needed to determine number of rule sets (chart width)*/ - let keys = Object.keys(V.defaultRules[0].set); /* needed to determine length of rules (chart height)*/ - let values; - let display = 0; + + if (rules.length === 0) { + return ''; + } /* start row title */ r += `<tr><td></td>`; /* make rest of row title */ - for (i = 0; i < rules.length; i++) { - r += `<td>${V.defaultRules[i].name}</td>`; + for (const rule of rules) { + r += `<td>${rule.name}</td>`; } r += `</tr>`; + const setters = rules.map(r => r.set); /* A row for every condition the RA can set. */ /* start loop for row*/ - for (i = 0; i < keys.length; i++) { /* i is for rows/"what they are fed" */ - /* Check if this row will have anything interesting*/ - for (j = 0; j < rules.length; j++) { /* j is the rule set it comes from/"obedient slaves" */ - values = V.defaultRules[j].set[keys[i]]; - if (values && values !== "no default setting") { - display++; - } - } - /* Show the interesting row */ - if (display > 0) { - /* make row title */ - r += `<tr><td>${keys[i]}</td>`; - /* make rest of cells */ - for (j = 0; j < rules.length; j++) { - values = V.defaultRules[j].set[keys[i]]; - if (values === "no default setting" || !values) { - r += `<td></td>`; - } else { - r += `<td>${V.defaultRules[j].set[keys[i]]}</td>`; - } - } - display = 0; - r += `</tr>`; - } + let tableRows = []; + walkObject(setters[0], (obj, path) => { + addRow(path, collectMemberFromObjects(setters, path), tableRows); + }, []); + + for (const row of tableRows) { + r += `<tr>${row}</tr>`; } return r; }; diff --git a/src/js/descriptionWidgets/boobs.js b/src/npc/descriptions/boobs/boobs.js similarity index 98% rename from src/js/descriptionWidgets/boobs.js rename to src/npc/descriptions/boobs/boobs.js index 25d3823b81447a80acf0bc7a77cb7fb67ea35191..6bc84d8ecddea532a747eb1620eed3d06b541cba 100644 --- a/src/js/descriptionWidgets/boobs.js +++ b/src/npc/descriptions/boobs/boobs.js @@ -2,97 +2,117 @@ App.Desc.boobBits = function() { 'use strict'; const data = { - 300: { + 299: { cup: "flat", anCup: false, adjective: ["androgynous", "flat"], noun: ["chest"] }, - 400: { + 399: { cup: "A-cup", anCup: true, adjective: ["pointy", "tiny"], noun: ["chest"] }, - 500: { + 499: { cup: "B-cup", anCup: false, adjective: ["perky", "small"], noun: ["boobs", "bosom", "breasts", "tits"] }, - 650: { + 649: { cup: "C-cup", anCup: false, adjective: ["curved", "healthy"], noun: ["boobs", "bosom", "breasts", "bust", "tits"] }, - 800: { + 799: { cup: "D-cup", anCup: false, adjective: ["big", "sizable"], noun: ["boobs", "bosom", "breasts", "bust", "tits"] }, - 1000: { + 999: { cup: "DD-cup", anCup: false, adjective: ["big", "large"], noun: ["boobs", "bosom", "breasts", "bust", "tits"] }, - 1200: { + 1199: { cup: "F-cup", anCup: true, adjective: ["hefty", "proud"], noun: ["boobs", "breasts", "mammaries", "tits", "udders"] }, - 1400: { + 1399: { cup: "G-cup", anCup: false, adjective: ["hefty", "huge"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 1600: { + 1599: { cup: "H-cup", anCup: true, adjective: ["huge", "massive"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 1800: { + 1799: { cup: "I-cup", anCup: true, adjective: ["enormous", "massive"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 2050: { + 2049: { cup: "J-cup", anCup: false, adjective: ["enormous", "titanic"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 2300: { + 2299: { cup: "K-cup", anCup: false, adjective: ["stupendous", "titanic"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 2600: { + 2599: { cup: "L-cup", anCup: true, adjective: ["magnificent", "stupendous"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 2900: { + 2899: { cup: "M-cup", anCup: true, adjective: ["magnificent", "tremendous"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 3250: { + 3249: { cup: "N-cup", anCup: true, adjective: ["awe-inspiring", "tremendous"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 3600: { + 3599: { cup: "O-cup", anCup: true, adjective: ["absurd", "awe-inspiring"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 3950: { + 3949: { cup: "P-cup", anCup: false, adjective: ["attention-grabbing", "disproportionate"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 4300: { + 4299: { cup: "Q-cup", anCup: false, adjective: ["massive", "shocking"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 4700: { + 4699: { cup: "R-cup", anCup: true, adjective: ["jaw-dropping", "unreal"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 5100: { + 5099: { cup: "S-cup", anCup: true, adjective: ["astounding", "tremendous"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 5500: { + 5499: { cup: "T-cup", anCup: false, adjective: ["astounding", "tremendous"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 6500: { + 6499: { cup: "U-cup", anCup: false, adjective: ["astounding", "tremendous"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 7000: { + 6999: { cup: "V-cup", anCup: false, adjective: ["astounding", "tremendous"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 7500: { + 7499: { cup: "X-cup", anCup: true, adjective: ["astounding", "tremendous"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 8000: { + 7999: { cup: "Y-cup", anCup: true, adjective: ["astounding", "tremendous"], noun: ["breasts", "mammaries", "tits", "udders"] }, - 8500: { + 8499: { cup: "Z-cup", anCup: false, adjective: ["astounding", "tremendous"], noun: ["boobs", "breasts", "mammaries", "udders"] }, - 20000: { + 14999: { cup: "", anCup: false, adjective: ["obscenely massive", "enormous"], noun: ["boobs", "breasts", "mammaries", "udders", "masses of breastflesh"] }, - 30000: { + 24999: { cup: "", anCup: false, - adjective: ["beanbag sized"], + adjective: ["arm filling"], noun: ["boobs", "breasts", "mammaries", "udders", "masses of breastflesh"] }, - 50000: { + 39999: { cup: "", anCup: false, - adjective: ["room filling"], + adjective: ["figure dominating"], + noun: ["boobs", "breasts", "mammaries", "udders", "masses of breastflesh"] + }, + 54999: { + cup: "", anCup: false, + adjective: ["beanbag-sized"], + noun: ["boobs", "breasts", "mammaries", "udders", "masses of breastflesh"] + }, + 69999: { + cup: "", anCup: false, + adjective: ["door-jamming"], + noun: ["boobs", "breasts", "mammaries", "udders", "masses of breastflesh"] + }, + 89999: { + cup: "", anCup: false, + adjective: ["hall-clearing"], + noun: ["boobs", "breasts", "mammaries", "udders", "masses of breastflesh"] + }, + 100000: { + cup: "", anCup: false, + adjective: ["hall-jamming"], noun: ["boobs", "breasts", "mammaries", "udders", "masses of breastflesh"] }, }; @@ -1325,9 +1345,9 @@ App.Desc.boobs = function() { r += `, ${num(slave.boobs)} CCs each,`; } if (slave.amp === 1) { - r += `are so immense it is safer to leave ${him} resting atop them. ${His} udders each weigh more than twice the rest of ${his} body, since ${his} body consists of nothing but ${his} head, torso, and breasts.`; + r += ` are so immense it is safer to leave ${him} resting atop them. ${His} udders each weigh more than twice the rest of ${his} body, since ${his} body consists of nothing but ${his} head, torso, and breasts.`; } else { - r += `are so gargantuan that they effectively immobilize ${him}. ${He}'s most comfortable lying down.`; + r += ` are so gargantuan that they effectively immobilize ${him}. ${He}'s most comfortable lying down.`; } } return r; diff --git a/src/js/descriptionWidgets/piercing.js b/src/npc/descriptions/boobs/piercing.js similarity index 100% rename from src/js/descriptionWidgets/piercing.js rename to src/npc/descriptions/boobs/piercing.js