:: Rules Assistant Options [script] // rewrite of the rules assistant options page in javascript // uses an object-oriented widget pattern // wrapped in a closure so as not to polute the global namespace // the widgets are generic enough to be reusable; if similar user interfaces are ported to JS, we could move the classes to the global scope window.rulesAssistantOptions = (function() { "use strict" let V let r = "" function rulesAssistantOptions(element) { V = State.variables V.nextButton = "Back to Main" V.nextLink = "Main" V.returnTo = "Main" V.showEncyclopedia = 1 V.encyclopedia = "Personal Assistant" const root = new Root(element) } function onreturn(e, cb) { if (e.keyCode === 13) cb() } // create a new rule and reload function newRule(root) { const id = generateNewID() V.defaultRules.push({ ID: id, name: `Rule ${id}`, condition: { function: false, data: {}, excludeSpecialSlaves: false, assignment: [], excludeAssignment: [], selectedSlaves: [], excludedSlaves: [], facility: [], excludeFacility: [], }, set: { releaseRules: "no default setting", clitSetting: "no default setting", clitSettingXY: "no default setting", clitSettingXX: "no default setting", clitSettingEnergy: "no default setting", speechRules: "no default setting", clothes: "no default setting", collar: "no default setting", shoes: "no default setting", virginAccessory: "no default setting", aVirginAccessory: "no default setting", vaginalAccessory: "no default setting", aVirginDickAccessory: "no default setting", dickAccessory: "no default setting", bellyAccessory: "no default setting", aVirginButtplug: "no default setting", buttplug: "no default setting", eyeColor: "no default setting", makeup: "no default setting", nails: "no default setting", hColor: "no default setting", hLength: "no default setting", hStyle: "no default setting", pubicHColor: "no default setting", pubicHStyle: "no default setting", nipplesPiercing: "no default setting", areolaePiercing: "no default setting", clitPiercing: "no default setting", vaginaLube: "no default setting", vaginaPiercing: "no default setting", dickPiercing: "no default setting", anusPiercing: "no default setting", lipsPiercing: "no default setting", tonguePiercing: "no default setting", earPiercing: "no default setting", nosePiercing: "no default setting", eyebrowPiercing: "no default setting", navelPiercing: "no default setting", corsetPiercing: "no default setting", boobsTat: "no default setting", buttTat: "no default setting", vaginaTat: "no default setting", dickTat: "no default setting", lipsTat: "no default setting", anusTat: "no default setting", shouldersTat: "no default setting", armsTat: "no default setting", legsTat: "no default setting", backTat: "no default setting", stampTat: "no default setting", curatives: "no default setting", livingRules: "no default setting", relationshipRules: "no default setting", standardPunishment: "no default setting", standardReward: "no default setting", diet: "no default setting", dietCum: "no default setting", dietMilk: "no default setting", muscles: "no default setting", XY: "no default setting", XX: "no default setting", gelding: "no default setting", preg: "no default setting", growth_boobs: "no default setting", growth_butt: "no default setting", growth_lips: "no default setting", growth_dick: "no default setting", growth_balls: "no default setting", aphrodisiacs: "no default setting", autoSurgery: 0, autoBrand: 0, pornFameSpending: "no default setting", dietGrowthSupport: 0, eyewear: "no default setting", setAssignment: "no default setting", facilityRemove: false, removalAssignment: "rest", surgery_eyes: "no default setting", surgery_lactation: "no default setting", surgery_prostate: "no default setting", surgery_cosmetic: "no default setting", surgery_accent: "no default setting", surgery_shoulders: "no default setting", surgery_shouldersImplant: "no default setting", surgery_boobs: "no default setting", surgery_hips: "no default setting", surgery_hipsImplant: "no default setting", surgery_butt: "no default setting", surgery_faceShape: "no default setting", surgery_lips: "no default setting", surgery_holes: "not default setting", underArmHColor: "no default setting", underArmHStyle: "no default setting", drug: "no default setting", eyes: "no default setting", pregSpeed: "no default setting", bellyImplantVol: -1, } }) V.currentRule = V.defaultRules[V.defaultRules.length-1] reload(root) } function removeRule(root) { const idx = V.defaultRules.findIndex(rule => rule.ID === V.currentRule.ID) V.defaultRules.splice(idx, 1) V.currentRule = idx < V.defaultRules.length ? idx : V.defaultRules.length - 1 reload(root) } function lowerPriority(root) { if (V.defaultRules.length === 1) return // nothing to swap with const idx = V.defaultRules.findIndex(rule => rule.ID === V.currentRule.ID) if (idx === 0) return // no lower rule arraySwap(V.defaultRules, idx, idx-1) reload(root) } function higherPriority(root) { if (V.defaultRules.length === 1) return // nothing to swap with const idx = V.defaultRules.findIndex(rule => rule.ID === V.currentRule.ID) if (idx === V.defaultRules.length - 1) return // no higher rule arraySwap(V.defaultRules, idx, idx+1) reload(root) } function changeName(name, root) { if (name === V.currentRule.name) return V.currentRule = name reload(root) } // reload the passage function reload(root) { root.element.remove() rulesAssistantOptions() } // the Element class wraps around a DOM element and adds extra functionality // this is safer than extending DOM objects directly // it also turns DOM manipulation into an implementation detail class Element { constructor(...args) { this.parent = null this.element = this.render(...args) this.children = [] } appendChild(child) { child.parent = this this.children.push(child) this.element.appendChild(child.element) } // return the first argument to simplify creation of basic container items render(...args) { return args[0] } } // list of clickable elements // has a short explanation (the prefix) and a value display // value display can optionally be an editable text input field // it can be "bound" to a variable by setting its "onchange" method class List extends Element { constructor(prefix, textinput=false) { super(prefix, textinput) this.selectedItem = null this.value = this.element.querySelector(".rajs-value") } render(prefix, textinput) { const elem = document.createElement("div") const label = document.createElement("span") label.innerHTML = prefix let value if (textinput) { value = document.createElement("input") value.classList.add("rajs-value") // call the variable binding when the input field is no longer being edited, and when the enter key is pressed value.onfocusout = () => { this.inputEdited() } value.onkeypress = (e) => { onreturn(e, () => { this.inputEdited() })} } else { value = document.createElement("strong") } value.setAttribute("type", "text") elem.appendChild(label) elem.appendChild(value) elem.classList.add("rajs-list") return elem } inputEdited() { if (this.selectedItem) this.selectedItem.deselect() this.propagateChange() } selectItem(item) { if (this.selectedItem) this.selectedItem.deselect() this.selectedItem = item setValue(item.setValue) this.propagateChange() } selectValue(what) { this.children.some(child => { if (child.data === what) { child.select() return true } else return false }) } setValue(what) { if (this.value.tagName === "input") this.value.value = what else this.value.innerHTML = what } getValue(what) { return (this.value.tagName === "input" ? this.parse(this.value.value) : this.value.innerHTML) } // customisable input field parser / sanity checker parse(what) { return what } propagateChange() { if (this.onchange instanceof Function) this.onchange(this.getValue(), this.selectedItem.data) } } const parse = { integer(string) { let n = parseInt(string, 10) return n === NaN? 0: n }, boobs(string) { return Math.clamp(parse.integer(string), 0, 48000) }, butt(string) { return Math.clamp(parse.integer(string), 0, 10) }, lips(string) { return Math.clamp(parse.integer(string), 0, 100) }, dick(string) { return Math.clamp(parse.integer(string), 0, 10) }, balls(string) { return Math.clamp(parse.integer(string), 0, 10) }, } // a clickable item of a list class ListItem extends Element { constructor(displayvalue, setvalue, data) { super(displayvalue) this.setvalue = setvalue !== undefined ? setvalue : displayvalue this.data = data !== undefined ? data : this.setvalue !== undefined ? this.setvalue : displayvalue this.selected = false } render(displayvalue) { const elem = document.createElement("span") elem.classList.add("rajs-listitem") elem.innerHTML = displayvalue elem.onclick = () => { return this.select() } return elem } select() { if (this.selected) return false this.parent.selectItem(this) this.elem.classList.add("selected") this.selected = true return true } deselect() { this.elem.classList.remove("selected") this.selected = false } } // a way to organise lists with too many elements in subsections // children are bound to the master list class ListSubSection extends Element { render(label) { const elem = document.createElement("em") elem.innerText = label + ":" return elem } appendChild(child) { super.appendChild(child) child.parent = this.parent this.parent.children.push(child) } } // similar to list, but is just a collection of buttons class Options extends Element { constructor(elements=[]) { elements.forEach(element => { this.appendChild(element) }) } render() { const elem = document.createElement("div") elem.classList.add("rajs-list") return elem } } // options equivalent of ListItem class OptionsItem extends Element { constructor(label, onclick) { super(label) this.label = label this.onclick = onclick } render(label, onclick) { const elem = document.createElement("span") elem.classList.add("rajs-listitem") elem.innerHTML = label elem.onclick = () => { return this.onclick(this) } return elem } } class ButtonList extends Element { render(label) { const elem = document.createElement("div") const labelel = document.createElement("span") labelel.innerhTML = label += ":" elem.appendChild(labelel) return elem } getSelection() { return (this.children .filter(child => child.selected) .map(child => child.setvalue) ) } onchange() { return } } class ButtonItem extends Element { constructor(label, setvalue, selected=false) { super(label, selected) this.selected = selected this.setvalue = setvalue ? setvalue : label } render(label, selected) { const container = document.createElement("div") container.classList.add("rajs-listitem") const labelel = document.createElement("span") labelel.innerHTML = label const button = document.createElement("input") button.setAttribute("type", "checkbox") button.checked = selected button.onchange = () => this.onchange(button.checked) container.appendChild(labelel) container.appendChild(button) return container } onchange(value) { this.selected = value parent.onchange(this) } } // rule import field class NewRuleField extends Element { constructor(root) { super() this.root = root } render() { const container = document.createElement("div") const textarea = document.createElmenet("textarea") textarea.placeholder = "Paste your rule here" container.appendChild(textarea) this.textarea = textarea const button = document.createElement("button") button.name = "Load" button.onclick = () => { this.loadNewRule() } container.appendChild(button) return container } loadNewRule() { const text = this.textarea.value try { const rule = JSON.parse(text) if (!rule.ID) rule.ID = generateNewID() reload(this.root) } catch (e) { alert(e) } } } // the base element, parent of all elements class Root extends Element { constructor() { super() if(V.defaultRules.length === 0) { const paragraph = document.createElement("p") paragraph.innerHTML = "<strong>No rules</strong>" this.appendChild(new Element(paragraph)) this.appendChild(new NoRules(this)) return } this.appendChild(new RuleSelector(this)) this.appendChild(new RuleOptions(this)) } render(element) { const greeting = document.createElement("p") greeting.innerHTML = `<em>${properTitle()}, I will review your slaves and make changes that will have a beneficial effect. Apologies, ${properTitle()}, but this function is... not fully complete. It may have some serious limitations. Please use the 'no default setting' option to identify areas I should not address.</em>` element.appendChild(greeting) return element } } // optoins displayed when there are no rules class NoRules extends Options { constructor(root) { super() this.root = root const newrule = new OptionsItem("Add a new rule", () => { newRule(this.root) }) this.appendChild(newrule) const importrule = new OptionsItem("Import a rule", () => { this.root.appendChild(new NewRuleField()) }) this.appendChild(importrule) } } // buttons for selecting the current rule class RuleSelector extends List { constructor(root) { super("Current rule:") if (!V.currentRule) V.currentRule = V.defaultRules[0] V.defaultRules.forEach(rule => { const item = new ListItem(rule.name, rule.name, rule) this.appendChild(item) if (rule.ID === V.currentRule.ID) item.select() }) this.onchange = function (rulename, rule) { V.currentRule = rule reload(root) } } } // buttons for doing transformations on rules class RuleOptions extends Options { constructor(root) { super() this.appendChild(new OptionsItem("New Rule", () => newRule(root))) this.appendChild(new OptionsItem("Remove Rule", () => removeRule(root))) this.appendChild(new OptionsItem("Apply rules", () => this.appendChild(new ApplicationLog()))) this.appendChild(new OptionsItem("Lower Priotity", () => lowerPriority(root))) this.appendChild(new OptionsItem("Higher Priority", () => higherPriority(root))) this.appendChild(new OptionsItem("Rename", () => this.appendChild(new RenameField(root)))) this.appendChild(new OptionsItem("Export this rule", () => this.appendChild(new ExportField()))) this.appendChild(new OptionsItem("Export all rules", () => this.appendChild(new ExportField(true)))) this.appendChild(new OptionsItem("Import a rule", () => this.appendChild(new NewRuleField()))) } } class ApplicationLog extends Element { render() { const elem = document.createElement("div") elem.innerHTML = DefaultRules() return elem } } class RenameField extends Element { constructor(root) { super() this.element.onfocusout = () => changeName(this.element.value, root) this.element.onkeypress = (e) => onreturn(e, () => changeName(this.element.value, root)) } render() { const elem = document.createElement("div") elem.setAttribute("type", "text") elem.setAttribute("value", V.currentRule.name) } } class ExportField extends Element { render(all=false) { const element = document.createElement("textarea") element.value = all ? JSON.stringify(V.currentRule) : map(i => JSON.stringify(i), V.defaultRules).join("\n\n") return element } } // parent section for condition editing class ConditionEditor extends Element { constructor() { super() this.appendChild(new ConditionFunction()) this.appendChild(new AssignmentInclusion()) this.appendChild(new FacilityInclusion()) this.appendChild(new SpecialExclusion()) this.appendChild(new SpecificInclusionExclusion()) } render() { const element = document.createElement("div") return element } } class ConditionFunction extends Element { constructor() { super() this.fnlist = new List("Activation function:") this.fneditor = null ["Never", "Always", "Custom"].forEach(i => this.fnlist.appendChild(i)) ["Devotion", "Trust", "Health", "Sex drive", "Weight", "Age", "Body Age", "Visible Age", "Muscles", "Lactation", "Pregnancy", "Pregnancy Multiples", "Belly Implant", "Belly Size"].forEach(i => this.fnlist.appendChild(i, this.getAttribute(i))) this.fnlist.onchange = () => this.fnchanged switch(V.currentRule.condition.function) { case "Never": case "Always": break case "Custom": this.appendChild(new CustomEditor(V.currentRule.condition.data)) break default: this.appendChild(new RangeEditor(V.currentRule.condition.function, V.currentRule.condition.data)) break } } render() { return document.createElement("div") } getAttribute(what) { return { "Devotion": "devotion", "Trust": "trust", "Health": "health", "Sex drive": "energy", "weight": "weight", "Age": "actualAge", "Body Age": "physicalAge", "Visible Age": "visualAge", "Muscles": "muscles", "Lactation": "lactation", "Pregnancy": "preg", "Pregnancy Multiples": "pregType", "Belly implant": "bellyImplant", "Belly Size": "belly", }[what] } fnchanged(value) { if (this.fneditor !== null) { this.fneditor.element.remove() this.fneditor = null } switch(value) { case "Never": V.currentRule.condition.function = false V.currentRule.condition.data = {} break case "Always": V.currentRule.condition.function = true V.currentRule.condition.data = {} break case "Custom": V.currentRule.condition.function = "custom" V.currentRule.condition.data = {} this.appendChild(new CustomEditor(V.currentRule.condition.data)) break default: V.currentRule.condition.function = "between" V.currentRule.condition.data = { attribute: value, value: [null, null] } this.appendChild(new RangeEditor(V.currentRule.condition.data)) break } } } class CustomEditor extends Element { constructor(data) { if (data.length === 0) data = "function(slave) { return slave.slaveName === 'Fancy Name'; }" super(data) this.elem.onfocusout = () => V.currentRule.data = this.elem.value } render(data) { const elem = document.createElement("textarea") elem.setAttribute(value, data) return elem } } class RangeEditor extends Element { render(data) { const elem = document.createElement("div") const min = document.createElement("input") min.setAttribute("type", "text") min.value = data.between[0] min.onkeypress = e => onreturn(e, () => this.setmin(min.value)) min.onfocusout = e => this.setmin(min.value) elem.appendChild(min) const max = document.createElement("input") max.setAttribute("type", "text") max.value = data.between[0] max.onkeypress = e => onreturn(e, () => this.setmax(max.value)) max.onfocusout = e => this.setmax(max.value) elem.appendChild(max) const infobar = document.createElement("div") infobar.innerHTML = this.info(data.attribute) elem.appendChild(infobar) return elem } parse(value) { value = value.strip() if (value === "null") value = null else { value = parseInt(value) if (value === NaN) value = null } return value } setmin(value) { V.currentRule.data.between[0] = this.parse(value) } setmax(value) { V.currentRule.data.between[1] = this.parse(value) } info(attribute) { return "TODO" } } class AssignmentInclusion extends ButtonList() { constructor() { super("Apply to assignments") ["Rest", "Fucktoy", "Subordinate Slave", "House Servant", "Confined", "Whore", "Public Servant", "Classes", "Milked", "Gloryhole"].forEach( i => this.appendChild(new ButtonItem(i, this.getAttribute(i), V.currentRule.condition.assignment.includes(i)))) } onchange() { V.currentRule.condition.assignment = this.getSelection() } getAttribute(what) { return { "Rest": "rest", "Fucktoy": "please you", "Subordinate Slave": "be a subordinate slave", "House Servant": "be a servant", "Confined": "stay confined", "Whore": "whore", "Public Servant": "serve the public", "Classes": "take classes", "Milked": "get milked", "Gloryhole": "work a glory hole", }[what] } } class FacilityInclusion extends ButtonList() { constructor() { super("Apply to assignments") const facilities = [] if (V.HGSuite > 0) facilities.push("Head Girl Suite") if (V.brothel > 0) facilities.push("Brothel") if (V.club > 0) facilities.push("Club") if (V.arcade > 0) facilities.push("Arcade") if (V.dairy > 0) facilities.push("Dairy") if (V.servantQuarters > 0) facilities.push("Servant Quarters") if (V.masterSuite > 0) facilities.push("Master Suite") if (V.schoolroom > 0) facilities.push("Schoolroom") if (V.spa > 0) facilities.push("Spa") if (V.clinic > 0) facilities.push("Clinic") if (V.cellblock > 0) facilities.push("Cellblock") facilities.forEach( i => this.appendChild(new ButtonItem(i, this.getAttribute(i), V.currentRule.condition.facility.includes(i)))) } onchange(value) { V.currentRule.condition.facility = this.getSelection() } getAttribute(what) { return { "Head Girl Suite": "live with your Head Girl", "Brothel": "work in the brothel", "Club": "serve in the club", "Arcade": "be confined in the arcade", "Dairy": "work in the dairy", "Servant Quarters": "work as a servant", "Master Suite": "serve in the master suite", "Schoolroom": "learn in the schoolroom", "Spa": "rest in the spa", "Clinic": "get treatment in the clinic", "Cellblock": "be confined in the cellblock", }[what] } } class SpecialExclusion extends List { constructor() { super("Exclude special slaves:") const yes = new ListItem("Yes", "Yes", true) const no = new ListItem("No", "No", false) this.appendChild(yes) this.appendChild(no) if (V.currentRule.excludeSpecialSlaves) yes.select() this.onchange = (label, value) => V.currentRule.excludeSpecialSlaves = value } } class SpecificInclusionExclusion extends Options { constructor() { super() this.appendChild(new OptionsItem("Limit to specific slaves", () => Engine.display("Rules Slave Select"))) this.appendChild(new OptionsItem("Exclude specific slaveS", () => Engine.display("Rules Slave Exclude"))) } } // parent section for effect editing class EffectEditor extends Element { constructor() { super() this.appendChild(new AppearanceSection()) this.appendChild(new CosmeticSection()) this.appendChild(new BodyModSection()) this.appendChild(new AutosurgerySection()) this.appendChild(new RegimenSection()) this.appendChild(new BehaviourSection()) } render() { const element = document.createElement("div") return element } } class AppearanceSection extends Element { constructor() { super() this.appendChild(new ClothesList()) this.appendChild(new CollarList()) this.appendChild(new ShoeList()) this.appendChild(new CorsetList()) this.appendChild(new VagAccVirginsList()) this.appendChild(new VagAccAVirginsList()) this.appendChild(new VagAccOtherList()) if (V.seeDicks !== 0 || V.makeDicks !== 0) { this.appendChild(new DickAccVirginsList()) this.appendChild(new DickAccOtherList()) } this.appendChild(new ButtplugsVirginsList()) this.appendChild(new ButtplugsOtherList()) this.appendChild(new ImplantVolumeList()) this.appendChild(new AutosurgerySwitch()) } render() { return document.createElement("div") } } class RegimenSection extends Element { constructor() { super() this.appendChild(new GrowthList()) this.appendChild(new CurrativesList()) this.appendChild(new AphrodisiacList()) this.appendChild(new ContraceptiveList()) if (V.pregSpeedControl) this.appendChild(new PregDrugsList()) this.appendChild(new FemaleHormonesList()) this.appendChild(new ShemaleHormonesList()) this.appendChild(new GeldingHormonesList()) this.appendChild(new OtherDrugsList()) this.appendChild(new DietList()) this.appendChild(new DietGrowthList()) this.appendChild(new DietBaseList()) this.appendChild(new MuscleList()) this.appendChild(new BraceList()) } render() { return document.createElement("div") } } class BehaviourSection extends List { constructor() { super() this.appendChild(new LivingStandardList()) this.appendChild(new PunishmentList()) this.appendChild(new RewardList()) this.appendChild(new ReleaseList()) this.appendChild(new SmartFetishList()) this.appendChild(new SmartXYAttractionList()) this.appendChild(new SmartXXAttractionList()) this.appendChild(new SmartEnergyList()) this.appendChild(new SpeechList()) this.appendChild(new RelationshipList()) if (V.studio === 1) this.appendChild(new PornList()) } render() { return document.createElement("div") } } class ClothesList extends List { constructor() { super("Clothes") this.appendChild(new ListItem("Select her own outfit", "choosing her own clothes")) const nice = new ListSubSection() this.appendChild(nice) const nclothes = [ ["No default clothes setting", "no default setting"], ["Bangles", "slutty jewelry"], ["Bodysuit", "a comfortable bodysuit"], ["Cheerleader outfit", "a cheerleader outfit"], ["Clubslut netting", "clubslut netting"], ["Cutoffs and a t-shirt", "cutoffs and a t-shirt"], ["Fallen nun", "a fallen nuns habit"], ["Halter top", "a halter top dress"], ["Hijab and abaya", "a hijab and abaya"], ["Latex catsuit", "a latex catsuit"], ["Leotard", "a leotard"], ["Maid (nice)", "a nice maid outfit"], ["Maid (slutty)", "a slutty maid outfit"], ["Military uniform", "a military uniform"], ["Mini dress", "a mini dress"], ["Nice lingerie", "attractive lingerie"], ["Nurse (nice)", "a nice nurse outfit"], ["Schoolgirl", "a schoolgirl outfit"], ["Silken ballgown", "a ball gown"], ["Skimpy battledress", "battledress"], ["Slave gown", "a slave gown"], ["Slutty outfit", "a slutty outfit"], ["String bikini", "a stirng bikini"], ["Scalemail bikini", "a scalemail bikini"], ["Succubus costume", "a succubus outfit"], ["Suit (nice)", "nice business sattire"], ["Suit (slutty", "slutty business attire"], ["Spats and tank top", "spats and a tank top"] ] const fsnclothes = [ ["Body oil (FS)", "body oil"], ["Bunny outfit (FS)", "a bunny outfit"], ["Chattel habit (FS)", "a chattel habit"], ["Conservative clothing (FS)", "conservative clothing"], ["Harem gauze (FS)", "harem gauze"], ["Huipil (FS)", "a huipil"], ["Kimono (FS)", "a kimono"], ["Maternity dress (FS)", "a maternity dress"], ["Maternity lingerie (FS)", "attractive lingerie for a pregnant woman"], ["Slutty qipao (FS)", "a slutty qipao"], ["Stretch pants and a crop-top (FS)", "stretch pants and a crop-top"], ["Toga (FS)", "a toga"], ["Western clothing (FS)", "Western clothing"], ] nclothes.forEach(pair => nice.appendChild(new ListItem(...pair))) fsnclothes.forEach(pair => { if (isItemAccessible(pair[1])) nice.appendChild(new ListItem(...pair))}) harsh = new ListSubSection() this.appendChild(harsh) const hclothes = [ ["Nude", "no clothing"] ["Penitent nun", "a penitent nuns habit"], ["Restrictive latex", "restrictive latex"], ["Shibari ropes", "shibari ropes"], ["Uncomfortable straps", "uncomfortable straps"] ] const fshclothes = [ ["Chains (FS)", "chains"], ] hclothes.forEach(pair => nice.appendChild(new ListItem(...pair))) fshclothes.forEach(pair => { if (isItemAccessible(pair[1])) nice.appendChild(new ListItem(...pair))}) this.selectValue(V.currentRule.set.clothes) this.onchange = (label, value) => V.currentRule.set.clothes = value } } class CollarList extends List { constructor() { super("Collar") this.appendChild("No default collar setting", "no default setting") this.appendChild("No collar", "none") const nice = new ListSubSection("Nice") this.appendChild(nice) const ncollars = [ ["Stylish leather", "stylish leather"], ["Satin choker", "satin choker"], ["Silken Ribbon", "silk ribbon"], ["Heavy Gold", "heavy gold"], ["Pretty jewelry", "pretty jewelry"], ["Cowbell", "leather with cowbell"] ] if (V.seeAge !== 0) ncollars.push(["Nice retirement counter", "nice retirement counter"]) const fsncollars = [ ["Bowtie collar", "bowtie"], ["ancient Egyptian", "ancient Egyptian"], ] ncollars.forEach(pair => nice.appendChild(new ListItem(...pair))) fsncollars.forEach(pair => { if (isItemAccessible(pair[1])) nice.appendChild(new ListItem(...pair))}) const harsh = new ListSubSection("Harsh") this.appendChild(harsh) const hcollars = [ ["Tight steel", "tight steel"], ["Uncomfortable leather", "uncomfortable leather"], ["Pregnancy biometrics", "preg biometrics"], ["Shock punishment", "shock punishment"], ["Dildo gag", "dildo gag"], ["Ball gag", "ball gag"], ["Bit gag", "bit gag"], ["Neck corset", "neck corset"], ] if (V.seeAge !== 0) harsh.appendChild(["Cruel retirement counter", "cruel retirement counter"]) if (V.toysBoughtGags === 1) harsh.appendChild(["Massive dildo gag", "massive dildo gag"]) hcollars.forEach(pair => harsh.appendChild(...pair)) this.selectValue(V.currentRule.set.collar) this.onchange = (label, value) => V.currentRule.set.collar = value } } class ShoeList extends List { constructor() { super("Shoes") setup.shoes.forEach(shoes => this.appendChild(new ListItem(shoes))) this.selectValue(V.currentRule.set.shoes) this.onchange = (label, value) => V.currentRule.set.shoes = value } } class CorsetList extends List { constructor() { super("Corsetage") const bellies = [] setup.bellyAccessories.forEach(acc => { if (acc.fs === undefined && acc.rs === undefined) bellies.push([acc.name, acc.value]) else if (acc.fs === "repopulation" && V.arcologies[0].FSRepopulationFocus !== "unset") bellies.push([acc.name + " (FS)", acc.value]) else if (acc.rs === "boughtBelly" && V.clothesBoughtBelly === 1) bellies.push([acc.name + " (Purchased)", acc.value]) }) bellies.forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.bellyAccessory) this.onchange = (label, value) => V.currentRule.set.bellyAccessory } } class VagAccVirginsList extends List { constructor() { super("Vaginal accessories for virgins") const accs = [] setup.vaginalAccessories.forEach(acc => { if (acc.fs === undefined && acc.rs === undefined) accs.push([acc.name, acc.value]) else if (acc.rs === "buyBigDildos" && V.toysBoughtDildos === 1) accs.push([acc.name + " (Purchased)", acc.value]) }) accs.forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.virginAccessory) this.onchange = (label, value) => V.currentRule.set.virginAccessory = value } } class VagAccAVirginsList extends List { constructor() { super("Vaginal accessories for anal virgins") const accs = [] setup.vaginalAccessories.forEach(acc => { if (acc.fs === undefined && acc.rs === undefined) accs.push([acc.name, acc.value]) else if (acc.rs === "buyBigDildos" && V.toysBoughtDildos === 1) accs.push([acc.name + " (Purchased)", acc.value]) }) accs.forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.aVirginAccessory) this.onchange = (label, value) => V.currentRule.set.aVirginAccessory = value } } class VagAccOtherList extends List { constructor() { super("Vaginal accessories for other slaves") const accs = [] setup.vaginalAccessories.forEach(acc => { if (acc.fs === undefined && acc.rs === undefined) accs.push([acc.name, acc.value]) else if (acc.rs === "buyBigDildos" && V.toysBoughtDildos === 1) accs.push([acc.name + " (Purchased)", acc.value]) }) accs.forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.vaginalAccessory) this.onchange = (label, value) => V.currentRule.set.vaginalAccessory = value } } class DickAccVirginsList extends List { constructor() { super("Dick accessories for anal virgins") setup.dickAccessories.forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.aVirginDickAccessory) this.onchange = (label, value) => V.currentRule.set.aVirginDickAccessory = value } } class DickAccOtherList extends List { constructor() { super("Dick accessories for other slaves") setup.dickAccessories.forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.dickAccessory) this.onchange = (label, value) => V.currentRule.set.dickAccessory = value } } class ButtplugsVirginsList extends List { constructor() { super("Buttplugs for anal virgins") const accs = [] setup.buttplugs.forEach(acc => { if (acc.fs === undefined && acc.rs === undefined) accs.push([acc.name, acc.value]) else if (acc.rs === "buyBigPlugs" && V.toysBoughtButtPlugs === 1) accs.push([acc.name + " (Purchased)", acc.value]) }) accs.forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.aVirginButtplug) this.onchange = (label, value) => V.currentRule.set.aVirginButtplug = value } } class ButtplugsOtherList extends List { constructor() { super("Buttplugs for other slaves") const accs = [] setup.buttplugs.forEach(acc => { if (acc.fs === undefined && acc.rs === undefined) accs.push([acc.name, acc.value]) else if (acc.rs === "buyBigPlugs" && V.toysBoughtButtPlugs === 1) accs.push([acc.name + " (Purchased)", acc.value]) }) accs.forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.buttplug) this.onchange = (label, value) => V.currentRule.set.buttplug = value } } class ImplantVolumeList extends List { constructor() { super("Belly implant target volume (if present)") const pairs = [ ["No changes", -1], ["Empty implant", 0], ["Early pregnancy", 1500], ["Second trimester pregnancy", 5000], ["Full-term pregnancy", 15000], ["Full-term with twins", 30000], ["Full-term with triplets", 45000], ["Full-term with quadruplets", 60000], ["Full-term with quintuplets", 75000], ["Full-term with sextuplets", 90000], ["Full-term with septuplets", 105000], ["Full-term with octuplets", 120000] ] pairs.forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.bellyImplantVol) this.onchange = (label, value) => V.currentRule.set.bellyImplantVol = value } } class AutosurgerySwitch extends List { constructor() { super("Assistant-applied implants (Autosurgery global switch)") this.appendChild(new ListItem("Activate", "ACTIVE, STAND CLEAR", 1)) this.appendChild(new ListItem("Off", "off", 0)) this.selectValue(V.currentRule.set.autoSurgery) this.onchange = (label, value) => V.currentRule.set.autoSurgery = value } } class GrowthList extends Options { constructor() { super() this.sublists = [] const pairs = [ ["No default setting", () => this.nds()], ["Girlish figure", () => this.girlish()], ["Stacked figure", () => this.stacked()], ["Huge but functional", () => this.huge()], ["Unlimited", () => this.unlimited()], ["None", () => this.none()] ] pairs.forEach(pair => this.appendChild(new OptionsItem(...pair))) this.breasts = new BreastGrowthList() this.butts = new ButtGrowthList() this.lips = new LipGrowthList() this.sublists.push(this.breasts, this.butts, this.lips) if (V.seeDicks > 0 || V.makeDicks > 0) { this.dicks = new DickGrowthList() this.balls = new BallGrowthList() this.sublists.push(this.dicks, this.balls) } this.sublists.forEach(i => this.appendChild(i)) } render() { const elem = document.createElement("div") const span = document.createElement("span") span.innerHTML = "Growth hormone regimes for healthy slaves:" elem.appendChild(span) return elem } nds() { [this.breasts, this.butts, this.lips, this.dicks, this.balls].forEach(i => { i.setValue("no default change") i.propagateChange() }) } girlish() { this.breasts.setValue(350) this.butts.setValue(2) this.lips.setValue(25) if (this.dicks) this.dicks.setValue(0) if (this.balls) this.balls.setValue(0) this.sublists.forEach(i => i.propagateChange()) } stacked() { this.breasts.setValue(1000) this.butts.setValue(4) this.lips.setValue(25) if (this.dicks) this.dicks.setValue(4) if (this.balls) this.balls.setValue(4) this.sublists.forEach(i => i.propagateChange()) } huge() { this.breasts.setValue(9000) this.butts.setValue(10) this.lips.setValue(45) if (this.dicks) this.dicks.setValue(6) if (this.balls) this.balls.setValue(6) this.sublists.forEach(i => i.propagateChange()) } unlimited() { this.breasts.setValue(48000) this.butts.setValue(10) this.lips.setValue(100) if (this.dicks) this.dicks.setValue(10) if (this.balls) this.balls.setValue(6) this.sublists.forEach(i => i.propagateChange()) } none() { this.sublists.forEach(i => { i.setValue(0) i.propagateChange() }) } } class BreastGrowthList extends List { constructor() { super("Breasts", true) [ ["No default setting", "no default setting"], ["B Cup", 350], ["D Cup", 1000], ["Monstrous", 9000], ["Unlimited", 48000], ["None", 0] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.setValue(V.currentRule.set.growth_boobs) this.onchange = (label, value) => V.currentRule.set.growth_boobs = value } } class ButtGrowthList extends List { constructor() { super("Butts", true) [ ["No default setting", "no default setting"], ["Cute", 2], ["Big", 4], ["Huge", 6], ["Unlimited", 10], ["None", 0] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.setValue(V.currentRule.set.growth_butt) this.onchange = (label, value) => V.currentRule.set.growth_butt = value } } class LipGrowthList extends List { constructor() { super("Lips", true) [ ["No default setting", "no default setting"], ["Plump", 25], ["Beestung", 45], ["Facepussy", 100], ["None", 0] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.setValue(V.currentRule.set.growth_lips) this.onchange = (label, value) => V.currentRule.set.growth_lips = value } } class DickGrowthList extends List { constructor() { super("Dicks, if present", true) [ ["No default setting", "no default setting"], ["Above average", 4], ["Pornstar", 6], ["Unlimited", 10], ["None", 0] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.setValue(V.currentRule.set.growth_dick) this.onchange = (label, value) => V.currentRule.set.growth_dick = value } } class BallGrowthList extends List { constructor() { super("Balls, if present", true) [ ["No default setting", "no default setting"], ["Sizeable", 4], ["Cumslave", 6], ["Unlimited", 10], ["None", 0] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.setValue(V.currentRule.set.growth_balls) this.onchange = (label, value) => V.currentRule.set.growth_balls = value } } class CurrativesList extends List { constructor() { super("Health drugs") [ ["No default setting", "no default setting"], ["None", "none", 0], ["Preventatives", "preventatives", 1], ["Curatives", "curatives", 2] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.curatives) this.onchange = (label, value) => V.currentRule.set.curatives = value } } class AphrodisiacList extends List { constructor() { super("Aphrodisiacs") [ ["No default setting", "no default setting"], ["None", "none", 0], ["Standard", "standard", 1], ["Extreme", "extreme", 2], ["Anaphrodisiacs", "anaphrodisiacs", -1] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.aphrodisiacs) this.onchange = (label, value) => V.currentRule.set.aphrodisiacs = value } } class ContraceptiveList extends List { constructor() { super("Contraceptives for fertile slaves") const drugs = [ ["No default setting", "no default setting"], ["Contraceptives", "contraceptives", -1] ["Fertile", "fertile", 0], ["Very fertile", "very fertile", 1], ["Extremely fertile", "extremely fertile", 2], ] if (V.seeHyperPreg === 1 && V.superFertilityDrugs === 1) { drugs.push(["Hyper fertile", "hyper fertile", 3]) drugs.push(["Maximize fertility", "maximize fertility", 4]) } drugs.forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.preg) this.onchange = (label, value) => V.currentRule.set.preg = value } } class PregDrugsList extends List { constructor() { super("Pregnancy control agents for pregnant slaves") [ ["No changes", "no changes", "no default setting"], ["None", "none"], ["Fast gestation", "fast gestation", "fast"], ["Slow gestation", "slow gestation", "slow"], ["Birth supressors", "birth supressors", "suppress"], ["Birth stimulators", "birth stimulators", "stimulate"] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.pregSpeed) this.onchange = (label, value) => V.currentRule.set.pregSpeed = value } } class FemaleHormonesList extends List { constructor() { super("Hormones for female slaves") [ ["No default setting", "no default setting"], ["Intensive Female", "intensive female", 2], ["Female", "female", 1], ["None", "none", 0], ["Male", "male", -1], ["Intensive Male", "intensive male", -2] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.XX) this.onchange = (label, value) => V.currentRule.set.XX = value } } class GeldingHormonesList extends List { constructor() { super("Hormones for geldings") [ ["No default setting", "no default setting"], ["Intensive Female", "intensive female", 2], ["Female", "female", 1], ["None", "none", 0], ["Male", "male", -1], ["Intensive Male", "intensive male", -2] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.gelding) this.onchange = (label, value) => V.currentRule.set.gelding = value } } class ShemaleHormonesList extends List { constructor() { super("Hormones for shemales") [ ["No default setting", "no default setting"], ["Intensive Female", "intensive female", 2], ["Female", "female", 1], ["None", "none", 0], ["Male", "male", -1], ["Intensive Male", "intensive male", -2] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.XY) this.onchange = (label, value) => V.currentRule.set.XY = value } } class OtherDrugsList extends List { constructor() { super("Other drugs (Will be overriden by hormones and other drugs where applicable)") const drugs = [] setup.drugs.forEach(drug => { if (drug.fs === undefined && drug.rs === undefined) drugs.push([drug.name, drug.value]) else if (drug.rs === "growth" && V.growthStim === 1) drugs.push([drug.name + " (Research)", drug.value]) else if (drug.rs === "pubHorm" && V.precociousPuberty === 1 && V.pubertyHormones === 1) drugs.push([drug.name + " (Research)", drug.value]) else if (drug.rs === "nosag" && V.purchasedSagBGone === 1) drugs.push([drug.name + " (Product)", drug.value]) else if (drug.fs === "slimness" && V.arcologies[0].FSSlimnessEnthusiastResearch === 1) drugs.push([drug.name + " (FS)", drug.value]) else if (drug.fs === "youth" && V.arcologies[0].FSYouthPreferentialistResearch === 1) drugs.push([drug.name + " (FS)", drug.value]) }) this.selectValue(V.currentRule.set.drug) this.onchange = (label, value) => V.currentRule.set.drug = value } } class DietList extends List { constructor() { super("Slave diets") const diets = [ ["no default setting", "no default setting"], ["Fix fat and skinny slaves", "fix fat and skinny slaves", "attractive"], ["Curvy", "curvy", 30], ["Average", "average", 0], ["Thin", "thin", -30] ] if (V.feeder === 1) { diets.push( ["Feminine", "feminine", "XX"], ["Masculine", "masculine", "XY"] ) if (V.dietXXY === 1) diets.push(["Futanari", "futanari", "XXY"]) } if (V.dietCleanse === 1) diets.push(["Cleansing", "promote health", "cleansing"]) if (V.dietFertility === 1) diets.push(["Feritlity", "promote fertility", "fertility"]) if (V.cumProDiet === 1) diets.push(["Cum production", "promote cum production", "cum production"]) diets.forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.diet) this.onchange = (label, value) => V.currentRule.set.diet = value } } class DietGrowthList extends List { constructor() { super("Diet support for growth drugs") [ ["On", "On", 1], ["Off", "Off", 0] ].forEach(i => this.appendChild(new ListItem(...i))) this.selectValue(V.currentRule.set.dietGrowthSupport) this.onchange = (label, value) => V.currentRule.set.dietGrowthSupport = value } } class DietBaseList extends List { constructor() { super("Diet base") // TODO: better data structure? [ ["No default setting", "No default setting", {cum: "no default setting", milk: "no default setting"}], ["Normal Diet", "Normal Diet", {cum: 0, milk: 0}], ["Cum Added", "Cum Added", {cum: 1, milk: 0}], ["Milk Added", "Milk Added", {cum: 0, milk: 1}], ["Cum & Milk Added", "Cum & Milk Added", {cum: 1, milk: 1}], ["Cum-Based", "Cum-Based", {cum: 2, milk: 0}] ["Milk-Based", "Milk-Based", {cum: 0, milk: 2}] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue({cum: V.currentRule.set.dietCum, milk: V.currentRule.set.dietMilk}) this.onchange = (label, value) => { V.currentRule.set.dietCum = value.cum V.currentRule.set.dietMilk = value.milk } } } class MuscleList extends List { constructor() { super("Muscles", true) [ ["No default setting", "no default setting"], ["None", "None", 0], ["Toned", "Toned", 20], ["Ripped", "Ripped", 50], ["Massive", "Massive", 100], ["Weak", "Weak", -20] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.setValue(V.currentRule.set.muscles) this.onchange = (label, value) => V.currentRule.set.muscles = value } } class BraceList extends List { constructor() { super("Braces") [ ["No default setting", "no default setting"], ["None", "none"], ["Straighten", "straighten"], ["Universal", "universal"] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.teeth) this.onchange = (label, value) => V.currentRule.set.teeth = value } } class LivingStandardList extends List { constructor() { super("Living standard") [ ["No default setting", "no default setting"], ["Luxurious", "luxurious"], ["Normal", "normal"], ["Spare", "spare"] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.livingRules) this.onchange = (label, value) => V.currentRule.set.livingRules = value } } class PunishmentList extends List { constructor() { super("Typical punishment") [ ["No default setting", "no default setting"], ["Confinement", "confinement"], ["Whipping", "whipping"], ["Chastity", "chastity"], ["Situational", "situational"] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.standardPunishment) this.onchange = (label, value) => V.currentRule.set.standardPunishment = value } } class RewardList extends List { constructor() { super("Typical reward") [ ["No default setting", "no default setting"], ["Relaxation", "relaxation"], ["Drugs", "drugs"], ["Orgasm", "orgasm"], ["Situational", "situational"] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.standardReward) this.onchange = (label, value) => V.currentRule.set.standardReward = value } } class ReleaseList extends List { constructor() { super("Release rules") [ ["No default setting", "no default setting"], ["Permissive", "permissive"], ["Sapphic", "sapphic"], ["Masturbation", "masturbation"], ["Restritive", "restrictive"] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.releaseRules) this.onchange = (label, value) => V.currentRule.set.releaseRules = value } } class SmartFetishList extends List { constructor() { super("Smart piercing fetish target") [ ["No default setting", "no default setting"], ["Vanilla", "vanilla"], ["Oral", "oral"], ["Anal", "anal"], ["Boobs", "boobs"], ["Sub", "submissive"], ["Dom", "dom"], ["Humiliation", "humiliation"], ["Preg", "pregnancy"], ["Pain", "masochist"], ["Sadism", "sadist"] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.clitSetting) this.onchange = (label, value) => V.currentRule.set.clitSetting = value } } class SmartXYAttractionList extends List { constructor() { super("Smart piercing XY attraction target") [ ["No default setting", "no default setting"], ["Passionate", "passionate", 100], ["Attracted", "attracted", 75], ["Indifferent", "indifferent", 45], ["None", "none", 0] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.clitSettingXY) this.onchange = (label, value) => V.currentRule.set.clitSettingXY = value } } class SmartXXAttractionList extends List { constructor() { super("Smart piercing XX attraction target") [ ["No default setting", "no default setting"], ["Passionate", "passionate", 100], ["Attracted", "attracted", 75], ["Indifferent", "indifferent", 45], ["None", "none", 0] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.clitSettingXX) this.onchange = (label, value) => V.currentRule.set.clitSettingXX = value } } class SmartEnergyList extends List { constructor() { super("Smart piercing sex drive target") [ ["Nympho", "nympho", 100], ["Sex Addict", "sex addict", 85], ["Powerful", "powerful", 65], ["Healthy", "healthy", 45], ["Weak", "weak", 25], ["Frigid", "frigid", 0] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.clitSettingEnergy) this.onchange = (label, value) => V.currentRule.set.clitSettingEnergy = value } } class SpeechList extends List { constructor() { super("Speech rules") [ ["No default setting", "no default setting"], ["Permissive", "permissive"], ["Suppress accents", "accent elimination"], ["Restrictive", "restrictive"] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set) this.onchange = (label,value) => V.currentRule.set = value } } class RelationshipList extends List { constructor() { super("Relationship rules") [ ["No default setting", "no default setting"], ["Permissive", "permissive"], ["Just friends", "just friends"], ["Restrictive", "restrictive"] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set) this.onchange = (label,value) => V.currentRule.set = value } } class PornList extends List { constructor() { super("Weekly porn publicity subsidy") [ ["No default setting", "no default setting"], ["No broadcasting", "no broadcasting", -1], ["No subsidy", "no subsidy", 0], ["1000", "1000", 1000], ["2000", "2000", 2000], ["3000", "3000", 3000], ["4000", "4000", 4000], ["5000", "5000", 5000] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.pornFameSpending) this.onchange = (label,value) => V.currentRule.set.pornFameSpending = value } } class CosmeticSection extends List { constructor() { this.appendChild(EyewearList) this.appendChild(LensesList) this.appendChild(MakeupList) this.appendChild(NailsList) this.appendChild(HairLengthList) this.appendChild(HairColourList) this.appendChild(HairStyleList) this.appendChild(PubicHairColourList) this.appendChild(PubicHairStyleList) this.appendChild(ArmpitHairColourList) this.appendChild(ArmpitHairStyleList) } } class EyewearList extends List { constructor() { super("Eyewear") [ ["no default setting"], ["correct with contacts"], ["universal glasses"], ["blur with glasses"], ["blur with contacts"] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.eyewear) this.onchange = (label, value) => V.currentRule.set.eyewear = value } } class LensesList extends Element { constructor() { super(V.currentRule.set.eyeColor) this.appendChild(new OptionsItem("No default Setting", () => this.setValue("no default setting"))) this.colourlist = new LensesColourList() this.shapelist = new LensesShapeList() this.appendChild(this.colourlist) this.appendChild(this.shapelist) } render(color) { const elem = document.createElement("div") elem.innerHTML = "Eye coloring: " this.label = document.createElement("strong") this.label.innerText = coloring elem.appendChild(this.label) } combine() { const lst = [] if (this.colourlist.value !== "no default setting") lst.appendChild(this.colourlist.value) if (this.shapelist.value !== "no default setting") list.appendChild(this.shapelist.value) if (lst.length === 0) return "no default value" else return lst.join(" ") } set_value() { const tmp = this.combine() this.label.innerText = tmp V.currentRule.set.eyeColor = tmp } } class LensesColourList extends Options { constructor() { super("Color:") [ ["no default setting"] ["blue"], ["black"], ["brown"], ["green"], ["turquoise"], ["sky-blue"], ["hazel"], ["pale-grey"], ["white"], ["pink"], ["amber"], ["red"] ].forEach(i => this.appendChild(new OptionsItem(i, item => { this.value = item.label this.parent.set_value() }))) } } class LensesShapeList extends Options { constructor() { super("Shape:") [ ["no default setting"], ["catlike"], ["serpent-like"], ["devilish"], ["demonic"], ["hypnotic"], ["heart-shaped"], ["wide-eyed"], ["almond-shaped"], ["bright"], ["teary"], ["vacant"] ].forEach(i => this.appendChild(new OptionsItem(i, item => { this.value = item.label this.parent.set_value() }))) } } class MakeupList extends List { constructor() { super("Makeup") [ ["no default setting"], ["makeup-free", "makeup-free", 0], ["nice", "nice", 1], ["gorgeous", "gorgeous", 2], ["color-coordinate with hair", "color-coordinate with hair", 3], ["slutty", "slutty", 4] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.makeup) this.onchange = (label, value) => V.currentRule.set.makeup = value } } class NailsList extends List { constructor() { super("Nails") [ ["no default setting"], ["clipped", "clipped", 0], ["extended", "extended", 1], ["color-coordinate with hair", "color-coordinate with hair", 2], ["sharp and claw-like", "sharp and claw-like", 3], ["bright and glittery", "bright and glittery", 4], ["hooker nails", "hooker nails", 5] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.nails) this.onchange = (label, value) => V.currentRule.set.nails = value } } class HairLengthList extends List { constructor() { super("Hair length") [ ["no default setting"], ["very short", "very short", 5], ["short", "short", 10], ["shoulder length", "shoulder length", 30], ["long", "long", 60], ["very long", "very long", 100], ["floor length", "floor length", 150] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.hLength) this.onchange = (label, value) => V.currentRule.set.hLength = value } } class HairColourList extends List { constructor() { super("Hair color") [ ["no default setting"], ["blonde"], ["golden"], ["platinum blonde"], ["strawbery-blonde"], ["copper"], ["ginger"], ["red"] ["green"], ["blue"], ["pink"], ["dark brown"], ["brown"], ["auburn"], ["burgundy"], ["chocolate"], ["chestnut"], ["hazel"], ["black"], ["grey"], ["silver"], ["white"], ["blazing red"], ["neon green"], ["neon blue"], ["neon pink"] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.hColor) this.onchange = (label, value) => V.currentRule.set.hColor = value } } class HairStyleList extends List { constructor() { super("Hair style") [ ["no default setting"], ["neat"], ["shaved"], ["trimmed"], ["buzzcut"], ["up"], ["ponytail"], ["bun"], ["curled"], ["permed"], ["luxurious"], ["dreadlocks"], ["cornrows"], ["braided"], ["tails"], ["afro"], ["strip"] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.hStyle) this.onchange = (label, value) => V.currentRule.set.hStyle = value } } class PubicHairColourList extends List { constructor() { super("Pubic hair color, when present") [ ["no default setting"], ["blonde"], ["golden"], ["platinum blonde"], ["strawerry-blonde"], ["copper"], ["ginger"], ["red"], ["green"], ["blue"], ["pink"], ["dark brown"], ["brown"], ["auburn"], ["burgundy"], ["chocolate"], ["chestnut"], ["hazel"], ["black"], ["grey"], ["silver"], ["white"], ["blazing red"], ["neon green"], ["neon blue"], ["neon pink"] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.pubicHColor) this.onchange = (label, value) => V.currentRule.set.pubicHColor = value } } class PubicHairStyleList extends List { constructor() { super("Pubic hairstyle") [ ["no default setting"], ["waxed"], ["in a strip"], ["neat"], ["bushy"], ["bushy in the front and neat in the rear"], ["very bushy"] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.pubicHStyle) this.onchange = (label, value) => V.currentRule.set.pubicHStyle = value } } class ArmpitHairColourList extends List { constructor() { super("Underarm hair color, when present") [ ["no default setting"], ["blonde"], ["golden"], ["platinum blonde"], ["strawberry-blonde"], ["copper"], ["ginger"], ["red"], ["green"], ["blue"], ["pink"], ["dark brown"], ["brown"], ["auburn"], ["burgundry"], ["chocolate"], ["chestnut"], ["hazel"], ["black"], ["grey"], ["silver"], ["white"] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.underArmHColor) this.onchange = (label, value) => V.currentRule.set.underArmHColor = value } } class ArmpitHairStyleList extends List { constructor() { super("Underarm hair style") [ ["no default setting"], ["waxed"], ["shaved"], ["neat"], ["bushy"] ].forEach(pair => this.appendChild(new ListItem(...pair))) this.selectValue(V.currentRule.set.underArmHStyle) this.onchange = (label, value) => V.currentRule.set.underArmHStyle = value } } })()