diff --git a/devTools/FC.d.ts b/devTools/FC.d.ts index abc179ce417d94675542045bb8b6d52c0cc05446..c1ffd2605ddeb79957033c4a4ddf9f1c835dd0b0 100644 --- a/devTools/FC.d.ts +++ b/devTools/FC.d.ts @@ -35,6 +35,32 @@ declare namespace App { noun: string; } } + + namespace SlaveSummary{ + class SmartPiercing{ + setting: { + off: string, + submissive: string, + lesbian: string, + oral: string, + humiliation: string, + anal: string, + boobs: string, + sadist: string, + masochist: string, + dom: string, + pregnancy: string, + vanilla: string, + all: string, + none: string, + monitoring: string, + men: string, + women: string, + "anti-men": string, + "anti-women": string, + } + } + } } namespace Debug {} @@ -254,8 +280,28 @@ declare namespace App { } namespace View { } namespace SlaveSummary { - type StringRenderer = (slave: App.Entity.SlaveState) => String; type AppendRenderer = (slave: App.Entity.SlaveState, parentNode: Node) => void; + + class AbbreviationState { + clothes: number; + devotion: number; + diet: number; + drugs: number; + genitalia: number; + health: number; + hormoneBalance: number; + mental: number; + nationality: number; + origins: number; + physicals: number; + race: number; + rules: number; + rulesets: number; + skills: number; + } + class State { + abbreviation: AbbreviationState; + } } } diff --git a/js/002-config/fc-js-init.js b/js/002-config/fc-js-init.js index 6ee8fcd98120639ab35fa353a5727ed02858bd4e..5eff87da0a2f291b10f185220944887ec5494106 100644 --- a/js/002-config/fc-js-init.js +++ b/js/002-config/fc-js-init.js @@ -17,7 +17,7 @@ App.Arcology.Cell = {}, App.Art = {}; App.Corporate = {}; App.Data = {}; -App.Data.HeroSlaves = { }; +App.Data.HeroSlaves = {}; App.Data.Weather = {}; App.Debug = {}; App.Desc = {}; diff --git a/js/003-data/gameVariableData.js b/js/003-data/gameVariableData.js index 27885b3ef3a8ee399e4eb6d95abd487c30f0c0ed..78cbf91463f9fba2beaed2495424a90d62342a03 100644 --- a/js/003-data/gameVariableData.js +++ b/js/003-data/gameVariableData.js @@ -34,24 +34,30 @@ App.Data.defaultGameStateVariables = { cashLastWeek: 0, // UI content + UI: { + slaveSummary: { + abbreviation: { + clothes: 2, + devotion: 2, + diet: 2, + drugs: 2, + genitalia: 2, + health: 2, + mental: 2, + nationality: 2, + origins: 2, + physicals: 2, + race: 2, + rules: 2, + rulesets: 2, + skills: 2, + } + } + }, FSNamePref: 0, HGFormality: 1, HGSeverity: 0, - abbreviateClothes: 2, - abbreviateDevotion: 2, - abbreviateDiet: 2, - abbreviateDrugs: 2, - abbreviateGenitalia: 2, - abbreviateHealth: 2, - abbreviateMental: 2, - abbreviateNationality: 2, - abbreviateOrigins: 2, - abbreviatePhysicals: 2, - abbreviateRace: 2, - abbreviateRules: 2, - abbreviateRulesets: 2, abbreviateSidebar: 2, - abbreviateSkills: 2, adamPrinciple: 0, allowFamilyTitles: 0, allowMaleSlaveNames: false, @@ -1385,7 +1391,6 @@ App.Data.resetOnNGPlus = { compact: 1, Cash: 1, Upkeep: 1, SexSlaveCount: 1, roomPop: 1, Rep: 1, GSP: 1, Authority: 1, Security: 1, Crime: 1, confirmWeekEnd: 0, }, DefaultBirthDestination: "individually decided fates", - abbreviateHormoneBalance: 2, legendaryFacility: 0, heroSlavesPurchased : [], fcnn: [ diff --git a/js/003-data/slaveSummaryData.js b/js/003-data/slaveSummaryData.js new file mode 100644 index 0000000000000000000000000000000000000000..4e2a4f5ab0c4d580823b324aa459dc564a1af5cc --- /dev/null +++ b/js/003-data/slaveSummaryData.js @@ -0,0 +1,1404 @@ +// these ratings tables are consumed by App.UI.SlaveSummaryImpl.helpers. getNumericRating() +// this function takes a value for rating and iterates a table (in the declaration order) +// until it finds a key greater or equal to the value; the found record is returned from the function +// Briefly, each dictionary entry key -> value is read as "the highest rating that still suits -> value" or +// "up to, including" +// The idea behind this is too decrease number of comparisons and retain compatibility with simple dictionaries +// without sparse keys +App.Data.SlaveSummary = { + long: { + body: { + age: { + 17: "Underage.", + 18: "Eighteen.", + 19: "Nineteen.", + 24: "Early twenties.", + 29: "Late twenties.", + 34: "Early thirties.", + 39: "Late thirties.", + 999: "Forties." + }, + face: { // face value + 100 + 4: {desc: "Very ugly", style: "red"}, + 59: {desc: "Ugly", style: "red"}, + 89: {desc: "Unattractive", style: "red"}, + 110: {desc: "Average"}, + 140: {desc: "Attractive", style: "pink"}, + 195: {desc: "Beautiful", style: "pink"}, + 200: {desc: "Very beautiful", style: "pink"}, + }, + lips: { + 10: {desc: "Thin lips", style: "red"}, + 20: {desc: "Normal lips"}, + 40: {desc: "Pretty lips"}, + 70: {desc: "Big lips"}, + 95: {desc: "Huge lips"}, + 100: {desc: "Facepussy"} + }, + teeth: { + "crooked": {desc: "Crooked teeth.", style: "yellow"}, + "gapped": {desc: "Tooth gap.", style: "yellow"}, + "cosmetic braces": {desc: "Cosmetic braces."}, + "straightening braces": {desc: "Braces."}, + "removable": {desc: "Removable teeth."}, + "pointy": {desc: "Sharp fangs."}, + "baby": {desc: "Baby teeth."}, + "mixed": {desc: "Mixed teeth."} + }, + waist: { // waist value + 100 + 4: {desc: "Absurdly narrow waist", style: "pink"}, + 60: {desc: "Hourglass waist", style: "pink"}, + 89: {desc: "Feminine waist", style: "pink"}, + 110: {desc: "Average waist"}, + 140: {desc: "Unattractive waist", style: "red"}, + 195: {desc: "Ugly waist", style: "red"}, + 200: {desc: "Masculine waist", style: "red"} + }, + genitalia: { + dickBalls: { // indices [dick, balls] + 3: { + 3: null, + 4: "Big balls.", + 5: "Huge balls.", + 8: "Monstrous balls.", + 99: "Hyper balls." + }, + 4: { + 3: "Big dick.", + 99: "Big dick & balls." + }, + 5: { + 4: "Huge dick.", + 99: "Huge dick & balls." + }, + 8: { + 5: "Monster dong.", + 99: "Monster dick & balls." + }, + 99: { + 8: "Hyper dong.", + 99: "Hyper dick & balls." + } + }, + holes: { // indices [vagina, anus] + 2: { + 2: null, + 3: "Gaping anus.", + 4: "Permagaped anus." + }, + 3: { + 2: "Loose pussy.", + 3: "High mileage." + }, + 4: { + 3: "Cavernous pussy.", + 4: "Blown out holes." + } + } + }, + titsAss: { // indices: [boobs, butt, FSAssetExpansionist(0,1), weight+100, muscles+100] + 499: { + 2: { + 2: { // FSAssetExpansionist doesn't matter + 109: { + 130: {desc: "Girlish figure.", style: "pink"}, + }, + }, + } + }, + 799: { + 4: null, + 6: {desc: "Big ass.", style: "pink"}, + 8: {desc: "Huge ass.", style: "pink"}, + 9: {desc: "Titanic ass.", style: "pink"}, + 999: {desc: "Hyper ass.", style: "pink"}, + }, + 1999: { + 4: {desc: "Big tits.", style: "pink"}, + 999: {desc: "Big T&A.", style: "pink"} + }, + 3999: { + 6: {desc: "Huge tits.", style: "pink"}, + 999: {desc: "Huge T&A.", style: "pink"} + }, + 11999: { + 8: {desc: "Monstrous tits.", style: "pink"}, + 999: {desc: "Enormous T&A.", style: "pink"}, + }, + 100000: { + 9: {desc: "Immobilizing tits.", style: "pink"}, + 999: {desc: "Hyper T&A.", style: "pink"} + } + }, + weight: { // indices: [weigh + 100, FSHedonisticDecadence (0,1), hips + 2, ] + 4: {desc: "Emaciated", style: "red"}, + 69: { + 2: { // FSHedonisticDecadence doesn't matter + 0: {desc: "Model-thin"}, + 5: {desc: "Very thin", style: "red"} + } + }, + 89: {desc: "Thin"}, + 110: {desc: "Trim"}, + 130: {desc: "Plush"}, + 195: { + 0: {desc: "Overweight", style: "red"}, + 1: { + 3: {desc: "Overweight", style: "red"}, + 5: {desc: "Nicely chubby"} + } + }, + 230: { + 0: {desc: "Fat", style: "red"}, + 1: { + 4: {desc: "Fat", style: "red"}, + 5: {desc: "Pleasantly soft and shapely"} + } + }, + 260: { + 0: {desc: "Obese", style: "red"}, + 1: {desc: "Amazingly voluptuous"} + }, + 290: { + 0: {desc: "Super Obese", style: "red"}, + 1: {desc: "SSBBW"} + }, + 999: { + 0: {desc: "Dangerously Obese", style: "red"}, + 1: {desc: "Perfectly massive"} + } + }, + hipsAss: { + 0: {desc: "Disproportionately small butt.", style: "red"}, + 1: {desc: "Disproportionately big butt.", style: "red"} + }, + muscles: { // indices: [muscles + 100, FSPhysicalIdealist(0,1) ] + 4: {desc:"Frail", style:"red"}, + 69: { + 0: {desc: "Very weak"}, + 1: {desc: "Very weak", style: "red"} + }, + 94: { + 0: {desc: "Weak"}, + 1: {desc: "Weak", style: "red"} + }, + 105: {desc: "Soft"}, + 130: {desc: "Toned"}, + 150: {desc: "Fit"}, + 195: {desc: "Muscular"}, + 100: {desc: "Hugely muscular"} + } + }, + mental: { + devotion: { // devotion value + 100 + 4: {desc: "Very hateful", style: ["devotion", "hateful"]}, + 49: {desc: "Hateful", style: ["devotion", "hateful"]}, + 79: {desc: "Resistant", style: ["devotion", "resistant"]}, + 120: {desc: "Ambivalent", style: ["devotion", "ambivalent"]}, + 150: {desc: "Accepting", style: ["devotion", "accept"]}, + 195: {desc: "Devoted", style: ["devotion", "devoted"]}, + 200: {desc: "Worshipful", style: ["devotion", "worship"]} + }, + trust: { // first key: trust + 100, second key: devotion + 100 + 4: {desc: "Extremely terrified", style: ["trust", "extremely-terrified"]}, + 49: {desc: "Terrified", style: ["trust", "terrified"]}, + 79: {desc: "Frightened", style: ["trust", "frightened"]}, + 120: {desc: "Fearful", style: ["trust", "fearful"]}, + 150: { + 79: {desc: "Careful", style: ["defiant", "careful"]}, + 200: {desc: "Careful", style: ["trust", "careful"]}, + }, + 195: { + 79: {desc: "Bold", style: ["defiant", "bold"]}, + 200: {desc: "Trusting", style: ["trust", "trusting"]}, + }, + 200: { + 79: {desc: "Defiant", style: ["defiant", "full"]}, + 200: {desc: "Profoundly trusting", style: ["trust", "prof-trusting"]}, + } + }, + education: { // index: intelligenceImplant + 15 + 0: ", hindered", + 29: "", + 44: ", educated", + 99: ", well educated" + }, + intelligence: { // index: intelligence + 100 + 4: {desc: "Moronic", style: "orangered"}, + 49: {desc: "Very slow", style: "orangered"}, + 84: {desc: "Slow", style: "orangered"}, + 115: {desc: "Average intelligence"}, + 150: {desc: "Smart", style: "deepskyblue"}, + 195: {desc: "Very smart", style: "deepskyblue"}, + 230: {desc: "Brilliant", style: "deepskyblue"}, + 999: {desc: "Genius", style: "deepskyblue"}, + }, + behavioralFlaw: { + "arrogant": "Arrogant.", + "bitchy": "Bitchy.", + "odd": "Odd.", + "hates men": "Hates men.", + "hates women": "Hates women.", + "gluttonous": "Stress eater.", + "anorexic": "Anorexic", + "devout": "Devoutly religious.", + "liberated": "Mentally liberated.", + } + }, + fetish: { // indices [fetish, fetishStrength] + "submissive": { + 60: "Submissive tendencies", + 95: "Submissive", + 100: "Complete submissive" + }, + "cumslut": { + 60: "Prefers oral", + 95: "Oral fixation", + 100: "Cumslut" + }, + "humiliation": { + 60: "Interest in humiliation", + 95: "Exhibitionist", + 100: "Humiliation slut" + }, + "buttslut": { + 60: "Prefers anal", + 95: "Anal fixation", + 100: "Buttslut" + }, + "boobs": { + 60: "Loves boobs", + 95: "Breast fixation", + 100: "Boobslut" + }, + "sadist": { + 60: "Sadistic tendencies", + 95: "Sadist", + 100: "Complete sadist" + }, + "masochist": { + 60: "Masochistic tendencies", + 95: "Masochist", + 100: "Complete masochist" + }, + "dom": { + 60: "Dominant tendencies", + 95: "Dominant", + 100: "Complete dom" + }, + "pregnancy": { + 60: "Interest in impregnation", + 95: "Pregnancy kink", + 100: "Pregnancy fetish" + }, + "none": "Sexually vanilla" + }, + clothes: { + "Western clothing": "Chaps.", + "a Santa dress": "Santa dress.", + "a ball gown": "Ball gown.", + "a bimbo outfit": "Bimbo outfit.", + "a biyelgee costume": "Biyelgee costume.", + "a bra": "Nice bra.", + "a bunny outfit": "Bunny outfit.", + "a burkini": "Burkini.", + "a burqa": "Burqa.", + "a button-up shirt and panties": "Button-up shirt, panties.", + "a button-up shirt": "Nice button-up shirt.", + "a chattel habit": "Chattel habit.", + "a cheerleader outfit": "Cheerleader.", + "a comfortable bodysuit": "Bodysuit.", + "a courtesan dress": "Courtesan dress.", + "a cybersuit": "Cybersuit.", + "a dirndl": "Dirndl.", + "a fallen nuns habit": "Slutty habit.", + "a gothic lolita dress": "Gothic lolita dress.", + "a halter top dress": "Halter top dress.", + "a hanbok": "Hanbok.", + "a hijab and abaya": "Hijab and abaya.", + "a hijab and blouse": "Hijab and blouse.", + "a huipil": "Huipil.", + "a kimono": "Kimono.", + "a klan robe": "Klan robe.", + "a latex catsuit": "Nice latex.", + "a leotard": "Leotard.", + "a long qipao": "Long Qipao.", + "a maternity dress": "Maternity dress.", + "a military uniform": "Military uniform.", + "a mini dress": "Mini dress.", + "a monokini": "Monokini.", + "a mounty outfit": "Mounty outfit.", + "a nice maid outfit": "Nice maid.", + "a nice nurse outfit": "Nice nurse.", + "a nice pony outfit": "Nice pony outfit.", + "a niqab and abaya": "Niqab and abaya.", + "a one-piece swimsuit": "Swimsuit.", + "a penitent nuns habit": "Cilice.", + "a police uniform": "Police uniform.", + "a red army uniform": "Red Army uniform.", + "a scalemail bikini": "Scalemail bikini.", + "a schoolgirl outfit": "Schoolgirl outfit.", + "a schutzstaffel uniform": "Schutzstaffel uniform.", + "a skimpy loincloth": "Skimpy loincloth.", + "a slave gown": "Slave gown.", + "a slutty klan robe": "Slutty klan robe.", + "a slutty maid outfit": "Slutty maid.", + "a slutty nurse outfit": "Slutty nurse.", + "a slutty outfit": "Slutty outfit.", + "a slutty pony outfit": "Slutty pony outfit.", + "a slutty qipao": "Slutty qipao.", + "a slutty schutzstaffel uniform": "Slutty Schutzstaffel uniform.", + "a sports bra": "Sports bra.", + "a string bikini": "String bikini.", + "a striped bra": "Striped bra.", + "a succubus outfit": "Succubus outfit.", + "a sweater and cutoffs": "Jean shorts, sweater.", + "a sweater and panties": "Sweater, panties.", + "a sweater": "Nice sweater.", + "a t-shirt and jeans": "Blue jeans, t-shirt.", + "a t-shirt and panties": "Panties, t-shirt.", + "a t-shirt and thong": "Thong, t-shirt.", + "a t-shirt": "T-shirt.", + "a tank-top and panties": "Tank-top, panties.", + "a tank-top": "Nice tank-top.", + "a thong": "Nice thong.", + "a toga": "Toga.", + "a tube top and thong": "Tube top, thong.", + "a tube top": "Nice tube top.", + "an apron": "Apron.", + "an oversized t-shirt and boy shorts": "Over-sized t-shirt, boy shorts.", + "an oversized t-shirt": "Nice over-sized t-shirt.", + "attractive lingerie for a pregnant woman": "Preggo lingerie.", + "attractive lingerie": "Nice lingerie.", + "battlearmor": "Battlearmor.", + "battledress": "Battledress.", + "body oil": "Body oil.", + "boyshorts": "Boy shorts.", + "chains": "Chains.", + "clubslut netting": "Netting.", + "conservative clothing": "Conservative clothing.", + "cutoffs and a t-shirt": "Cutoffs, t-shirt.", + "cutoffs": "Jean shorts.", + "harem gauze": "Harem outfit.", + "jeans": "Tight blue jeans.", + "kitty lingerie": "Kitty lingerie.", + "leather pants and a tube top": "Leather pants, tube top.", + "leather pants and pasties": "Leather pants, pasties.", + "leather pants": "Nice leather pants.", + "lederhosen": "Lederhosen.", + "nice business attire": "Nice suit.", + "overalls": "Overalls.", + "panties and pasties": "Pasties, panties.", + "panties": "Nice panties.", + "pasties": "Pasties.", + "restrictive latex": "Bondage latex.", + "shibari ropes": "Shibari.", + "slutty business attire": "Slutty suit.", + "slutty jewelry": "Bangles.", + "spats and a tank top": "Spats, tank top.", + "sport shorts and a sports bra": "Shorts, bra.", + "sport shorts and a t-shirt": "Nice sport shorts, shirt.", + "sport shorts": "Shorts.", + "stretch pants and a crop-top": "Stretch pants, crop-top.", + "striped panties": "Striped panties.", + "striped underwear": "Striped underwear", + "uncomfortable straps": "Leather straps.", + + }, + accessory: { + collar: { + "ancient Egyptian": "Wesekh.", + "ball gag": "Ball gag.", + "bell collar": "Bell collar.", + "bit gag": "Bit gag.", + "bowtie": "Bowtie collar.", + "cruel retirement counter": "Cruel counter collar.", + "dildo gag": "Dildo gag.", + "heavy gold": "Gold collar.", + "leather with cowbell": "Cowbell collar.", + "massive dildo gag": "Throat-bulging dildo gag.", + "neck corset": "Neck corset.", + "nice retirement counter": "Nice counter collar.", + "porcelain mask": "Porcelain mask.", + "preg biometrics": "Pregnancy biometrics collar.", + "pretty jewelry": "Pretty collar.", + "satin choker": "Satin choker.", + "shock punishment": "Shock collar.", + "silk ribbon": "Silken ribbon.", + "stylish leather": "Stylish leather collar.", + "tight steel": "Steel collar.", + "uncomfortable leather": "Leather collar.", + }, + belly: { + "a corset": "Corset.", + "a huge empathy belly": "Huge fake belly.", + "a large empathy belly": "Large fake belly.", + "a medium empathy belly": "Medium fake belly.", + "a small empathy belly": "Small fake belly.", + "a support band": "Support band.", + "an extreme corset": "Extreme corsetage.", + "shapewear": "Shapewear.", + }, + vaginal: { + "bullet vibrator": "Attached bullet vibrator.", + "smart bullet vibrator": "Attached smart bullet vibrator.", + "dildo": "Vaginal dildo.", + "large dildo": "Large vaginal dildo.", + "huge dildo": "Huge vaginal dildo.", + "long dildo": "Long vaginal dildo.", + "long, large dildo": "Long and large vaginal dildo.", + "long, huge dildo": "Long and wide vaginal dildo.", + }, + buttplug: { + "plug": "Buttplug.", + "large plug": "Large buttplug.", + "huge plug": "Huge buttplug.", + "long plug": "Long buttplug.", + "long, large plug": "Large, long buttplug.", + "long, huge plug": "Enormous buttplug.", + }, + buttplugAttachment: { + "tail": "Attached tail.", + "cat tail": "Attached cat tail.", + "fox tail": "Attached fox tail.", + "cow tail": "Attached cow tail.", + } + }, + diet: { + "restricted": "Dieting.", + "fattening": "Gaining weight.", + "corrective": "Corrective.", + "XX": "Estrogen rich.", + "XY": "Testosterone rich.", + "XXY": "Futanari mix.", + "muscle building": "Pumping iron.", + "slimming": "Slimming down.", + "cum production": "Cum production.", + "cleansing": "Cleansing.", + "fertility": "Fertility.", + }, + specialDiet: { // index: dietCum + 3 * dietMilk + 0: null, + 1: "Cum Added.", + 2: "Cum Based.", + 3: "Milk Based.", + 4: "Milk & Cum Added.", + 5: "Cum Based with Milk.", + 6: "Milk Added.", + 7: "Milk Based with Cum.", + 8: "Cum and Milk Based." + }, + race: { + "white": "Caucasian", + "asian": "Asian", + "indo-aryan": "Indo-aryan", + "latina": "Latina", + "middle eastern": "Middle Eastern", + "black": "Black", + "pacific islander": "Pacific Islander", + "malay": "Malay", + "amerindian": "Amerindian", + "semitic": "Semitic", + "southern european": "Southern European", + "mixed race": "Mixed race", + }, + hormoneBalance: { // rating is hormoneBalance value + 500 + 100: "Overwhelmingly masculine", + 200: "Extremely masculine", + 300: "Heavily masculine", + 400: "Very masculine", + 479: "Masculine", + 520: "Neutral", + 599: "Feminine", + 699: "Very feminine", + 799: "Heavily feminine", + 899: "Extremely feminine", + 1000: "Overwhelmingly feminine" + }, + health: { + illness: { + 0: null, + 1: {desc: "Sick", style: "yellow"}, + 2: {desc: "Ill", style: ["red", "strong"]}, + 3: {desc: "Very ill", style: ["red", "strong"]}, + 4: {desc: "Terribly ill", style: ["red", "strong"]}, + 5: {desc: "Dangerously ill", style: ["red", "strong"]} + }, + tiredness: { + 30: {desc: "Energetic", style: "green"}, + 60: {desc: "Tired", style: "yellow"}, + 90: {desc: "Fatigued", style: "orange"}, + 100: {desc: "Exhausted", style: ["red", "strong"]} + }, + health: { // health + 100 + 10: {desc: "On the edge of death", style: ["red", "strong"]}, + 49: {desc: "Extremely unhealthy", style: ["red", "strong"]}, + 79: {desc: "Unhealthy", style: ["red", "strong"]}, + 120: {desc: "healthy", style: "yellow"}, + 150: {desc: "Very healthy", style: "green"}, + 190: {desc: "Extremely healthy", style: "green"}, + 200: {desc: "Unnaturally healthy", style: "green"} + }, + }, + prestige: { + 0: null, + 1: {desc: "Prestigious.", style: "green"}, + 2: {desc: "Very prestigious.", style: "green"}, + 3: {desc: "Extremely prestigious.", style: "green"}, + }, + pornPrestige: { + 0: null, + 1: {desc: "Porn amateur.", style: "green"}, + 2: {desc: "Porn slut.", style: "green"}, + 3: {desc: "Porn star.", style: "green"}, + }, + accent: { + 0: null, + 1: {desc: "Cute accent.", style: "pink"}, + 2: {desc: "Accent."}, + 3: {desc: "Bad accent.", style: "red"}, + 4: {desc: "No language skills.", style: "red"}, + }, + smartPiercing: { + setting: { + "off": "SP off.", + "submissive": "SP: submissive.", + "lesbian": "SP: lesbian", + "oral": "SP: oral.", + "humiliation": "SP: humiliation.", + "anal": "SP: anal.", + "boobs": "SP: breasts.", + "sadist": "SP: sadism.", + "masochist": "SP: masochism.", + "dom": "SP: dominance.", + "pregnancy": "SP: pregnancy.", + "vanilla": "SP: vanilla.", + "all": "SP: all.", + "none": "SP: none.", + "monitoring": "SP: monitoring", + "men": "SP: men", + "women": "SP: women", + "anti-men": "SP: anti men", + "anti-women": "SP: anti women", + } + }, + skills: { + entertainment: { + 10: null, + 29: {desc: "Basic entertainer", style: "aquamarine"}, + 59: {desc: "Skilled entertainer", style: "aquamarine"}, + 99: {desc: "Expert entertainer", style: "aquamarine"}, + 999: {desc: "Masterful entertainer", style: "aquamarine"} + }, + sex: { // indices: [sexSkills, hasVagina(0,1)] + 30: {desc: "Sexually unskilled", style: "aquamarine"}, + 90: {desc: "Sexually skilled", style: "aquamarine"}, + 120: {desc: "Sexual expert", style: "aquamarine"}, + 180: { + 0: {desc: "Masterful shemale", style: "aquamarine"}, + 1: {desc: "Sexual expert", style: "aquamarine"} + }, + 9999: {desc: "Sex master", style: "aquamarine"} + }, + whoring: { + 10: null, + 29: {desc: "Basic whore", style: "aquamarine"}, + 59: {desc: "Skilled whore", style: "aquamarine"}, + 99: {desc: "Expert whore", style: "aquamarine"}, + 999: {desc: "Masterful whore", style: "aquamarine"} + }, + mss: {desc: "Masterful Sex Slave.", style: "aquamarine"}, + fighter: {desc: "Trained fighter.", style: "aquamarine"}, + }, + sexDrive: { + XX: { + 5: {desc: "Disgusted by men", style: "red"}, + 15: {desc: "Turned off by men", style: "red"}, + 35: {desc: "Not attracted to men", style: "red"}, + 65: {desc: "Indifferent to men"}, + 85: {desc: "Attracted to men", style: "green"}, + 95: {desc: "Aroused by men", style: "green"}, + 999: {desc: "Passionate about men", style: "green"} + }, + XY: { + 5: {desc: "disgusted by women", style: "red"}, + 15: {desc: "turned off by women", style: "red"}, + 35: {desc: "not attracted to women", style: "red"}, + 65: {desc: "indifferent to women"}, + 85: {desc: "attracted to women", style: "green"}, + 95: {desc: "aroused by women", style: "green"}, + 999: {desc: "passionate about women", style: "green"} + }, + energy: { + 20: {desc: "No sex drive", style: "red"}, + 40: {desc: "Poor sex drive", style: "red"}, + 60: {desc: "Average sex drive", style: "yellow"}, + 80: {desc: "Good sex drive", style: "green"}, + 95: {desc: "Powerful sex drive", style: "green"}, + 999: {desc: "Nymphomaniac!", style: "green"} + }, + synergy: { + omni: {desc: "Omnisexual!", style: "green"}, + nymphomni: {desc: "Omnisexual nymphomaniac!", style: "green"} + } + } + }, + short: { + body: { + age: { + 18: "18", + 19: "19", + 24: "Ea20s", + 29: "Lt20s", + 34: "Ea30s", + 39: "Lt30s", + 999: "40s" + }, + face: { // face value + 100 + 4: {desc: "Face---", style: "red"}, + 59: {desc: "Face--", style: "red"}, + 89: {desc: "Face-", style: "red"}, + 110: {desc: "Face"}, + 140: {desc: "Face+", style: "pink"}, + 195: {desc: "Face++", style: "pink"}, + 200: {desc: "Face+++", style: "pink"}, + }, + lips: { + 10: {desc: "Lips-", style: "red"}, + 20: {desc: "Lips"}, + 40: {desc: "Lips+"}, + 70: {desc: "Lips++"}, + 95: {desc: "Lips+++"}, + 100: {desc: "Facepussy"} + }, + teeth: { + "crooked": {desc: "Cr Teeth", style: "yellow"}, + "gapped": {desc: "Gap", style: "yellow"}, + "cosmetic braces": {desc: "Cos Braces"}, + "straightening braces": {desc: "Braces"}, + "removable": {desc: "Rem Teeth"}, + "pointy": {desc: "Fangs"}, + "baby": {desc: "Baby"}, + "mixed": {desc: "Mixed"} + }, + waist: { // waist value + 100 + 4: {desc: "Wst+++", style: "pink"}, + 60: {desc: "Wst++", style: "pink"}, + 89: {desc: "Wst+", style: "pink"}, + 110: {desc: "Wst"}, + 140: {desc: "Wst-", style: "red"}, + 195: {desc: "Wst--", style: "red"}, + 200: {desc: "Wst---", style: "red"} + }, + genitalia:{ + dickBalls: { // indices [dick, balls] + 3: { + 3: null, + 4: "Balls", + 5: "Balls+", + 8: "Balls++", + 99: "Balls+++" + }, + 4: { + 3: "Dick", + 99: "Junk" + }, + 5: { + 4: "Dick+", + 99: "Junk+" + }, + 8: { + 5: "Dick++", + 99: "Junk++" + }, + 99: { + 8: "Dick+++", + 99: "Junk+++" + } + }, + holes: { // indices [vagina, anus] + 2: { + 2: null, + 3: "A+", + 4: "A++" + }, + 3: { + 2: "V+", + 3: "V+A+" + }, + 4: { + 3: "V++", + 4: "V++A++" + } + } + }, + titsAss: { // indices: [boobs, butt, FSAssetExpansionist(0,1), weight+100, muscles+100] + 499: { + 2: { + 2: { // FSAssetExpansionist doesn't matter + 109: { + 130: {desc: "Girlish", style: "pink"}, + }, + }, + } + }, + 799: { + 4: null, + 6: {desc: "Ass", style: "pink"}, + 8: {desc: "Ass+", style: "pink"}, + 9: {desc: "Ass++", style: "pink"}, + 999: {desc: "Ass+++", style: "pink"}, + }, + 1999: { + 4: {desc: "Boobs", style: "pink"}, + 999: {desc: "T&A", style: "pink"} + }, + 3999: { + 6: {desc: "Boobs+", style: "pink"}, + 999: {desc: "T&A+", style: "pink"} + }, + 11999: { + 8:{desc: "Boobs++", style: "pink"}, + 999: {desc: "T&A++", style: "pink"}, + }, + 100000: { + 9: {desc: "Boobs+++", style: "pink"}, + 999: {desc: "T&A+++", style: "pink"} + } + }, + weight: { // indices: [weigh + 100, FSHedonisticDecadence (0,1), hips + 2, ] + 4: {desc: "W---", style: ["red", "strong"]}, + 69: { + 99: { // FSHedonisticDecadence doesn't matter + 0: {desc: "W--", style: "strong"}, + 5: {desc: "W--", style: ["red", "strong"]} + } + }, + 89: {desc: "W-", style: "strong"}, + 110: {desc: "W", style: "strong"}, + 130: {desc: "W+", style: "strong"}, + 195: { + 0: {desc: "W++", style: ["red", "strong"]}, + 1: { + 3: {desc: "W++", style: ["red", "strong"]}, + 5: {desc: "W++", style: "strong"} + } + }, + 230: { + 0: {desc: "W+++", style: ["red", "strong"]}, + 1: { + 4: {desc: "W+++", style: ["red", "strong"]}, + 5: {desc: "W+++", style: "strong"} + } + }, + 260: { + 0: {desc: "W++++", style: ["red", "strong"]}, + 1: {desc: "W++++", style: "strong"} + }, + 290: { + 0: {desc: "W+++++", style: ["red", "strong"]}, + 1: {desc: "W+++++", style: "strong"} + }, + 999: { + 0: {desc: "W++++++", style: ["red", "strong"]}, + 1: {desc: "W++++++", style: "strong"} + } + }, + hipsAss: { + 0: {desc: "Disp-", style: "red"}, + 1: {desc: "Disp+", style: "red"} + }, + muscles: { // indices: [muscles + 100, FSPhysicalIdealist(0,1) ] + 4: {desc:"Weak++", style:"red"}, + 69: { + 0: {desc: "Soft+"}, + 1: {desc: "Weak+", style: "red"} + }, + 94: { + 0: {desc: "Soft"}, + 1: {desc: "Weak", style: "red"} + }, + 105: {desc: "Soft"}, + 130: {desc: "Toned"}, + 150: {desc: "Fit"}, + 195: {desc: "Musc+"}, + 100: {desc: "Musc++"} + } + }, + mental: { + devotion: { // devotion value + 100 + 4: {desc: "VHate", style: ["devotion", "hateful"]}, + 49: {desc: "Hate", style: ["devotion", "hateful"]}, + 79: {desc: "Res", style: ["devotion", "resistant"]}, + 120: {desc: "Ambiv", style: ["devotion", "ambivalent"]}, + 150: {desc: "Accept", style: ["devotion", "accept"]}, + 195: {desc: "Devo", style: ["devotion", "devoted"]}, + 200: {desc: "Wor", style: ["devotion", "worship"]} + }, + trust: { // first key: trust + 100, second key: devotion + 100 + 4: {desc: "ETerr", style: ["trust", "extremely-terrified"]}, + 49: {desc: "Terr", style: ["trust", "terrified"]}, + 79: {desc: "Fright", style: ["trust", "frightened"]}, + 120: {desc: "Fear", style: ["trust", "fearful"]}, + 150: { + 79: {desc: "Caref", style: ["defiant", "careful"]}, + 200: {desc: "Caref", style: ["trust", "careful"]}, + }, + 195: { + 79: {desc: "Bold", style: ["defiant", "bold"]}, + 200: {desc: "Trust", style: ["trust", "trusting"]}, + }, + 200: { + 79: {desc: "Defiant", style: ["defiant", "full"]}, + 200: {desc: "VTrust", style: ["trust", "prof-trusting"]}, + } + }, + education: { // index: intelligenceImplant + 15 + 0: "(e-)", + 29: "", + 44: "(e)", + 99: "(e+)" + }, + intelligence: { // index: intelligence + 100 + 4: {desc: "I---", style: "orangered"}, + 49: {desc: "I--", style: "orangered"}, + 84: {desc: "I-", style: "orangered"}, + 115: {desc: "I"}, + 150: {desc: "I+", style: "deepskyblue"}, + 195: {desc: "I++", style: "deepskyblue"}, + 230: {desc: "I+++", style: "deepskyblue"}, + 999: {desc: "I++++", style: "deepskyblue"}, + }, + behavioralFlaw: { + "arrogant": "Arrog", + "bitchy": "Bitchy", + "odd": "Odd", + "hates men": "Men-", + "hates women": "Women-", + "gluttonous": "Glut", + "anorexic": "Ano", + "devout": "Dev", + "liberated": "Lib", + }, + sexualFlaw: { + "hates oral": {desc: "Oral-", style: "red"}, + "hates anal": {desc: "Anal-", style: "red"}, + "hates penetration": {desc: "Fuck-", style: "red"}, + "shamefast": {desc: "Shame", style: "red"}, + "idealistic": {desc: "Ideal", style: "red"}, + "repressed": {desc: "Repre", style: "red"}, + "apathetic": {desc: "Apath", style: "red"}, + "crude": {desc: "Crude", style: "red"}, + "judgemental": {desc: "Judge", style: "red"}, + "cum addict": {desc: "CumAdd", style: "yellow"}, + "anal addict": {desc: "AnalAdd", style: "yellow"}, + "attention whore": {desc: "Attention", style: "yellow"}, + "breast growth": {desc: "BoobObsess", style: "yellow"}, + "abusive": {desc: "Abusive", style: "yellow"}, + "malicious": {desc: "Malice", style: "yellow"}, + "self hating": {desc: "SelfHatr", style: "yellow"}, + "neglectful": {desc: "SelfNeglect", style: "yellow"}, + "breeder": {desc: "BreedObsess", style: "yellow"}, + }, + behavioralQuirk: { + "confident": "Confid", + "cutting": "Cutting", + "funny": "Funny", + "fitness": "Fit", + "adores women": "Women+", + "adores men": "Men+", + "insecure": "Insec", + "sinful": "Sinf", + "advocate": "Advoc", + }, + sexualQuirk: { + "gagfuck queen": "Gagfuck", + "painal queen": "Painal", + "strugglefuck queen": "Struggle", + "tease": "Tease", + "romantic": "Romantic", + "perverted": "Perverted", + "caring": "Caring", + "unflinching": "Unflinch", + "size queen": "SizeQ", + } + }, + health: { + tiredness: { + 30: {desc: "Ene", style: "green"}, + 60: {desc: "Tir", style: "yellow"}, + 90: {desc: "Tir+", style: "orange"}, + 100: {desc: "Exh", style: ["red", "strong"]} + } + }, + accent: { + 1: {desc: "Acc", style: "pink"}, + 2: {desc: "Acc-"}, + 3: {desc: "Acc--"}, + 4: {desc: "Acc--", style: "red"}, + }, + fetish: { // indices [fetish, fetishStrength] + "submissive": { + 60: "Sub", + 95: "Sub+", + 100: "Sub++" + }, + "cumslut": { + 60: "Oral", + 95: "Oral+", + 100: "Oral++" + }, + "humiliation": { + 60: "Humil", + 95: "Humil+", + 100: "Humil++" + }, + "buttslut": { + 60: "Anal", + 95: "Anal+", + 100: "Anal++" + }, + "boobs": { + 60: "Boobs", + 95: "Boobs+", + 100: "Boobs++" + }, + "sadist": { + 60: "Sadist", + 95: "Sadist+", + 100: "Sadist++" + }, + "masochist": { + 60: "Pain", + 95: "Pain+", + 100: "Pain++" + }, + "dom": { + 60: "Dom", + 95: "Dom+", + 100: "Dom++" + }, + "pregnancy": { + 60: "Preg", + 95: "Preg+", + 100: "Preg++" + }, + "none" : "Vanilla" + }, + prestige: { + 0: null, + 1: {desc: "Prest", style: "green"}, + 2: {desc: "Prest+", style: "green"}, + 3: {desc: "Prest++", style: "green"}, + }, + pornPrestige: { + 0: null, + 1: {desc: "PPrest", style: "green"}, + 2: {desc: "PPrest+", style: "green"}, + 3: {desc: "PPrest++", style: "green"}, + }, + diet: { + "restricted": "Di:W-", + "fattening": "Di:W+", + "corrective": "Di:W=", + "XX": "Di:XX+", + "XY": "Di:XY+", + "XXY": "Di:XXY+", + "muscle building": "Di:M+", + "slimming": "Di:M-", + "cum production": "Di:C+", + "cleansing": "Di:H+", + "fertility": "Di:F+", + + }, + specialDiet: { // index: dietCum + 3 * dietMilk + 0: null, + 1: "Cum+", + 2: "Cum++", + 3: "Milk+", + 4: "Cum+ Milk+", + 5: "Cum++ Milk+", + 6: "Milk++", + 7: "Cum+ Milk++", + 8: "Cum++ Milk++" + }, + drugs: { + "breast injections": "Boobs+", + "intensive breast injections": "Boobs++", + "hyper breast injections": "Boobs+++", + "nipple enhancers": "Nipple+", + "butt injections": "Butt+", + "intensive butt injections": "Butt++", + "hyper butt injections": "Butt+++", + "lip injections": "Lip+", + "fertility drugs": "Fert+", + "super fertility drugs": "Fert++", + "penis enhancement": "Dick+", + "intensive penis enhancement": "Dick++", + "hyper penis enhancement": "Dick+++", + "testicle enhancement": "Balls+", + "intensive testicle enhancement": "Balls++", + "hyper testicle enhancement": "Balls+++", + "psychosuppressants": "Psych-", + "psychostimulants": "Psych+", + "steroids": "Ster", + "female hormone injections": "HormXX++", + "male hormone injections": "HormXY++", + "hormone enhancers": "Horm+", + "hormone blockers": "Horm-", + "anti-aging cream": "Age-", + "appetite suppressors": "ApSup", + "penis atrophiers": "Dick-", + "testicle atrophiers": "Balls-", + "clitoris atrophiers": "Clit-", + "labia atrophiers": "Labia-", + "nipple atrophiers": "Nipple-", + "lip atrophiers": "Lip-", + "breast redistributors": "Breast-", + "butt redistributors": "Butt-", + "sag-B-gone": "AntiSag", + "growth stimulants": "GroStim", + "priapism agents": "Erection" + }, + nationality: { // NOTE this dictionary lacks "Zimbabwean" key, which is a spacial case + "Afghan": "Afg", + "Albanian": "Alb", + "Algerian": "Alg", + "American": "USA", + "Andorran": "And", + "Angolan": "Ang", + "Antiguan": "AB", + "Argentinian": "Arg", + "Armenian": "Arm", + "Aruban": "Aru", + "Australian": "Aus", + "Austrian": "Aut", + "Azerbaijani": "Aze", + "Bahamian": "Bah", + "Bahraini": "Bah", + "Bangladeshi": "Bgd", + "Barbadian": "Bar", + "Belarusian": "Ber", + "Belgian": "Bel", + "Belizean": "Blz", + "Beninese": "Ben", + "Bermudian": "Bmd", + "Bhutanese": "Bhu", + "Bissau-Guinean": "GB", + "Bolivian": "Bol", + "Bosnian": "Bos", + "Brazilian": "Bra", + "British": "UK", + "Bruneian": "Bru", + "Bulgarian": "Bul", + "Burkinabé": "BF", + "Burmese": "Bur", + "Burundian": "Bnd", + "Cambodian": "Kam", + "Cameroonian": "Cam", + "Canadian": "Can", + "Cape Verdean": "CV", + "Catalan": "Cat", + "Central African": "CAR", + "Chadian": "Cha", + "Chilean": "Chl", + "Chinese": "Chi", + "Colombian": "Col", + "Comorian": "Com", + "Congolese": "RC", + "a Cook Islander": "CI", + "Costa Rican": "CR", + "Croatian": "Cro", + "Cuban": "Cub", + "Curaçaoan": "Cur", + "Cypriot": "Cyp", + "Czech": "Cze", + "Danish": "Den", + "Djiboutian": "Dji", + "Dominican": "DR", + "Dominiquais": "Dom", + "Dutch": "Nld", + "East Timorese": "ET", + "Ecuadorian": "Ecu", + "Egyptian": "Egy", + "Emirati": "UAE", + "Equatoguinean": "EG", + "Eritrean": "Eri", + "Estonian": "Est", + "Ethiopian": "Eth", + "Fijian": "Fij", + "Filipina": "Phl", + "Finnish": "Fin", + "French": "Fra", + "French Guianan": "FG", + "French Polynesian": "FP", + "Gabonese": "Gab", + "Gambian": "Gam", + "Georgian": "Geo", + "German": "Ger", + "Ghanan": "Gha", + "Greek": "Gre", + "Greenlandic": "Grn", + "Grenadian": "Gda", + "Guamanian": "Gua", + "Guatemalan": "Gtm", + "Guinean": "Gui", + "Guyanese": "Guy", + "Haitian": "Hai", + "Honduran": "Hon", + "Hungarian": "Hun", + "I-Kiribati": "Kir", + "Icelandic": "Ice", + "Indian": "Ind", + "Indonesian": "Idn", + "Iranian": "Irn", + "Iraqi": "Irq", + "Irish": "Irl", + "Israeli": "Isr", + "Italian": "Ita", + "Ivorian": "IC", + "Jamaican": "Jam", + "Japanese": "Jpn", + "Jordanian": "Jor", + "Kazakh": "Kaz", + "Kenyan": "Ken", + "Kittitian": "SKN", + "Korean": "Kor", + "Kosovan": "Kos", + "Kurdish": "Kur", + "Kuwaiti": "Kuw", + "Kyrgyz": "Kyr", + "Laotian": "Lao", + "Latvian": "Lat", + "Lebanese": "Lbn", + "Liberian": "Lib", + "Libyan": "Lby", + "a Liechtensteiner": "Lie", + "Lithuanian": "Lit", + "Luxembourgian": "Lux", + "Macedonian": "Mac", + "Malagasy": "Mad", + "Malawian": "Mwi", + "Malaysian": "Mys", + "Maldivian": "Mdv", + "Malian": "Mal", + "Maltese": "Mlt", + "Marshallese": "MI", + "Mauritanian": "Mta", + "Mauritian": "Mts", + "Mexican": "Mex", + "Micronesian": "FSM", + "Moldovan": "Mol", + "Monégasque": "Mnc", + "Mongolian": "Mon", + "Montenegrin": "Mng", + "Moroccan": "Mor", + "Mosotho": "Les", + "Motswana": "Bot", + "Mozambican": "Moz", + "Namibian": "Nam", + "Nauruan": "Nau", + "Nepalese": "Npl", + "New Caledonian": "NC", + "a New Zealander": "NZ", + "Ni-Vanuatu": "Van", + "Nicaraguan": "Nic", + "Nigerian": "Nga", + "Nigerien": "Ngr", + "Niuean": "Niu", + "Norwegian": "Nor", + "Omani": "Omn", + "Pakistani": "Pak", + "Palauan": "Plu", + "Palestinian": "Pal", + "Panamanian": "Pan", + "Papua New Guinean": "PNG", + "Paraguayan": "Par", + "Peruvian": "Per", + "Polish": "Pol", + "Portuguese": "Por", + "Puerto Rican": "PR", + "Qatari": "Qat", + "Romanian": "Rom", + "Russian": "Rus", + "Rwandan": "Rwa", + "Sahrawi": "Sah", + "Saint Lucian": "SL", + "Salvadoran": "ES", + "Sammarinese": "SM", + "Samoan": "Sam", + "São Toméan": "STP", + "Saudi": "Sau", + "Scottish": "Sco", + "Senegalese": "Sen", + "Serbian": "Srb", + "Seychellois": "Sey", + "Sierra Leonean": "Sie", + "Singaporean": "Sng", + "Slovak": "Svk", + "Slovene": "Svn", + "a Solomon Islander": "SI", + "Somali": "Som", + "South African": "RSA", + "South Sudanese": "SS", + "Spanish": "Spa", + "Sri Lankan": "Sri", + "Sudanese": "Sud", + "Surinamese": "Sur", + "Swazi": "Swa", + "Swedish": "Swe", + "Swiss": "Swi", + "Syrian": "Syr", + "Taiwanese": "Tai", + "Tajik": "Taj", + "Tanzanian": "Tza", + "Thai": "Tha", + "Tibetan": "Tib", + "Togolese": "Tog", + "Tongan": "Ton", + "Trinidadian": "TT", + "Tunisian": "Tun", + "Turkish": "Tur", + "Turkmen": "Tkm", + "Tuvaluan": "Tuv", + "Ugandan": "Uga", + "Ukrainian": "Ukr", + "Uruguayan": "Uru", + "Uzbek": "Uzb", + "Vatican": "VC", + "Venezuelan": "Ven", + "Vietnamese": "Vnm", + "Vincentian": "SVG", + "Yemeni": "Yem", + "Zairian": "DRC", + "Zambian": "Zam", + "Ancient Chinese Revivalist": "Chi Rev", + "Ancient Egyptian Revivalist": "Egy Rev", + "Arabian Revivalist": "Ara Rev", + "Aztec Revivalist": "Azt Rev", + "Edo Revivalist": "Edo Rev", + "Roman Revivalist": "Rom Rev", + "": "None", + "none": "None", + "slave": "None", + "Stateless": "None" + }, + race: { + "white": "C", + "asian": "A", + "indo-aryan": "I", + "latina": "L", + "middle eastern": "ME", + "black": "B", + "pacific islander": "PI", + "malay": "M", + "amerindian": "AI", + "semitic": "S", + "southern european": "SE", + "mixed race": "MR", + }, + skin: { + "pure white": "P. Whi", + "extremely fair": "E. Fai", + "very fair": "V. Fai", + "extremely pale": "E. Pal", + "very pale": "V. Pal", + "light brown": "L. Br", + "dark brown": "D. Br", + "light olive": "L. Oli", + "dark olive": "D. Oli", + "light beige": "L. Bei", + "dark beige": "D. Bei", + "tan": "Tan", + "bronze": "Bron", + "ebony": "Ebon", + "pure black": "P. Bla", + "dark": "Dark", + "fair": "Fair", + "pale": "Pale" + }, + smartPiercing: { + setting: { + "off": "SP-", + "submissive": "SP:sub", + "lesbian": "SP:les", + "oral": "SP:oral", + "humiliation": "SP:humil", + "anal": "SP:anal", + "boobs": "SP:boobs", + "sadist": "SP:sade", + "masochist": "SP:pain", + "dom": "SP:dom", + "pregnancy": "SP:pregnancy", + "vanilla": "SP:vanilla", + "all": "SP:all", + "none": "SP:none", + "monitoring": "SP:monitoring", + "men": "SP:men", + "women": "SP:women", + "anti-men": "SP:anti-men", + "anti-women": "SP:anti-women", + } + }, + skills: { + entertainment: { + 10: null, + 29: {desc: "E", style: "aquamarine"}, + 59: {desc: "E+", style: "aquamarine"}, + 99: {desc: "E++", style: "aquamarine"}, + 999: {desc: "E+++", style: "aquamarine"} + }, + sex: { // indices: [sexSkills, hasVagina(0,1)] + 30: {desc: "S-", style: "aquamarine"}, + 90: {desc: "S+", style: "aquamarine"}, + 120: {desc: "S++", style: "aquamarine"}, + 180: { + 0: {desc: "Sh++", style: "aquamarine"}, + 1: {desc: "S++", style: "aquamarine"} + }, + 9999: {desc: "S++", style: "aquamarine"} + }, + whoring: { + 10: null, + 29: {desc: "W", style: "aquamarine"}, + 59: {desc: "W+", style: "aquamarine"}, + 99: {desc: "W++", style: "aquamarine"}, + 999: {desc: "W+++", style: "aquamarine"} + }, + mss: {desc: "MSS", style: "aquamarine"}, + fighter: {desc: "C", style: "aquamarine"}, + }, + sexDrive: { + XX: { + 5: {desc: "XY---", style: "red"}, + 15: {desc: "XY--", style: "red"}, + 35: {desc: "XY-", style: "red"}, + 65: {desc: "XY"}, + 85: {desc: "XY+", style: "green"}, + 95: {desc: "XY++", style: "green"}, + 999: {desc: "XY+++", style: "green"} + }, + XY: { + 5: {desc: "XX---", style: "red"}, + 15: {desc: "XX--", style: "red"}, + 35: {desc: "XX-", style: "red"}, + 65: {desc: "XX"}, + 85: {desc: "XX+", style: "green"}, + 95: {desc: "XX++", style: "green"}, + 999: {desc: "XX+++", style: "green"} + }, + energy: { + 20: {desc: "SD--", style: "red"}, + 40: {desc: "SD-", style: "red"}, + 60: {desc: "SD", style: "yellow"}, + 80: {desc: "SD+", style: "green"}, + 95: {desc: "SD++", style: "green"}, + 999: {desc: "Nympho!", style: "green"} + }, + synergy: { + omni: {desc: "Omni!", style: "green"}, + nymphomni: {desc: "Omni+Nympho!!", style: "green"} + } + } + } +}; diff --git a/src/002-config/fc-version.js b/src/002-config/fc-version.js index 9be650848c218e931834205c1b94a8380a525fb8..dda732eac5bddf28028fe2ede56ffabe69dd2a0a 100644 --- a/src/002-config/fc-version.js +++ b/src/002-config/fc-version.js @@ -1,7 +1,7 @@ App.Version = { base: "0.10.7.1", // The vanilla version the mod is based off of, this should never be changed. pmod: "3.4.0", - release: 1065, + release: 1066, }; /* Use release as save version */ diff --git a/src/data/backwardsCompatibility/backwardsCompatibility.js b/src/data/backwardsCompatibility/backwardsCompatibility.js index 930e64d4bce2e80a5c1e00c310d766475e390af3..3eb0251be825d75d3e08964f423acf58b7abff69 100644 --- a/src/data/backwardsCompatibility/backwardsCompatibility.js +++ b/src/data/backwardsCompatibility/backwardsCompatibility.js @@ -105,6 +105,7 @@ App.Update.backwardsCompatibility = function() { div.append(`Cleaning up... `); jQuery('#backwardsCompatibility').append(div); App.Update.cleanUp(div); + App.UI.SlaveSummary.settingsChanged(); } catch (error) { div = document.createElement('p'); div.className = "red"; @@ -113,7 +114,6 @@ App.Update.backwardsCompatibility = function() { State.restore(); throw (error); // rethrow the exception to Sugarcube so we get a fancy stack trace } - return; }; App.Update.globalVariables = function(node) { @@ -199,6 +199,13 @@ App.Update.globalVariables = function(node) { if (V.sortSlavesBy === "income" || V.sortSlavesBy === "lastWeeksCashIncome") { V.sortSlavesBy = "weeklyIncome"; } + + if (typeof V.abbreviateClothes === "number") { + for (const key of ["clothes", "devotion", "diet", "drugs", "genitalia", "health", "hormoneBalance", + "mental", "nationality", "origins", "physicals", "race", "rules", "rulesets", "skills"]) { + V.UI.slaveSummary.abbreviation[key] = V["abbreviate" + capFirstChar(key)]; + } + } } if (typeof V.taitorWeeks !== "undefined") { diff --git a/src/data/onLoad.js b/src/data/onLoad.js deleted file mode 100644 index 349c62cad99c864af3de06bcd6c5b18927c90eb3..0000000000000000000000000000000000000000 --- a/src/data/onLoad.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * - * @param {object} save - */ -Config.saves.onLoad = function(save) { - // get the old State.variables for easier access. - const V = save.state.history[0].variables; - - App.UI.Theme.onLoad(V); -}; diff --git a/src/debugging/debugJS.js b/src/debugging/debugJS.js index d2c4dabc29c39f9086ba2f7c25c9ad1f57d7eda9..92f29adeb43750a93d37d3053a083816f3b243e3 100644 --- a/src/debugging/debugJS.js +++ b/src/debugging/debugJS.js @@ -121,6 +121,6 @@ App.Debug.dumpGameState = function() { App.Debug.slaveSummaryText = function(idx) { let span = document.createElement("span"); - span.appendChild(SlaveSummary(State.variables.slaves[idx])); + span.appendChild(App.UI.SlaveSummary.render(State.variables.slaves[idx])); return span.outerHTML; }; diff --git a/src/events/intro/introSummary.tw b/src/events/intro/introSummary.tw index f4663b62525eb58ea43159b44ba9be197235dae6..25f164f96dbd605afa5e7a460a21a47cf22a77d6 100644 --- a/src/events/intro/introSummary.tw +++ b/src/events/intro/introSummary.tw @@ -78,7 +78,7 @@ You may review your settings before clicking "Continue" to begin.<br> <<if ($economy != 100) || ($seeDicks != 25) || ($continent != "North America") || ($internationalTrade != 1) || ($internationalVariety != 1) || ($seeRace != 1) || ($seeNationality != 1) || ($seeExtreme != 0) || ($seeCircumcision != 1) || ($seeAge != 1) || ($plot != 1)>> | [[restore defaults|Intro Summary][$seeDicks = 25, $economy = 100, $continent = "North America", $internationalTrade = 1, $internationalVariety = 1, $seeRace = 1, $seeNationality = 1, $seeExtreme = 0, $seeCircumcision = 1, $seeAge = 1, $plot = 1]] <</if>> - | [[Cheat Start|init Nationalities][cashX(1000000, "cheating"), $PC.rules.living = "luxurious",repX(20000, "cheating"), $dojo += 1, $cheatMode = 1, $seeDesk = 0, $seeFCNN = 0, $sortSlavesBy = "devotion", $sortSlavesOrder = "descending", $sortSlavesMain = 0, $rulesAssistantMain = 1, $abbreviateDevotion = 1, $abbreviateRules = 1, $abbreviateClothes = 2, $abbreviateHealth = 1, $abbreviateDiet = 1, $abbreviateDrugs = 1, $abbreviateRace = 1, $abbreviateNationality = 1, $abbreviateGenitalia = 1, $abbreviatePhysicals = 1, $abbreviateSkills = 1, $abbreviateMental = 2, $PC.skill.trading = 100, $PC.skill.warfare = 100, $PC.skill.slaving = 100, $PC.skill.engineering = 100, $PC.skill.medicine = 100, $PC.skill.hacking = 100, resetEyeColor($PC)]] //Intended for debugging: may have unexpected effects// + | [[Cheat Start|init Nationalities][cashX(1000000, "cheating"), $PC.rules.living = "luxurious",repX(20000, "cheating"), $dojo += 1, $cheatMode = 1, $seeDesk = 0, $seeFCNN = 0, $sortSlavesBy = "devotion", $sortSlavesOrder = "descending", $sortSlavesMain = 0, $rulesAssistantMain = 1, $UI.slaveSummary.abbreviation = {devotion: 1, rules: 1, clothes: 2, health: 1, diet: 1, drugs: 1, race: 1, nationality: 1, genitalia: 1, physicals: 1, skills: 1, mental: 2}, $PC.skill.trading = 100, $PC.skill.warfare = 100, $PC.skill.slaving = 100, $PC.skill.engineering = 100, $PC.skill.medicine = 100, $PC.skill.hacking = 100, resetEyeColor($PC)]] //Intended for debugging: may have unexpected effects// <<set $minimumSlaveAge = variableAsNumber($minimumSlaveAge, 3, 18, 18)>> <<set $retirementAge = variableAsNumber($retirementAge, 25, 120, 45)>> @@ -1362,4 +1362,4 @@ You may review your settings before clicking "Continue" to begin.<br> <</if>> </div> -</div> \ No newline at end of file +</div> diff --git a/src/facilities/nursery/nurseryWidgets.js b/src/facilities/nursery/nurseryWidgets.js index 764f268c1f28f4cbcb89ad0d97ec9624d93e4b71..ce37ddade40cd968014524a9cf417ef04844854f 100644 --- a/src/facilities/nursery/nurseryWidgets.js +++ b/src/facilities/nursery/nurseryWidgets.js @@ -14,12 +14,14 @@ App.Facilities.Nursery.InfantSummary = function(child) { r = ``; function InfantSummaryUncached(child) { - if (V.abbreviateHealth === 1) { + /** @type {App.UI.SlaveSummary.AbbreviationState} */ + const abbreviate = V.UI.slaveSummary.abbreviation; + if (abbreviate.health === 1) { // shortHealth(child); - } else if (V.abbreviateHealth === 2) { + } else if (abbreviate.health === 2) { // longHealth(child); } - if (V.abbreviateNationality + V.abbreviateGenitalia + V.abbreviatePhysicals + V.abbreviateSkills + V.abbreviateMental !== 0) { + if (abbreviate.nationality + abbreviate.genitalia + abbreviate.physicals + abbreviate.skills + abbreviate.mental !== 0) { r += `<br> `; if (V.seeImages !== 1 || V.seeSummaryImages !== 1 || V.imageChoice === 1) { r += " "; @@ -40,32 +42,32 @@ App.Facilities.Nursery.InfantSummary = function(child) { } const firstLetter = V.desc.substring(0, 1).toUpperCase(); V.desc = firstLetter + V.desc.substring(1); - r += `<strong><span class="coral">${V.desc}${V.abbreviatePhysicals === 2? '.' : ''}</span></strong> `; + r += `<strong><span class="coral">${V.desc}${abbreviate.physicals === 2? '.' : ''}</span></strong> `; if (V.seeRace) { r += `<span class="tan">`; - if (V.abbreviateRace === 1) { + if (abbreviate.race === 1) { shortRace(child); - } else if (V.abbreviateRace === 2) { + } else if (abbreviate.race === 2) { longRace(child); } r += `</span> `; } - if (V.abbreviateNationality === 1) { + if (abbreviate.nationality === 1) { shortNationality(child); - } else if (V.abbreviateNationality === 2) { + } else if (abbreviate.nationality === 2) { longNationality(child); } - if (V.abbreviatePhysicals === 1) { + if (abbreviate.physicals === 1) { shortSkin(child); } else { r += `<span class="pink">${child.skin.charAt(0).toUpperCase() + child.skin.slice(1)} skin.</span> `; } - if (V.abbreviatePhysicals === 1) { + if (abbreviate.physicals === 1) { shortAge(child); shortFace(child); shortEyes(child); r += `</span> `; - } else if (V.abbreviatePhysicals === 2) { + } else if (abbreviate.physicals === 2) { longAge(child); longFace(child); longEyes(child); @@ -75,39 +77,39 @@ App.Facilities.Nursery.InfantSummary = function(child) { if (V.seeImages !== 1 || V.seeSummaryImages !== 1 || V.imageChoice === 1) { r += " "; } - if (V.abbreviateSkills === 1) { + if (abbreviate.skills === 1) { shortIntelligence(child); shortPrestige(child); shortPornPrestige(child); - } else if (V.abbreviateSkills === 2) { + } else if (abbreviate.skills === 2) { longIntelligence(child); longPrestige(child); longPornPrestige(child); } - if (V.abbreviateMental === 1) { + if (abbreviate.mental === 1) { shortBehaviorFlaw(child); shortSexFlaw(child); - } else if (V.abbreviateMental === 2) { + } else if (abbreviate.mental === 2) { longBehaviorFlaw(child); longSexFlaw(child); } - if ((child.relationship !== 0) || (V.abbreviateClothes === 2) || (V.abbreviateRulesets === 2)) { + if ((child.relationship !== 0) || (abbreviate.clothes === 2) || (abbreviate.rulesets === 2)) { r += `<br> `; if (V.seeImages !== 1 || V.seeSummaryImages !== 1 || V.imageChoice === 1) { r += ` `; } } - if (V.abbreviateMental === 1) { + if (abbreviate.mental === 1) { r += `<span class="lightgreen">`; shortExtendedFamily(child); r += `</span> `; shortRival(child); - } else if (V.abbreviateMental === 2) { + } else if (abbreviate.mental === 2) { longExtendedFamily(child); longRival(child); } r += ` `; - if (V.abbreviateOrigins === 2 && child.origin !== 0) { + if (abbreviate.origins === 2 && child.origin !== 0) { origins(child); } return r; @@ -2065,6 +2067,8 @@ App.Facilities.Nursery.LongInfantDescription = function(child) { */ App.Facilities.Nursery.ChildSummary = function(child) { "use strict"; + /** @type {App.UI.SlaveSummary.AbbreviationState} */ + const abbreviate = V.UI.slaveSummary.abbreviation; let r = ``; @@ -2074,39 +2078,39 @@ App.Facilities.Nursery.ChildSummary = function(child) { * @returns {string} */ function ChildSummaryUncached(child) { - if (V.abbreviateDevotion === 1) { + if (abbreviate.devotion === 1) { shortDevotion(child); - } else if (V.abbreviateDevotion === 2) { + } else if (abbreviate.devotion === 2) { longDevotion(child); } if (child.fuckdoll === 0) { - if (V.abbreviateRules === 1) { + if (abbreviate.rules === 1) { shortRules(child); - } else if (V.abbreviateRules === 2) { + } else if (abbreviate.rules === 2) { longRules(child); } } - if (V.abbreviateDiet === 1) { + if (abbreviate.diet === 1) { shortWeight(child); - } else if (V.abbreviateDiet === 2) { + } else if (abbreviate.diet === 2) { longWeight(child); } - if (V.abbreviateDiet === 1) { + if (abbreviate.diet === 1) { shortDiet(child); - } else if (V.abbreviateDiet === 2) { + } else if (abbreviate.diet === 2) { longDiet(child); } - if (V.abbreviateHealth === 1) { + if (abbreviate.health === 1) { shortHealth(child); - } else if (V.abbreviateHealth === 2) { + } else if (abbreviate.health === 2) { longHealth(child); } - if (V.abbreviateDrugs === 1) { + if (abbreviate.drugs === 1) { shortDrugs(child); - } else if (V.abbreviateDrugs === 2) { + } else if (abbreviate.drugs === 2) { longDrugs(child); } - if (V.abbreviateNationality + V.abbreviateGenitalia + V.abbreviatePhysicals + V.abbreviateSkills + V.abbreviateMental !== 0) { + if (abbreviate.nationality + abbreviate.genitalia + abbreviate.physicals + abbreviate.skills + abbreviate.mental !== 0) { r += `<br> `; if (V.seeImages !== 1 || V.seeSummaryImages !== 1 || V.imageChoice === 1) { r += " "; @@ -2115,32 +2119,32 @@ App.Facilities.Nursery.ChildSummary = function(child) { V.desc = SlaveTitle(child); const firstLetter = V.desc.substring(0, 1).toUpperCase(); V.desc = firstLetter + V.desc.substring(1); - r += `<strong><span class="coral">${V.desc}${V.abbreviatePhysicals === 2? '.' : ''}</span></strong> `; + r += `<strong><span class="coral">${V.desc}${abbreviate.physicals === 2? '.' : ''}</span></strong> `; if (V.seeRace) { r += `<span class="tan">`; - if (V.abbreviateRace === 1) { + if (abbreviate.race === 1) { shortRace(child); - } else if (V.abbreviateRace === 2) { + } else if (abbreviate.race === 2) { longRace(child); } r += `</span> `; } - if (V.abbreviateNationality === 1) { + if (abbreviate.nationality === 1) { shortNationality(child); - } else if (V.abbreviateNationality === 2) { + } else if (abbreviate.nationality === 2) { longNationality(child); } - if (V.abbreviatePhysicals === 1) { + if (abbreviate.physicals === 1) { shortSkin(child); } else { r += `<span class="pink">${child.skin.charAt(0).toUpperCase() + child.skin.slice(1)} skin.</span> `; } - if (V.abbreviateGenitalia === 1) { + if (abbreviate.genitalia === 1) { shortGenitals(child); - } else if (V.abbreviateGenitalia === 2) { + } else if (abbreviate.genitalia === 2) { longGenitals(child); } - if (V.abbreviatePhysicals === 1) { + if (abbreviate.physicals === 1) { shortAge(child); shortFace(child); shortEyes(child); @@ -2160,7 +2164,7 @@ App.Facilities.Nursery.ChildSummary = function(child) { shortLactation(child); // shortMods(child); r += `</span> `; - } else if (V.abbreviatePhysicals === 2) { + } else if (abbreviate.physicals === 2) { longAge(child); longFace(child); longEyes(child); @@ -2181,7 +2185,7 @@ App.Facilities.Nursery.ChildSummary = function(child) { } r += `</span> `; } - if (V.abbreviateHormoneBalance === 1) { + if (abbreviate.hormoneBalance === 1) { if (child.hormoneBalance <= -21) { r += `<span class="deepskyblue">`; r += ` <strong>HB:M</strong> `; @@ -2193,7 +2197,7 @@ App.Facilities.Nursery.ChildSummary = function(child) { r += ` <strong>HB:F</strong> `; } r += `</span> `; - } else if (V.abbreviateHormoneBalance === 2) { + } else if (abbreviate.hormoneBalance === 2) { r += `<span class=`; if (child.hormoneBalance <= -21) { r += `"deepskyblue"`; @@ -2230,7 +2234,7 @@ App.Facilities.Nursery.ChildSummary = function(child) { if (V.seeImages !== 1 || V.seeSummaryImages !== 1 || V.imageChoice === 1) { r += " "; } - if (V.abbreviateSkills === 1) { + if (abbreviate.skills === 1) { shortIntelligence(child); shortSexSkills(child); if (child.skill.combat > 0) { @@ -2239,7 +2243,7 @@ App.Facilities.Nursery.ChildSummary = function(child) { r += "</span> "; shortPrestige(child); shortPornPrestige(child); - } else if (V.abbreviateSkills === 2) { + } else if (abbreviate.skills === 2) { longIntelligence(child); longSexSkills(child); if (child.skill.combat > 0) { @@ -2249,7 +2253,7 @@ App.Facilities.Nursery.ChildSummary = function(child) { longPrestige(child); longPornPrestige(child); } - if (V.abbreviateMental === 1) { + if (abbreviate.mental === 1) { if (child.fetish !== "mindbroken") { if (child.fetishKnown === 1) { shortFetish(child); @@ -2266,7 +2270,7 @@ App.Facilities.Nursery.ChildSummary = function(child) { shortSexFlaw(child); shortBehaviorQuirk(child); shortSexQuirk(child); - } else if (V.abbreviateMental === 2) { + } else if (abbreviate.mental === 2) { if (child.fetish !== "mindbroken") { if (child.fetishKnown === 1) { longFetish(child); @@ -2287,23 +2291,23 @@ App.Facilities.Nursery.ChildSummary = function(child) { if (child.custom.label) { r += `<strong><span class="yellow">${capFirstChar(child.custom.label)}</span></strong> `; } - if ((child.relationship !== 0) || (V.abbreviateClothes === 2) || (V.abbreviateRulesets === 2)) { + if ((child.relationship !== 0) || (abbreviate.clothes === 2) || (abbreviate.rulesets === 2)) { r += `<br> `; if (V.seeImages !== 1 || V.seeSummaryImages !== 1 || V.imageChoice === 1) { r += ` `; } } - if (V.abbreviateMental === 1) { + if (abbreviate.mental === 1) { r += `<span class="lightgreen">`; shortExtendedFamily(child); r += `</span> `; shortClone(child); shortRival(child); - } else if (V.abbreviateMental === 2) { + } else if (abbreviate.mental === 2) { longExtendedFamily(child); } if (child.fuckdoll === 0) { - if (V.abbreviateClothes === 2) { + if (abbreviate.clothes === 2) { r += ` `; if (child.choosesOwnClothes === 1) { r += "Dressing herself. "; @@ -2325,7 +2329,7 @@ App.Facilities.Nursery.ChildSummary = function(child) { } r += ` `; rulesAssistant(child); - if (V.abbreviateOrigins === 2 && child.origin !== 0) { + if (abbreviate.origins === 2 && child.origin !== 0) { origins(child); } return r; @@ -6448,7 +6452,7 @@ App.Facilities.Nursery.ChildSummary = function(child) { function rulesAssistant(child) { if (child.useRulesAssistant === 0) { r += `<span class="lightgreen">RA-Exempt</span> `; - } else if (V.abbreviateRulesets === 2 && (child.currentRules !== undefined) && (child.currentRules.length > 0)) { + } else if (abbreviate.rulesets === 2 && (child.currentRules !== undefined) && (child.currentRules.length > 0)) { r += `Rules: ${V.defaultRules.filter(x => ruleApplied(child, x)).map(x => x.name).join(", ")}`; } } diff --git a/src/js/eventHandlers.js b/src/js/eventHandlers.js index 4099ad52566ebc2354161abf905e45bb84717516..4e3a7fc73e4e128f3d3566970828a0492aa020ef 100644 --- a/src/js/eventHandlers.js +++ b/src/js/eventHandlers.js @@ -3,6 +3,18 @@ App.EventHandlers = function() { * @param {SugarCubeLib.SaveObject} save */ function onLoad(save) { + const v = save.state.history[0].variables; + if (v.releaseID > App.Version.release) { + console.error("Save game version problem. Loaded : " + v.releaseID + ", above expected:" + App.Version.release); // eslint-disable-line no-console + throw new Error("The save you're attempting to load was created with the game version newer than one you are running. Please download the latest game version."); + } + // updating settings only for the same releaseID, otherwise user will run + // backwards compatibility and we update settings from there + if (v.releaseID === App.Version.release) { + App.UI.SlaveSummary.settingsChanged(v); + } + + App.UI.Theme.onLoad(v); } /** @@ -15,6 +27,7 @@ App.EventHandlers = function() { } function optionsChanged() { + App.UI.SlaveSummary.settingsChanged(); } return { diff --git a/src/js/slaveListing.js b/src/js/slaveListing.js index cc59d9a7aa1cc816a4f8890d42fe1b199dad2b90..86eb4a8010566738bd4aaf05a2b61444c40da656 100644 --- a/src/js/slaveListing.js +++ b/src/js/slaveListing.js @@ -328,7 +328,7 @@ App.UI.SlaveList.render = function() { res.appendChild(App.UI.jobLinks.transfersFragment(index, (slave, assignment) => { App.UI.SlaveList.ScrollPosition.record(); assignJob(slave, assignment); })); } - res.appendChild(SlaveSummary(slave)); + res.appendChild(App.UI.SlaveSummary.render(slave)); if (postNote !== undefined) { const pn = postNote(slave, index); diff --git a/src/js/slaveSummaryHelpers.js b/src/js/slaveSummaryHelpers.js new file mode 100644 index 0000000000000000000000000000000000000000..f7fd1efc792bffcb1628b1bbc7c8ef5c7999941c --- /dev/null +++ b/src/js/slaveSummaryHelpers.js @@ -0,0 +1,1738 @@ +// WARNING This file defines objects referenced in slaveSummaryWidgets.js. +// Either keep this file above the slaveSummaryWidgets.js in the name ordered list +// (tweego process them in this order), or rework the references. + +/* eslint-disable camelcase */ + +App.UI.SlaveSummaryImpl = function() { + const data = App.Data.SlaveSummary; + + const helpers = function() { + /** + * @param {HTMLElement} element + * @param {string|string[]} [classNames] + */ + function _addClassNames(element, classNames) { + if (classNames != undefined) { /* eslint-disable-line eqeqeq */ + if (Array.isArray(classNames)) { + element.classList.add(...classNames); + } else { + element.classList.add(classNames); + } + } + } + + /** + * @param {Node} container + * @param {string} text + * @param {string|string[]} [classNames] + * @param {boolean} [stdDecor=false] + * @param {number} [value] + */ + function makeSpan(container, text, classNames, stdDecor = false, value) { + let r = document.createElement("span"); + r.classList.add("ssi"); + _addClassNames(r, classNames); + if (value != undefined && V.summaryStats) { /* eslint-disable-line eqeqeq */ + text += `[${value}]`; + } + r.textContent = stdDecor ? `${capFirstChar(text)}.` : text; + if (container) { + container.appendChild(r); + } + return r; + } + + /** + * @param {Node} container + * @param {string} text + * @returns {Text} + */ + function addText(container, text) { + const r = document.createTextNode(text); + if (container) { + container.appendChild(r); + } + return r; + } + + /** + * @param {Node} [container] + * @param {string|string[]} [classNames] + */ + function makeBlock(container, classNames) { + let r = document.createElement("span"); + r.classList.add("ssb"); + _addClassNames(r, classNames); + if (container) { + container.appendChild(r); + } + return r; + } + + /** + * @param {Node} container + * @param {string|string[]} [classNames] + * @returns {HTMLParagraphElement} + */ + function makeParagraph(container, classNames) { + let r = document.createElement("p"); + r.classList.add("si"); + _addClassNames(r, classNames); + if (container) { + container.appendChild(r); + } + return r; + } + + /** + * @param {object} dict + * @param {*} value + * @param {*} [defaultValue] + * @returns {*|null} + */ + function getExactRating(dict, value, defaultValue = null) { + const res = dict[value]; + return res ? res : defaultValue; + } + + /** + * @param {object} ratings + * @param {number} value + * @returns {*|null} + */ + function getNumericRating(ratings, value) { + for (const key in ratings) { + if (parseInt(key) >= value) { + return ratings[key]; + } + } + return null; + } + + /** + * @param {object} ratings + * @param {number[]} values + * @returns {*|null} + */ + function getMultiNumericRating(ratings, values) { + const firstRating = getNumericRating(ratings, values[0]); + if (firstRating === null || typeof firstRating === "string" || firstRating.hasOwnProperty("desc")) { + return firstRating; + } + return getMultiNumericRating(firstRating, values.slice(1)); + } + + /** + * @typedef {object} StyledDesc + * @property {string} desc + * @property {string|string[]} [style] + */ + + /** @typedef {Object.<string, StyledDesc>} StyledRatings */ + /** + * @param {Node} container + * @param {StyledRatings} ratings + * @param {number} [value] + * @param {number} [offset] value offset in the ratings dictionary (to eliminate negative values) + * @param {boolean} [stdDecor=false] + */ + function makeRatedStyledSpan(container, ratings, value, offset = 0, stdDecor = false) { + /** @type {StyledDesc} */ + const d = getNumericRating(ratings, value + offset); + if (d) { + makeSpan(container, d.desc, d.style, stdDecor, value); + } + } + + /** + * @param {Node} container + * @param {StyledDesc} styledDesc + * @param {number} [value] + * @param {boolean} [stdDecor] + */ + function makeStyledSpan(container, styledDesc, value, stdDecor = false) { + if (styledDesc) { + makeSpan(container, styledDesc.desc, styledDesc.style, stdDecor, value); + } + } + + /** + * @param {Node} container + * @param {StyledRatings} ratings + * @param {string|number} value + */ + function makeMappedStyledSpan(container, ratings, value) { + const d = ratings[value]; + if (d) { + makeSpan(container, d.desc, d.style); + } + } + + /** + * @param {Node} container + * @param {Object.<string, string>} ratings + * @param {string|number} value + * @param {string|string[]} [classNames] + */ + function makeMappedSpan(container, ratings, value, classNames) { + const d = ratings[value]; + if (d) { + makeSpan(container, d, classNames); + } + } + + /** + * Returns first three string characters with the first one uppercased (string -> Str) + * @param {string} s + * @returns {string} + */ + function firstThreeUc(s) { + return s.charAt(0).toUpperCase() + s.charAt(1) + s.charAt(2); + } + + function syncFSData(arcology) { + arcology = arcology || V.arcologies[0]; + for (const fsp of App.Data.misc.FutureSocieties) { + const policy = arcology[fsp]; + const p = fsp.slice(2); + FSData.policy[p] = { + active: policy === "unset" ? 0 : 1, + strength: Math.trunc(policy === "unset" ? 0: policy / 10) + }; + } + + const dislikeBigButts = (FSData.policy.TransformationFetishist.strength < 2) && (FSData.policy.HedonisticDecadence.strength < 2) && (FSData.policy.AssetExpansionist.strength < 2) && (arcology.FSIntellectualDependencyLawBeauty === 0); + FSData.bigButts = dislikeBigButts ? -1 : 0; + } + /** + * @typedef {Object} FSDatum + * @property {number} active FS policy is active (0,1) + * @property {number} strength FS decoration level divided by 10 + */ + const FSData = { + /** @type {Object.<string, FSDatum>} */ + policy: {}, + bigButts: 0, + }; + + return { + addText: addText, + makeSpan: makeSpan, + makeBlock: makeBlock, + makeParagraph: makeParagraph, + getExactRating: getExactRating, + getNumericRating: getNumericRating, + getMultiNumericRating: getMultiNumericRating, + makeStyledSpan: makeStyledSpan, + makeRatedStyledSpan: makeRatedStyledSpan, + makeMappedStyledSpan: makeMappedStyledSpan, + makeMappedSpan: makeMappedSpan, + firstThreeUc: firstThreeUc, + syncFSData: syncFSData, + FSData: FSData, + }; + }(); + + const bits = function() { + const addText = helpers.addText; + const makeSpan = helpers.makeSpan; + const makeBlock = helpers.makeBlock; + const makeRatedStyledSpan = helpers.makeRatedStyledSpan; + + /** + * Returns index in the hips-ass rating table + * @param {App.Entity.SlaveState} slave + * @returns {number} 0 if butt is considered too small, 1 is too big, -1 otherwise. + */ + function hipsAssRating(slave) { + const FSData = helpers.FSData; + if (slave.hips < -1) { + if (slave.butt > 2 && FSData.bigButts <= 0) { + return 1; + } + } else if (slave.hips < 0) { + if (slave.butt > 4 && FSData.bigButts <= 0) { + return 1; + } + } else if (slave.hips > 2) { + if (slave.butt <= 8) { + return 0; + } + } else if (slave.hips > 1) { + if (slave.butt <= 3 && (FSData.policy.SlimnessEnthusiast.active === 0 || (slave.boobs >= 500))) { + return 0; + } + } else if (slave.hips > 0) { + if (slave.butt > 8) { + if (FSData.bigButts <= 0) { + return 1; + } + } else if (slave.butt <= 2 && ((FSData.policy.SlimnessEnthusiast.active === 0) || (slave.boobs >= 500))) { + return 0; + } + } else { + if (slave.butt > 6) { + if (FSData.bigButts <= 0) { + return 1; + } + } else if (slave.butt <= 1 && (FSData.policy.SlimnessEnthusiast.active === 0 || (slave.boobs >= 500))) { + return 0; + } + } + return -1; + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {App.Data.SlaveSummary.SmartPiercing} spData + * @returns {string} + */ + function smartFetishStr(slave, spData) { + if (slave.fetishKnown === 1) { + if (slave.clitSetting === "off") { + return spData.setting.off; + } else if ((slave.energy <= 95) && (slave.clitSetting === "all")) { + return spData.setting.all; + } else if ((slave.energy > 5) && (slave.clitSetting === "none")) { + return spData.setting.none; + } else if (((slave.fetish !== "none") && (slave.clitSetting === "vanilla"))) { + return spData.setting.vanilla; + } else if (slave.fetishStrength <= 95 || slave.fetish !== slave.clitSetting) { + const s = spData.setting[slave.clitSetting]; + if (s) { + return s; + } + } + if (!["anti-men", "anti-women", "men", "women"].includes(slave.clitSetting)) { + return spData.setting.monitoring; + } + } else { + return data.smartPiercing.setting[slave.clitSetting]; + } + return null; + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {App.Data.SlaveSummary.SmartPiercing} spData + * @returns {string} + */ + function smartAttractionStr(slave, spData) { + const sps = spData.setting; + const cs = slave.clitSetting; + if (slave.attrKnown === 1) { + switch (cs) { + case "women": + if (slave.attrXX < 95) { + return sps.women; + } else { + return sps.monitoring; + } + case "men": + if (slave.attrXY < 95) { + return sps.men; + } else { + return sps.monitoring; + } + case "anti-women": + if (slave.attrXX > 0) { + return sps["anti-women"]; + } else { + return sps.monitoring; + } + case "anti-men": + if (slave.attrXY > 0) { + return sps["anti-men"]; + } else { + return sps.monitoring; + } + } + } else { + switch (cs){ + // fall-through + case "women": + case "men": + case "anti-women": + case "anti-men": + return sps[cs]; + } + } + return null; + } + + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_health(slave, c) { + if (slave.health.health < -20) { + makeSpan(c, "H", ["red", "strong"], true, slave.health.health); + } else if (slave.health.health <= 20) { + makeSpan(c, "H", ["yellow", "strong"], true, slave.health.health); + } else if (slave.health.health > 20) { + makeSpan(c, "H", ["green", "strong"], true, slave.health.health); + } + if (passage() === "Clinic" && V.clinicUpgradeScanner) { + if (slave.chem > 15) { + makeSpan(c, `C${Math.ceil(slave.chem / 10)}`, ["cyan", "strong"]); + } else if (slave.chem <= 15 && slave.assignment === "get treatment in the clinic") { + makeSpan(c, `CSafe`, ["green", "strong"]); + } + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_illness(slave, c) { + if (slave.health.illness > 2) { + makeSpan(c, `Ill${slave.health.illness}`, ["red", "strong"], true, slave.health.illness); + } else if (slave.health.illness > 0) { + makeSpan(c, `Ill${slave.health.illness}`, ["yellow", "strong"], true, slave.health.illness); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_tired(slave, c) { + helpers.makeRatedStyledSpan(c, data.short.health.tiredness, slave.health.tired, 0, true); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_health(slave, c) { + helpers.makeRatedStyledSpan(c, data.long.health.health, slave.health.health, 100, true); + if (passage() === "Clinic" && V.clinicUpgradeScanner) { + if (slave.chem > 15) { + makeSpan(c, `Carcinogen buildup: ${Math.ceil(slave.chem / 10)}.`, "cyan"); + } else if (slave.chem <= 15 && slave.assignment === "get treatment in the clinic") { + makeSpan(c, `Safe chem levels.`, "green"); + } + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_illness(slave, c) { + makeRatedStyledSpan(c, data.long.health.illness, slave.health.illness, 0, true); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_tired(slave, c) { + makeRatedStyledSpan(c, data.long.health.tiredness, slave.health.tired, 0, true); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_age(slave, c) { + let r = makeSpan(c, "", "pink"); + if (V.showAgeDetail === 1) { + r.textContent += `Age ` + `${slave.actualAge}` + `.`; + } else { + r.textContent += helpers.getNumericRating(data.long.body.age, slave.actualAge); + } + /* + ** No NCS, then do the standard, However because of the wrinkles of Incubators, as long as visual age is greater + ** than or equal to physical age, we do the old physical body/Looks for fresh out of the can NCS slaves. + */ + if (((slave.geneMods.NCS === 0) || (slave.visualAge >= slave.physicalAge))) { + if (slave.actualAge !== slave.physicalAge) { + r.textContent += ` ${slave.physicalAge}` + ` year old body.`; + } + if (slave.visualAge !== slave.physicalAge) { + r.textContent += ` Looks ` + `${slave.visualAge}` + `.`; + } + } else { + /* + ** Now the rub. The use of physical Age for the year old body above, basically conflicts with the changes + ** that NCS introduces, so here to *distinguish* the changes, we use visual age with the 'year old body' + ** and appears, for example: Slave release from incubator at age 10, Her summary would show, 'Age 0. 10 + ** year old body.' But if she's given NCS a few weeks after release, while she's still before her first + ** birthday, it'll appear the same. But once her birthday fires, if we ran with the above code it would + ** say: 'Age 1. 11 year old body.' -- this conflicts with the way NCS works though, because she hasn't + ** visually aged, so our change here makes it say 'Age 1. Appears to have a 10 year old body.' + */ + r.textContent += ` Appears to have a ` + `${slave.visualAge}` + ` year old body.`; + } + if (slave.geneMods.NCS === 1) { + makeSpan(r, "NCS", "orange"); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_face(slave, c) { + const r = helpers.getNumericRating(data.long.body.face, slave.face + 100); + makeSpan(c, `${r.desc} ${slave.faceShape} face`, r.style, true, slave.face); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_eyes(slave, c) { + if (!canSee(slave)) { + makeSpan(c, "Blind.", "red"); + } else if (!canSeePerfectly(slave)) { + makeSpan(c, "Nearsighted.", "yellow"); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_ears(slave, c) { + if (slave.hears <= -2) { + makeSpan(c, "Deaf.", "red"); + } else if ((slave.hears === -1) && (slave.earwear !== "hearing aids")) { + makeSpan(c, "Hard of hearing.", "yellow"); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_lips(slave, c) { + makeRatedStyledSpan(c, data.long.body.lips, slave.lips, 0, true); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_teeth(slave, c) { + helpers.makeMappedStyledSpan(c, data.long.body.teeth, slave.teeth); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_muscles(slave, c) { + const h = helpers; + h.makeStyledSpan(c, h.getMultiNumericRating(data.long.body.muscles, [slave.muscles + 100, h.FSData.policy.PhysicalIdealist.active])); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_voice(slave, c) { + if (slave.voice === 0) { + makeSpan(c, "Mute.", "red"); + } else { + helpers.makeMappedStyledSpan(c, data.long.accent, slave.accent); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_tits_ass(slave, c) { + const h = helpers; + h.makeStyledSpan(c, + h.getMultiNumericRating(data.long.body.titsAss, + [slave.boobs, slave.butt, h.FSData.policy.AssetExpansionist.active, slave.weight + 100, slave.muscles + 100])); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_hips(slave, c) { + const di = hipsAssRating(slave); + if (di >= 0) { + helpers.makeMappedStyledSpan(c, data.long.body.hipsAss, di); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_waist(slave, c) { + makeRatedStyledSpan(c, data.long.body.waist, slave.waist, 100, true); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_implants(slave, c) { + const styles = "pink"; + if ((slave.boobsImplant !== 0) || (slave.buttImplant !== 0) || (slave.lipsImplant !== 0) || (slave.bellyImplant !== -1)) { + makeSpan(c, "Implants.", styles); + } else if ((slave.faceImplant >= 30) || (slave.waist < -95)) { + makeSpan(c, "Surgery enhanced.", styles); + } else { + makeSpan(c, "All natural.", styles); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_lactation(slave, c) { + if (slave.lactation === 1) { + makeSpan(c, "Lactating naturally.", "pink"); + } else if (slave.lactation === 2) { + makeSpan(c, "Heavy lactation.", "pink"); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_mods(slave, c) { + V.modScore = SlaveStatsChecker.modScore(slave); + if (slave.corsetPiercing === 0 && V.piercingScore < 3 && V.tatScore < 2) { + return; + } else if (V.modScore > 15 || (V.piercingScore > 8 && V.tatScore > 5)) { + makeSpan(c, "Extensive body mods."); + } else if (V.modScore > 7) { + makeSpan(c, "Noticeable body mods."); + } else { + makeSpan(c, "Light body mods."); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_age(slave, c) { + let r = makeSpan(c, "", "pink"); + if (V.showAgeDetail === 1) { + r.textContent += slave.actualAge.toString(); + } else if (slave.actualAge >= 18) { + r.textContent += helpers.getNumericRating(data.short.body.age, slave.actualAge); + } + + if (slave.actualAge !== slave.physicalAge) { + r.textContent += ` w ${slave.physicalAge}y-bdy`; + } + if (slave.visualAge !== slave.physicalAge) { + r.textContent += ` Lks${slave.visualAge}`; + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_face(slave, c) { + makeRatedStyledSpan(c, data.short.body.face, slave.face, 100, true); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_eyes(slave, c) { + if (!canSee(slave)) { + makeSpan(c, "Blind", "red"); + } else if (!canSeePerfectly(slave)) { + makeSpan(c, "Sight-", "yellow"); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_ears(slave, c) { + if (slave.hears === -2) { + makeSpan(c, "Deaf", "red"); + } else if ((slave.hears === -1) && (slave.earwear !== "hearing aids")) { + makeSpan(c, "Hearing-", "yellow"); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_lips(slave, c) { + makeRatedStyledSpan(c, data.short.body.lips, slave.lips, 0, true); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_teeth(slave, c) { + helpers.makeMappedStyledSpan(c, data.short.body.teeth, slave.teeth); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_muscles(slave, c) { + const h = helpers; + h.makeStyledSpan(c, h.getMultiNumericRating(data.short.body.muscles, [slave.muscles + 100, h.FSData.policy.PhysicalIdealist.active])); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_voice(slave, c) { + if (slave.voice === 0) { + makeSpan(c, "Mute", "red"); + } else { + helpers.makeMappedStyledSpan(c, data.short.accent, slave.accent); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_tits_ass(slave, c) { + const h = helpers; + h.makeStyledSpan(c, + h.getMultiNumericRating(data.short.body.titsAss, + [slave.boobs, slave.butt, h.FSData.policy.AssetExpansionist.active, slave.weight + 100, slave.muscles + 100])); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_hips(slave, c) { + const di = hipsAssRating(slave); + if (di >= 0) { + helpers.makeMappedStyledSpan(c, data.short.body.hipsAss, di); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_waist(slave, c) { + makeRatedStyledSpan(c, data.short.body.waist, slave.waist, 100, false); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_implants(slave, c) { + if ((slave.boobsImplant === 0) && (slave.buttImplant === 0) && (slave.waist >= -95) && (slave.lipsImplant === 0) && (slave.faceImplant <= 5) && (slave.bellyImplant === -1)) { + makeSpan(c, "Natr", "pink"); + } else { + makeSpan(c, "Impl", "pink"); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_lactation(slave, c) { + if (slave.lactation === 1) { + makeSpan(c, "Lact", "pink"); + } else if (slave.lactation === 2) { + makeSpan(c, "Lact", "pink"); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_mods(slave, c) { + V.modScore = SlaveStatsChecker.modScore(slave); + if (slave.corsetPiercing === 0 && V.piercingScore < 3 && V.tatScore < 2) { + return; + } else if (V.modScore > 15 || (V.piercingScore > 8 && V.tatScore > 5)) { + makeSpan(c, "Mods++"); + } else if (V.modScore > 7) { + makeSpan(c, "Mods+"); + } else { + makeSpan(c, "Mods"); + } + if (!jQuery.isEmptyObject(slave.brand)) { + makeSpan(c, "Br"); + } + } + + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_intelligence(slave, c) { + if (slave.fetish === "mindbroken") { + return; + } + const intelligence = slave.intelligence + slave.intelligenceImplant; + const educationStr = helpers.getNumericRating(data.short.mental.education, slave.intelligenceImplant + 15); + const intelligenceRating = helpers.getNumericRating(data.short.mental.intelligence, intelligence + 100); + makeSpan(c, `${intelligenceRating.desc}${educationStr}`, intelligenceRating.style, true, intelligence); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_skills(slave, c) { + const sd = data.short.skills; + let _SSkills = (slave.skill.anal + slave.skill.oral); + if (((_SSkills + slave.skill.whoring + slave.skill.entertainment) >= 400) && ((slave.vagina < 0) || (slave.skill.vaginal >= 100))) { + helpers.makeStyledSpan(c, sd.mss); + } else { + _SSkills += slave.skill.vaginal; + helpers.makeStyledSpan(c, helpers.getMultiNumericRating(sd.sex, [_SSkills, slave.vagina >= 0 ? 1 : 0]), Math.trunc(_SSkills), true); + helpers.makeRatedStyledSpan(c, sd.whoring, slave.skill.whoring, 0, true); + helpers.makeRatedStyledSpan(c, sd.entertainment, slave.skill.entertainment, 0, true); + } + if (slave.skill.combat > 0) { + helpers.makeStyledSpan(c, sd.fighter); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_prestige(slave, c) { + helpers.makeMappedStyledSpan(c, data.short.prestige, slave.prestige); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_porn_prestige(slave, c) { + helpers.makeMappedStyledSpan(c, data.short.pornPrestige, slave.porn.prestige); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_intelligence(slave, c) { + if (slave.fetish === "mindbroken") { + return; + } + const intelligence = slave.intelligence + slave.intelligenceImplant; + const educationStr = helpers.getNumericRating(data.long.mental.education, slave.intelligenceImplant + 15); + const intelligenceRating = helpers.getNumericRating(data.long.mental.intelligence, intelligence + 100); + makeSpan(c, `${intelligenceRating.desc}${educationStr}`, intelligenceRating.style, true, intelligence); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_skills(slave, c) { + const sd = data.long.skills; + let _SSkills = (slave.skill.anal + slave.skill.oral); + if (((_SSkills + slave.skill.whoring + slave.skill.entertainment) >= 400) && ((slave.vagina < 0) || (slave.skill.vaginal >= 100))) { + helpers.makeStyledSpan(c, sd.mss); + } else { + _SSkills += slave.skill.vaginal; + helpers.makeStyledSpan(c, helpers.getMultiNumericRating(sd.sex, [_SSkills, slave.vagina >= 0 ? 1 : 0]), Math.trunc(_SSkills), true); + helpers.makeRatedStyledSpan(c, sd.whoring, slave.skill.whoring, 0, true); + helpers.makeRatedStyledSpan(c, sd.entertainment, slave.skill.entertainment, 0, true); + } + if (slave.skill.combat > 0) { + helpers.makeStyledSpan(c, sd.fighter); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_prestige(slave, c) { + helpers.makeMappedStyledSpan(c, data.long.prestige, slave.prestige); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_porn_prestige(slave, c) { + helpers.makeMappedStyledSpan(c, data.long.pornPrestige, slave.porn.prestige); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_clothes(slave, c) { + makeSpan(c, helpers.getExactRating(data.long.clothes, slave.clothes, 'Naked.')); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_collar(slave, c) { + helpers.makeMappedSpan(c, data.long.accessory.collar, slave.collar); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_belly(slave, c) { + helpers.makeMappedSpan(c, data.long.accessory.belly, slave.bellyAccessory); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_arms(slave, c) { + if (["hand gloves", "elbow gloves"].includes(slave.armAccessory)) { + makeSpan(c, slave.armAccessory, undefined, true); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_legs(slave, c) { + if (slave.legAccessory === "short stockings") { + makeSpan(c, "Short stockings."); + } else if (slave.legAccessory === "long stockings") { + makeSpan(c, "Long stockings."); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_shoes(slave, c) { + if (["boots", "extreme heels", "extreme platform heels", "flats", "heels", "platform heels", "platform shoes", "pumps"].includes(slave.shoes)) { + makeSpan(c, slave.shoes, undefined, true); + } else if (slave.heels === 1) { + makeSpan(c, "Crawling.", "yellow"); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_chastity(slave, c) { + if (slave.chastityAnus === 1 && slave.chastityPenis === 1 && slave.chastityVagina === 1) { + makeSpan(c, "Full chastity."); + } else if (slave.chastityPenis === 1 && slave.chastityVagina === 1) { + makeSpan(c, "Genital chastity."); + } else if ((slave.chastityAnus === 1 && slave.chastityVagina === 1) || (slave.chastityAnus === 1 && slave.chastityPenis === 1)) { + makeSpan(c, "Combined chastity."); + } else if (slave.chastityVagina === 1) { + makeSpan(c, "Vaginal chastity."); + } else if (slave.chastityPenis === 1) { + makeSpan(c, "Chastity cage."); + } else if (slave.chastityAnus === 1) { + makeSpan(c, "Anal chastity."); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_vaginal_acc(slave, c) { + if (slave.vaginalAttachment !== "vibrator") { + helpers.makeMappedSpan(c, data.long.accessory.vaginal, slave.vaginalAccessory); + } + if (slave.vaginalAttachment !== "none") { + switch (slave.vaginalAttachment) { + case "vibrator": + makeSpan(c, "Vibrating dildo."); + break; + } + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_dick_acc(slave, c) { + switch (slave.dickAccessory) { + case "sock": + makeSpan(c, "Cock sock."); + break; + case "bullet vibrator": + makeSpan(c, "Frenulum bullet vibrator."); + break; + case "smart bullet vibrator": + makeSpan(c, "Smart frenulum bullet vibrator."); + break; + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_buttplug(slave, c) { + helpers.makeMappedSpan(c, data.long.accessory.buttplug, slave.buttplug); + helpers.makeMappedSpan(c, data.long.accessory.buttplugAttachment, slave.buttplugAttachment); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_fetish(slave, c) { + function fetishStr(slave) { + const tbl = data.short.fetish[slave.fetish]; + if (!tbl || typeof tbl === 'string') { + return tbl; + } + return helpers.getNumericRating(tbl, slave.fetishStrength); + } + makeSpan(c, fetishStr(slave), "lightcoral", true, slave.fetishStrength); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_attraction(slave, c) { + const sd = data.short.sexDrive; + // check for special cases first + if (slave.energy > 95 && slave.attrXX > 95 && slave.attrXY > 95) { + helpers.makeStyledSpan(c, sd.synergy.nymphomni); + } else if (slave.attrXX > 95 && slave.attrXY > 95) { + helpers.makeStyledSpan(c, sd.synergy.omni); + } else { + helpers.makeRatedStyledSpan(c, sd.XY, slave.attrXY, 0, true); + helpers.makeRatedStyledSpan(c, sd.XX, slave.attrXX, 0, true); + helpers.makeRatedStyledSpan(c, sd.energy, slave.energy, 0, true); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_smart_fetish(slave, c) { + const s = smartFetishStr(slave, data.short.smartPiercing); + if (s) { + makeSpan(c, s); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_smart_attraction(slave, c) { + /* + if (slave.attrKnown === 1) { + if ((slave.attrXX < 100) && (slave.clitSetting === "women")) { + makeSpan(c, `SP: women.`); + } else if ((slave.attrXY < 100) && (slave.clitSetting === "men")) { + makeSpan(c, `SP: men.`); + } + } else { + if (slave.clitSetting === "women") { + makeSpan(c, `SP: women.`); + } else if (slave.clitSetting === "men") { + makeSpan(c, `SP: men.`); + } + }*/ + const s = smartAttractionStr(slave, data.short.smartPiercing); + if (s) { + makeSpan(c, s); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_behavior_flaw(slave, c) { + helpers.makeMappedSpan(c, data.short.mental.behavioralFlaw, slave.behavioralFlaw, "red"); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_sex_flaw(slave, c) { + helpers.makeMappedStyledSpan(c, data.short.mental.sexualFlaw, slave.sexualFlaw); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_behavior_quirk(slave, c) { + helpers.makeMappedSpan(c, data.short.mental.behavioralQuirk, slave.behavioralQuirk, "green"); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_sex_quirk(slave, c) { + helpers.makeMappedSpan(c, data.short.mental.sexualQuirk, slave.sexualQuirk, "green"); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_fetish(slave, c) { + function fetishStr(slave) { + const tbl = data.long.fetish[slave.fetish]; + if (!tbl || typeof tbl === 'string') { + return tbl; + } + return helpers.getNumericRating(tbl, slave.fetishStrength); + } + makeSpan(c, fetishStr(slave), "lightcoral", true, slave.fetishStrength); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_attraction(slave, c) { + const sd = data.long.sexDrive; + + // check for special cases first + if (slave.energy > 95 && slave.attrXX > 95 && slave.attrXY > 95) { + helpers.makeStyledSpan(c, sd.synergy.nymphomni); + } else if (slave.attrXX > 95 && slave.attrXY > 95) { + helpers.makeStyledSpan(c, sd.synergy.omni); + } else { + helpers.makeRatedStyledSpan(c, sd.XY, slave.attrXY, 0, true); + helpers.makeRatedStyledSpan(c, sd.XX, slave.attrXX, 0, true); + helpers.makeRatedStyledSpan(c, sd.energy, slave.energy, 0, true); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_smart_fetish(slave, c) { + const s = smartFetishStr(slave, data.long.smartPiercing); + if (s) { + makeSpan(c, s); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_smart_attraction(slave, c) { + const s = smartAttractionStr(slave, data.long.smartPiercing); + if (s) { + makeSpan(c, s); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_behavior_flaw(slave, c) { + helpers.makeMappedSpan(c, data.long.mental.behavioralFlaw, slave.behavioralFlaw, "red"); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_sex_flaw(slave, c) { + switch (slave.sexualFlaw) { + case "hates oral": + case "hates anal": + case "hates penetration": + case "shamefast": + makeSpan(c, slave.sexualFlaw, "red", true); + break; + case "idealistic": + case "repressed": + case "apathetic": + case "crude": + case "judgemental": + makeSpan(c, `Sexually ${slave.sexualFlaw}.`, "red"); + break; + case "cum addict": + case "anal addict": + case "attention whore": + makeSpan(c, slave.sexualFlaw, "yellow", true); + break; + case "breast growth": + makeSpan(c, `Breast obsession.`, "yellow"); + break; + case "abusive": + case "malicious": + makeSpan(c, `Sexually ${slave.sexualFlaw}.`, "yellow"); + break; + case "self hating": + makeSpan(c, `Self hatred.`, "yellow"); + break; + case "neglectful": + makeSpan(c, `Self neglectful.`, "yellow"); + break; + case "breeder": + makeSpan(c, `Breeding obsession.`, "yellow"); + break; + default: + slave.sexualFlaw = "none"; + break; + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_behavior_quirk(slave, c) { + switch (slave.behavioralQuirk) { + case "confident": + case "cutting": + case "funny": + case "fitness": + case "adores women": + case "adores men": + case "insecure": + case "sinful": + case "advocate": + makeSpan(c, slave.behavioralQuirk, "green", true); + break; + default: + slave.behavioralQuirk = "none"; + break; + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_sex_quirk(slave, c) { + switch (slave.sexualQuirk) { + case "gagfuck queen": + case "painal queen": + case "strugglefuck queen": + case "tease": + case "romantic": + case "perverted": + case "caring": + case "unflinching": + case "size queen": + makeSpan(c, slave.sexualQuirk, "green", true); + break; + default: + slave.sexualQuirk = "none"; + break; + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_family(slave, c) { + let res = ""; + let handled = 0; + if (slave.mother > 0) { + const _ssj = V.slaves.findIndex(s => s.ID === slave.mother); + if (_ssj !== -1) { + res += `${SlaveFullName(V.slaves[_ssj])}'s ${getPronouns(slave).daughter}`; + if (slave.relationshipTarget === V.slaves[_ssj].ID) { + const friendShipShort = relationshipTermShort(slave); + res += ` & ${friendShipShort}`; + handled = 1; + } + } + res += " "; + } else if (slave.mother === -1) { + res += `Your ${getPronouns(slave).daughter}`; + if (slave.relationship < -1) { + res += ` & ${PCrelationshipTerm(slave)}`; + handled = 1; + } + res += " "; + } else if (slave.mother in V.missingTable && V.showMissingSlavesSD && V.showMissingSlaves) { + res += `${V.missingTable[slave.mother].fullName}'s ${getPronouns(slave).daughter} `; + } + if (slave.father > 0 && slave.father !== slave.mother) { + const _ssj = V.slaves.findIndex(s => s.ID === slave.father); + if (_ssj !== -1) { + res += `${SlaveFullName(V.slaves[_ssj])}'s ${getPronouns(slave).daughter}`; + if (slave.relationshipTarget === V.slaves[_ssj].ID && handled !== 1) { + const friendShipShort = relationshipTermShort(slave); + res += ` & ${friendShipShort}`; + handled = 1; + } + } + res += " "; + } else if (slave.father === -1 && slave.mother !== -1) { + res += `Your ${getPronouns(slave).daughter}`; + if (slave.relationship < -1) { + res += ` & ${PCrelationshipTerm(slave)}`; + handled = 1; + } + res += " "; + } else if (slave.father in V.missingTable && slave.father !== slave.mother && V.showMissingSlavesSD && V.showMissingSlaves) { + res += `${V.missingTable[slave.father].fullName}'s ${getPronouns(slave).daughter}`; + } + if (slave.daughters === 1) { + let _ssj = V.slaves.findIndex(s => s.mother === slave.ID); + if (_ssj !== -1) { + res += `${SlaveFullName(V.slaves[_ssj])}'s mother`; + if (slave.relationshipTarget === V.slaves[_ssj].ID) { + const friendShipShort = relationshipTermShort(slave); + res += ` & ${friendShipShort}`; + handled = 1; + } + } + res += " "; + _ssj = V.slaves.findIndex(s => s.father === slave.ID); + if (_ssj !== -1) { + res += `${SlaveFullName(V.slaves[_ssj])}'s father`; + if (slave.relationshipTarget === V.slaves[_ssj].ID && handled !== 1) { + const friendShipShort = relationshipTermShort(slave); + res += ` & ${friendShipShort}`; + handled = 1; + } + } + res += " "; + } else if (slave.daughters > 1) { + res += `multiple daughters `; + } + if (slave.sisters === 1) { + const _ssj = V.slaves.findIndex(s => areSisters(s, slave) > 0); + if (_ssj !== -1) { + res += `${SlaveFullName(V.slaves[_ssj])}'s ${getPronouns(slave).sister}`; + if (slave.relationshipTarget === V.slaves[_ssj].ID) { + const friendShipShort = relationshipTermShort(slave); + res += `& ${friendShipShort}`; + handled = 1; + } + } + res += " "; + } else if (slave.sisters > 1) { + res += `multiple sisters `; + } + if (slave.relationship > 0 && handled !== 1) { + const _ssj = V.slaves.findIndex(s => s.ID === slave.relationshipTarget); + if (_ssj !== -1) { + res += `${SlaveFullName(V.slaves[_ssj])}'s`; + const friendShipShort = relationshipTermShort(slave); + res += ` ${friendShipShort}`; + } + } else if (slave.relationship === -3 && slave.mother !== -1 && slave.father !== -1) { + res += `Your ${getPronouns(slave).wife}`; + } else if (slave.relationship === -2) { + res += `E Bonded`; + } else if (slave.relationship === -1) { + res += `E Slut`; + } + helpers.makeSpan(c, res); + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_clone(slave, c) { + if (slave.clone !== 0) { + makeSpan(c, "Clone"); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function short_rival(slave, c) { + if (slave.rivalry !== 0) { + const block = makeBlock(c, "lightsalmon"); + const _ssj = V.slaves.findIndex(s => s.ID === slave.rivalryTarget); + if (_ssj !== -1) { + if (slave.rivalry <= 1) { + block.textContent = `Disl ${SlaveFullName(V.slaves[_ssj])}`; + } else if (slave.rivalry <= 2) { + block.textContent = `${SlaveFullName(V.slaves[_ssj])}'s rival`; + } else { + block.textContent = `Hates ${SlaveFullName(V.slaves[_ssj])}`; + } + } + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_family(slave, c) { + let handled = 0; + const block = makeBlock(); + if (slave.mother > 0) { + const _ssj = V.slaves.findIndex(s => s.ID === slave.mother); + if (_ssj !== -1) { + addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); + const tmpSpan = makeSpan(block, getPronouns(slave).daughter, "lightgreen"); + if (slave.relationshipTarget === V.slaves[_ssj].ID) { + const friendShipShort = relationshipTerm(slave); + tmpSpan.textContent += ` and ${friendShipShort}`; + handled = 1; + } + tmpSpan.textContent += '.'; + } + } else if (slave.mother === -1) { + addText(block, `Your `); + if (slave.relationship < -1) { + makeSpan(block, `${getPronouns(slave).daughter} and ${PCrelationshipTerm(slave)}.`, "lightgreen"); + handled = 1; + } else { + makeSpan(block, `${getPronouns(slave).daughter}.`, "lightgreen"); + } + } else if (slave.mother in V.missingTable && V.showMissingSlavesSD && V.showMissingSlaves) { + addText(block, `${V.missingTable[slave.mother].fullName}'s `); + makeSpan(block, `${getPronouns(slave).daughter}.`, "lightgreen"); + } + if (slave.father > 0 && slave.father !== slave.mother) { + const _ssj = V.slaves.findIndex(s => s.ID === slave.father); + if (_ssj !== -1) { + addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); + const tmpSpan = makeSpan(block, getPronouns(slave).daughter, "lightgreen"); + if (slave.relationshipTarget === V.slaves[_ssj].ID) { + const friendShipShort = relationshipTerm(slave); + tmpSpan.textContent += ` and ${friendShipShort}`; + handled = 1; + } + tmpSpan.textContent += '.'; + } + } else if (slave.father === -1 && slave.father !== slave.mother) { + addText(block, `Your `); + if (slave.relationship < -1) { + makeSpan(block, `${getPronouns(slave).daughter} and ${PCrelationshipTerm(slave)}.`, "lightgreen"); + handled = 1; + } else { + makeSpan(block, `${getPronouns(slave).daughter}.`, "lightgreen"); + } + } else if (slave.father in V.missingTable && slave.father !== slave.mother && V.showMissingSlavesSD && V.showMissingSlaves) { + addText(block, `${V.missingTable[slave.father].fullName}'s `); + makeSpan(block, `${getPronouns(slave).daughter}.`, "lightgreen"); + } + if (areSisters(V.PC, slave) > 0) { + addText(block, `Your `); + if (slave.relationship < -1) { + makeSpan(block, `${relativeTerm(V.PC, slave)} and ${PCrelationshipTerm(slave)}.`, "lightgreen"); + handled = 1; + } else { + makeSpan(block, `${relativeTerm(V.PC, slave)}.`, "lightgreen"); + } + } + if (slave.daughters === 1) { + let _ssj = V.slaves.findIndex(s => s.mother === slave.ID); + if (_ssj !== -1) { + addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); + const tmpSpan = makeSpan(block, "mother", "lightgreen"); + if (slave.relationshipTarget === V.slaves[_ssj].ID) { + const friendShipShort = relationshipTerm(slave); + tmpSpan.textContent += ` and ${friendShipShort}`; + handled = 1; + } + tmpSpan.textContent += '.'; + } + _ssj = V.slaves.findIndex(s => s.father === slave.ID); + if (_ssj !== -1) { + addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); + const tmpSpan = makeSpan(block, "father", "lightgreen"); + if (slave.relationshipTarget === V.slaves[_ssj].ID) { + const friendShipShort = relationshipTerm(slave); + tmpSpan.textContent += ` and ${friendShipShort}`; + handled = 1; + } + tmpSpan.textContent += '.'; + } + } else if (slave.daughters > 1) { + if (slave.daughters > 10) { + makeSpan(block, "Has tons of daughters.", "lightgreen"); + } else if (slave.daughters > 5) { + makeSpan(block, "Has many daughters.", "lightgreen"); + } else { + makeSpan(block, "Has several daughters.", "lightgreen"); + } + } + if (slave.sisters === 1) { + const _ssj = V.slaves.findIndex(s => areSisters(s, slave) > 0); + if (_ssj !== -1) { + addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); + const tmpSpan = makeSpan(block, getPronouns(slave).sister, "lightgreen"); + if (slave.relationshipTarget === V.slaves[_ssj].ID) { + const friendShipShort = relationshipTerm(slave); + tmpSpan.textContent += ` and ${friendShipShort}`; + handled = 1; + } + tmpSpan.textContent += '.'; + } + } else if (slave.sisters > 1) { + if (slave.sisters > 10) { + makeSpan(block, "One of many sisters.", "lightgreen"); + } else if (slave.sisters > 5) { + makeSpan(block, "Has many sisters.", "lightgreen"); + } else { + makeSpan(block, "Has several sisters.", "lightgreen"); + } + } + if (slave.relationship > 0 && handled !== 1) { + const _ssj = V.slaves.findIndex(s => s.ID === slave.relationshipTarget); + if (_ssj !== -1) { + const friendship = relationshipTerm(slave); + addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); + makeSpan(block, `${friendship}.`, "lightgreen"); + } + } else if (slave.relationship === -3 && slave.mother !== -1 && slave.father !== -1 && areSisters(V.PC, slave) === 0) { + makeSpan(block, `Your ${getPronouns(slave).wife}.`, "lightgreen"); + } else if (slave.relationship === -2) { + makeSpan(block, "Emotionally bonded to you.", "lightgreen"); + } else if (slave.relationship === -1) { + makeSpan(block, "Emotional slut.", "lightgreen"); + } + + if (block.textContent.length > 0) { + c.appendChild(block); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_clone(slave, c) { + if (slave.clone !== 0) { + makeSpan(c, `Clone of ${slave.clone}.`, "skyblue"); + } + } + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + function long_rival(slave, c) { + if (slave.rivalry !== 0) { + const block = makeBlock(c); + const _ssj = V.slaves.findIndex(s => s.ID === slave.rivalryTarget); + if (_ssj !== -1) { + if (slave.rivalry <= 1) { + makeSpan(block, "Dislikes", "lightsalmon"); + block.appendChild(document.createTextNode(` ${SlaveFullName(V.slaves[_ssj])}.`)); + } else if (slave.rivalry <= 2) { + block.appendChild(document.createTextNode(`${SlaveFullName(V.slaves[_ssj])}'s `)); + makeSpan(block, "rival.", "lightsalmon"); + } else { + makeSpan(block, "Hates", "lightsalmon"); + block.appendChild(document.createTextNode(` ${SlaveFullName(V.slaves[_ssj])}.`)); + } + } + } + } + + return { + long: { + health: long_health, + illness: long_illness, + tired: long_tired, + age: long_age, + face: long_face, + eyes: long_eyes, + ears: long_ears, + lips: long_lips, + teeth: long_teeth, + muscles: long_muscles, + voice: long_voice, + tits_ass: long_tits_ass, + hips: long_hips, + waist: long_waist, + implants: long_implants, + lactation: long_lactation, + mods: long_mods, + intelligence: long_intelligence, + skills: long_skills, + prestige: long_prestige, + porn_prestige: long_porn_prestige, + clothes: long_clothes, + collar: long_collar, + belly: long_belly, + arms: long_arms, + legs: long_legs, + shoes: long_shoes, + chastity: long_chastity, + vaginal_acc: long_vaginal_acc, + dick_acc: long_dick_acc, + buttplug: long_buttplug, + fetish: long_fetish, + attraction: long_attraction, + smart_fetish: long_smart_fetish, + smart_attraction: long_smart_attraction, + behavior_flaw: long_behavior_flaw, + sex_flaw: long_sex_flaw, + behavior_quirk: long_behavior_quirk, + sex_quirk: long_sex_quirk, + family: long_family, + clone: long_clone, + rival: long_rival + }, + short: { + health: short_health, + illness: short_illness, + tired: short_tired, + age: short_age, + face: short_face, + eyes: short_eyes, + ears: short_ears, + lips: short_lips, + teeth: short_teeth, + muscles: short_muscles, + voice: short_voice, + tits_ass: short_tits_ass, + hips: short_hips, + waist: short_waist, + implants: short_implants, + lactation: short_lactation, + mods: short_mods, + intelligence: short_intelligence, + skills: short_skills, + prestige: short_prestige, + porn_prestige: short_porn_prestige, +/* clothes: short_clothes, + collar: short_collar, + belly: short_belly, + arms: short_arms, + legs: short_legs, + shoes: short_shoes, + chastity: short_chastity, + vaginal_acc: short_vaginal_acc, + dick_acc: short_dick_acc, + buttplug: short_buttplug, +*/ + fetish: short_fetish, + attraction: short_attraction, + smart_fetish: short_smart_fetish, + smart_attraction: short_smart_attraction, + behavior_flaw: short_behavior_flaw, + sex_flaw: short_sex_flaw, + behavior_quirk: short_behavior_quirk, + sex_quirk: short_sex_quirk, + family: short_family, + clone: short_clone, + rival: short_rival + } + }; + }(); + + return { + helpers: helpers, + bits: bits + }; +}(); diff --git a/src/js/slaveSummaryWidgets.js b/src/js/slaveSummaryWidgets.js index a5b28aa5561a5c738c92c4416a49d313a728868f..ad5e8a32fa9b911f97961fee7568951fa964107f 100644 --- a/src/js/slaveSummaryWidgets.js +++ b/src/js/slaveSummaryWidgets.js @@ -1,4514 +1,1008 @@ -/* eslint-disable camelcase */ +App.UI.SlaveSummaryRenderers = function() { -window.SlaveSummary = (function() { - /** @type {DocumentFragment} */ - let res; + const bits = App.UI.SlaveSummaryImpl.bits; + const helpers = App.UI.SlaveSummaryImpl.helpers; + const data = App.Data.SlaveSummary; - /** - * @param {App.Entity.SlaveState} slave - * @returns {DocumentFragment} */ - function SlaveSummary(slave) { - res = document.createDocumentFragment(); - let para = makeParagraph(res); - - if (V.abbreviateDevotion === 1) { - short_devotion(slave, para); - } else if (V.abbreviateDevotion === 2) { - long_devotion(slave, para); - } - if (slave.fuckdoll === 0) { - if (V.abbreviateRules === 1) { - short_rules(slave, para); - } else if (V.abbreviateRules === 2) { - long_rules(slave, para); + const shortRenderers = { + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + */ + devotion: function(slave, c) { + const makeSpan = helpers.makeSpan; + if (slave.fetish === "mindbroken") { + makeSpan(c, "MB", "mindbroken"); + } else { + helpers.makeRatedStyledSpan(c, data.short.mental.devotion, slave.devotion, 100, true); + helpers.makeStyledSpan(c, helpers.getMultiNumericRating(data.short.mental.trust, [slave.trust + 100, slave.devotion + 100]), + slave.trust, true); } - } - if (V.abbreviateDiet === 1) { - short_weight(slave, para); - } else if (V.abbreviateDiet === 2) { - long_weight(slave, para); - } - if (V.abbreviateDiet === 1) { - short_diet(slave, para); - } else if (V.abbreviateDiet === 2) { - long_diet(slave, para); - } - if (V.abbreviateHealth === 1) { - short_health(slave, para); - short_illness(slave, para); - short_tired(slave, para); - } else if (V.abbreviateHealth === 2) { - long_health(slave, para); - long_illness(slave, para); - long_tired(slave, para); - } - if (V.abbreviateDrugs === 1) { - short_drugs(slave, para); - } else if (V.abbreviateDrugs === 2) { - long_drugs(slave, para); - } - - para = makeParagraph(res); - para.classList.add("pink"); + }, - makeSpan(para, `${capFirstChar(SlaveTitle(slave))}${V.abbreviatePhysicals === 2 ? '.' : ''}`, ["coral", "strong"]); - if (V.seeRace === 1 && V.abbreviateRace !== 0) { - makeSpan(para, V.abbreviateRace === 1 ? short_race(slave) : long_race(slave), "tan"); - } - if (V.abbreviateNationality !== 0) { - makeSpan(para, V.abbreviateNationality === 1 ? short_nationality(slave) : long_nationality(slave), "tan"); - } - makeSpan(para, V.abbreviatePhysicals === 1 ? short_skin(slave) : `${capFirstChar(slave.skin)} skin.`); - if (V.abbreviateGenitalia === 1) { - short_genitals(slave, para); - } else if (V.abbreviateGenitalia === 2) { - long_genitals(slave, para); - } - if (V.abbreviatePhysicals === 1) { - short_age(slave, para); - short_face(slave, para); - short_eyes(slave, para); - short_ears(slave, para); - if (slave.markings !== "none") { - makeSpan(para, "Markings"); + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + rules: function(slave, c) { + const makeSpan = helpers.makeSpan; + const styles = "strong"; + switch (slave.rules.living) { + case "luxurious": + makeSpan(c, "LS:Lux", styles); + break; + case "normal": + makeSpan(c, "LS:Nor", styles); + break; + default: + makeSpan(c, "LS:Spa", styles); + break; } - short_lips(slave, para); - short_teeth(slave, para); - short_muscles(slave, para); - addText(para, App.Desc.shortLimbs(slave)); - short_voice(slave, para); - short_tits_ass(slave, para); - short_hips(slave, para); - short_waist(slave, para); - short_implants(slave, para); - short_lactation(slave, para); - short_mods(slave, para); - } else if (V.abbreviatePhysicals === 2) { - long_age(slave, para); - long_face(slave, para); - long_eyes(slave, para); - long_ears(slave, para); - long_lips(slave, para); - long_teeth(slave, para); - long_muscles(slave, para); - makeSpan(para, App.Desc.longLimbs(slave)); - long_voice(slave, para); - long_tits_ass(slave, para); - long_hips(slave, para); - long_waist(slave, para); - long_implants(slave, para); - long_lactation(slave, para); - long_mods(slave, para); - if (!jQuery.isEmptyObject(slave.brand)) { - makeSpan(para, `Branded.`); + if (canTalk(slave, false)) { + switch (slave.rules.speech) { + case "permissive": + makeSpan(c, "SpR:P", styles); + break; + case "accent elimination": + makeSpan(c, "SpR:NoAcc", styles); + break; + case "language lessons": + makeSpan(c, "SpR:LL", styles); + break; + default: + makeSpan(c, "SpR:R", styles); + break; + } + } + switch (slave.rules.relationship) { + case "permissive": + makeSpan(c, "ReR:P", styles); + break; + case "just friends": + makeSpan(c, "ReR:Fr", styles); + break; + default: + makeSpan(c, "ReR:R", styles); + break; } - } - if (V.abbreviateHormoneBalance === 1) { - if (slave.hormoneBalance <= -21) { - makeSpan(para, "HB:M", ["deepskyblue", "strong"]); - } else if (slave.hormoneBalance <= 20) { - makeSpan(para, "HB:N", ["pink", "strong"]); - } else if (slave.hormoneBalance <= 500) { - makeSpan(para, "HB:F", ["pink", "strong"]); + switch (slave.rules.punishment) { + case "confinement": + makeSpan(c, "Pun:Conf", styles); + break; + case "whipping": + makeSpan(c, "Pun:Whip", styles); + break; + case "chastity": + makeSpan(c, "Pun:Chas", styles); + break; + default: + makeSpan(c, "Pun:Situ", styles); + break; } - } else if (V.abbreviateHormoneBalance === 2) { - const colorClass = slave.hormoneBalance <= -21 ? "deepskyblue" : "pink"; - let desc = ""; - if (slave.hormoneBalance < -400) { - desc = `Overwhelmingly masculine`; - } else if (slave.hormoneBalance <= -300) { - desc = `Extremely masculine`; - } else if (slave.hormoneBalance <= -200) { - desc = `Heavily masculine`; - } else if (slave.hormoneBalance <= -100) { - desc = `Very masculine`; - } else if (slave.hormoneBalance <= -21) { - desc = `Masculine`; - } else if (slave.hormoneBalance <= 20) { - desc = `Neutral`; - } else if (slave.hormoneBalance <= 99) { - desc = `Feminine`; - } else if (slave.hormoneBalance <= 199) { - desc = `Very feminine`; - } else if (slave.hormoneBalance <= 299) { - desc = `Heavily feminine`; - } else if (slave.hormoneBalance <= 399) { - desc = `Extremely feminine`; - } else if (slave.hormoneBalance <= 500) { - desc = `Overwhelmingly feminine`; + switch (slave.rules.reward) { + case "relaxation": + makeSpan(c, "Rew:Relx", styles); + break; + case "drugs": + makeSpan(c, "Rew:Drug", styles); + break; + case "orgasm": + makeSpan(c, "Rew:Orga", styles); + break; + default: + makeSpan(c, "Rew:Situ", styles); + break; } - makeSpan(para, desc + " hormone balance.", colorClass); - } + makeSpan(c, "MaR:" + App.Utils.releaseSummaryShort(slave), styles); + }, - para = makeParagraph(res); - if (V.abbreviateSkills === 1) { - short_intelligence(slave, para); - short_skills(slave, para); - short_prestige(slave, para); - short_porn_prestige(slave, para); - } else if (V.abbreviateSkills === 2) { - long_intelligence(slave, para); - long_skills(slave, para); - long_prestige(slave, para); - long_porn_prestige(slave, para); - } - if (V.abbreviateMental === 1) { - if (slave.fetish !== "mindbroken") { - if (slave.fetishKnown === 1) { - short_fetish(slave, para); + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + health: function(slave, c) { + const b = bits.short; + b.health(slave, c); + b.illness(slave, c); + b.tired(slave, c); + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + weight: function(slave, c) { + helpers.makeStyledSpan(c, helpers.getMultiNumericRating(data.short.body.weight, + [slave.weight + 100, helpers.FSData.policy.HedonisticDecadence.active, slave.hips + 2]), slave.weight, true); + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + genitalia: function(slave, c) { + const makeSpan = helpers.makeSpan; + if (slave.dick > 0) { + let dickDesc = slave.balls === 0 ? "Geld" : ""; + const dickBallsDesc = helpers.getMultiNumericRating(data.short.body.genitalia.dickBalls, [slave.dick, slave.balls]); + if (dickBallsDesc) { + dickDesc += ` ${dickBallsDesc}`; } - if (slave.attrKnown === 1) { - short_attraction(slave, para); + if (dickDesc) { + helpers.makeSpan(c, dickDesc, "pink"); } } - if (slave.clitPiercing === 3) { - short_smart_fetish(slave, para); - short_smart_attraction(slave, para); + if (slave.vagina === 0) { + makeSpan(c, "VV", "lime"); + } else if ((slave.pregKnown === 1) && canWalk(slave) && (slave.clothes === "no clothing" || slave.clothes === "body oil") && (slave.shoes === "none")) { + makeSpan(c, "NBP", "pink"); + } + if (slave.anus === 0) { + makeSpan(c, "AV", "lime"); + } + const holesDesc = helpers.getMultiNumericRating(data.long.body.genitalia.holes, [slave.vagina, slave.anus]); + if (holesDesc) { + makeSpan(c, holesDesc, "pink"); + } + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + diet: function(slave, c) { + const style = ["teal", "strong"]; + helpers.makeMappedSpan(c, data.short.diet, slave.diet, style); + helpers.makeMappedSpan(c, data.short.specialDiet, slave.dietCum + 3 * slave.dietMilk, style); + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + drugs: function(slave, c) { + let drugDesc = data.short.drugs[slave.drugs]; + const makeSpan = helpers.makeSpan; + if (drugDesc) { + makeSpan(c, "Dr:" + drugDesc, ["tan", "strong"]); + } + if (slave.curatives === 2) { + makeSpan(c, "Cura", ["lightgreen", "strong"]); + } else if (slave.curatives === 1) { + makeSpan(c, "Prev", ["lightgreen", "strong"]); + } + if (slave.aphrodisiacs !== 0) { + if (slave.aphrodisiacs === 1) { + makeSpan(c, "Aph", ["lightblue", "strong"]); + } else if (slave.aphrodisiacs === 2) { + makeSpan(c, "Aph++", ["lightblue", "strong"]); + } else { + makeSpan(c, "Anaph", ["lightblue", "strong"]); + } + } + if (slave.addict !== 0) { + makeSpan(c, "Add", "cyan"); + } + let styles = ["lightsalmon", "strong"]; + if (slave.hormones > 1) { + makeSpan(c, "Ho:F+", styles); + } else if (slave.hormones > 0) { + makeSpan(c, "Ho:F", styles); + } else if (slave.hormones < -1) { + makeSpan(c, "Ho:M+", styles); + } else if (slave.hormones < 0) { + makeSpan(c, "Ho:M", styles); + } + + styles = ["mediumseagreen", "strong"]; + if ((slave.bellyImplant > -1)) { + makeSpan(c, "Belly Imp", styles); + } else if (((slave.preg <= -2) || (slave.ovaries === 0)) && (slave.vagina !== -1)) { + makeSpan(c, "Barr", styles); + } else if (slave.pubertyXX === 0 && (slave.ovaries === 1 || slave.mpreg === 1)) { + makeSpan(c, "Prepub", styles); + } else if (slave.ovaryAge >= 47 && (slave.ovaries === 1 || slave.mpreg === 1)) { + makeSpan(c, "Meno", styles); + } else if (slave.pregWeek < 0) { + makeSpan(c, "Postpartum", styles); + } else if (slave.preg === -1) { + makeSpan(c, "CC", styles); + } else if (slave.preg === 0 && (slave.ovaries === 1 || slave.mpreg === 1)) { + makeSpan(c, "Fert+", styles); + } else if (((slave.preg < slave.pregData.normalBirth / 10) && (slave.preg > 0) && slave.pregKnown === 0) || slave.pregWeek === 1) { + makeSpan(c, "Preg?", styles); + } else if ((slave.preg >= 36) && (slave.broodmother > 0)) { + makeSpan(c, "Perm preg", styles); + } else if (slave.pregKnown === 1) { + makeSpan(c, `${slave.pregWeek} wks preg`, styles); + } + if (slave.induce === 1) { + makeSpan(c, "Early Labor", ["orange", "strong"]); + } + if (slave.pubertyXY === 0 && slave.balls > 0) { + makeSpan(c, "Prepub balls", "strong"); + } + if (slave.balls > 0 && slave.vasectomy === 1) { + makeSpan(c, "Vasect", "strong"); + } + styles = ["springgreen", "strong"]; + if (slave.inflation === 3) { + makeSpan(c, `8 ltr ${slave.inflationType}`, styles); + } else if (slave.inflation === 2) { + makeSpan(c, `4 ltr ${slave.inflationType}`, styles); + } else if (slave.inflation === 1) { + makeSpan(c, `2 ltr ${slave.inflationType}`, styles); + } else if (slave.bellyFluid > 0) { + makeSpan(c, `${slave.bellyFluid}ccs ${slave.inflationType}`, styles); + } + }, + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + physicals: function(slave, c) { + const b = bits.short; + b.age(slave, c); + b.face(slave, c); + b.eyes(slave, c); + b.ears(slave, c); + if (slave.markings !== "none") { + helpers.makeSpan(c, "Markings"); + } + b.lips(slave, c); + b.teeth(slave, c); + b.muscles(slave, c); + helpers.addText(c, App.Desc.shortLimbs(slave)); + b.voice(slave, c); + b.tits_ass(slave, c); + b.hips(slave, c); + b.waist(slave, c); + b.implants(slave, c); + b.lactation(slave, c); + b.mods(slave, c); + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + hormoneBalance: function(slave, c) { + if (slave.hormoneBalance <= -21) { + helpers.makeSpan(c, "HB:M", ["deepskyblue", "strong"]); + } else if (slave.hormoneBalance <= 20) { + helpers.makeSpan(c, "HB:N", ["pink", "strong"]); + } else if (slave.hormoneBalance <= 500) { + helpers.makeSpan(c, "HB:F", ["pink", "strong"]); } - short_behavior_flaw(slave, para); - short_sex_flaw(slave, para); - short_behavior_quirk(slave, para); - short_sex_quirk(slave, para); - } else if (V.abbreviateMental === 2) { + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + mental: function(slave, c) { + const b = bits.short; if (slave.fetish !== "mindbroken") { if (slave.fetishKnown === 1) { - long_fetish(slave, para); + b.fetish(slave, c); } if (slave.attrKnown === 1) { - long_attraction(slave, para); + b.attraction(slave, c); } } if (slave.clitPiercing === 3) { - long_smart_fetish(slave, para); - long_smart_attraction(slave, para); - } - long_behavior_flaw(slave, para); - long_sex_flaw(slave, para); - long_behavior_quirk(slave, para); - long_sex_quirk(slave, para); - } - if (slave.custom.label) { - makeSpan(res, `${capFirstChar(slave.custom.label)}.`, ["yellow", "strong"]); - } - if ((slave.relationship !== 0) || (V.abbreviateClothes === 2) || (V.abbreviateRulesets === 2)) { - para = makeParagraph(res); - } - if (V.abbreviateMental === 1) { - makeSpan(para, short_extended_family(slave), "lightgreen"); - short_clone(slave, para); - short_rival(slave, para); - } else if (V.abbreviateMental === 2) { - long_extended_family(slave, para); - long_clone(slave, para); - long_rival(slave, para); - } - if (slave.fuckdoll === 0) { - if (V.abbreviateClothes === 2) { - const dressingBlock = makeBlock(para); - if (slave.choosesOwnClothes === 1) { - makeSpan(dressingBlock, `Dressing ${getPronouns(slave).himself}.`); - } - long_clothes(slave, dressingBlock); - long_collar(slave, dressingBlock); - long_belly(slave, dressingBlock); - if (hasAnyArms(slave)) { - long_arms(slave, dressingBlock); - } - if (hasAnyLegs(slave)) { - long_legs(slave, dressingBlock); - long_shoes(slave, dressingBlock); + b.smart_fetish(slave, c); + b.smart_attraction(slave, c); + } + b.behavior_flaw(slave, c); + b.sex_flaw(slave, c); + b.behavior_quirk(slave, c); + b.sex_quirk(slave, c); + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + skills: function(slave, c) { + const b = bits.short; + b.intelligence(slave, c); + b.skills(slave, c); + b.prestige(slave, c); + b.porn_prestige(slave, c); + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + race: function(slave, c) { + const s = data.short.race[slave.race]; + helpers.makeSpan(c, s ? s : helpers.firstThreeUc(slave.race), "tan"); + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + nationality: function(slave, c) { + let tmp = data.short.nationality[slave.nationality]; + if (!tmp && slave.nationality === "Zimbabwean") { + if (slave.race === "white") { + tmp = 'Rhodesian.'; + } else { + tmp = `${slave.nationality}.`; } - long_chastity(slave, dressingBlock); - long_vaginal_acc(slave, dressingBlock); - long_dick_acc(slave, dressingBlock); - long_buttplug(slave, dressingBlock); } - } - const RABlock = makeBlock(para); - rules_assistant(slave, RABlock); - if (V.abbreviateOrigins === 2 && slave.origin !== 0) { - origins(slave, res); - } - return res; - } + helpers.makeSpan(c, tmp ? tmp : slave.nationality.substr(0, 3), "tan"); + }, - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - */ - function short_devotion(slave, c) { - if (slave.fetish === "mindbroken") { - makeSpan(c, "MB", "mindbroken"); - } else if (slave.devotion < -95) { - makeSpan(c, "Hate", ["devotion", "hateful"], true, slave.devotion); - } else if (slave.devotion < -50) { - makeSpan(c, "Hate", ["devotion", "hateful"], true, slave.devotion); - } else if (slave.devotion < -20) { - makeSpan(c, "Res", ["devotion", "resistant"], true, slave.devotion); - } else if (slave.devotion <= 20) { - makeSpan(c, "Ambiv", ["devotion", "ambivalent"], true, slave.devotion); - } else if (slave.devotion <= 50) { - makeSpan(c, "Accept", ["devotion", "accept"], true, slave.devotion); - } else if (slave.devotion <= 95) { - makeSpan(c, "Devo", ["devotion", "devoted"], true, slave.devotion); - } else { - makeSpan(c, "Wor", ["devotion", "worship"], true, slave.devotion); - } - if (slave.fetish === "mindbroken") { - return; - } else if (slave.trust < -95) { - makeSpan(c, "ETerr", ["trust", "extremely-terrified"], true, slave.trust); - } else if (slave.trust < -50) { - makeSpan(c, "Terr", ["trust", "terrified"], true, slave.trust); - } else if (slave.trust < -20) { - makeSpan(c, "Fright", ["trust", "frightened"], true, slave.trust); - } else if (slave.trust <= 20) { - makeSpan(c, "Fear", ["trust", "fearful"], true, slave.trust); - } else if (slave.trust <= 50) { - if (slave.devotion < -20) { - makeSpan(c, "Caref", ["defiant", "careful"], true, slave.trust); - } else { - makeSpan(c, "Caref", ["trust", "careful"], true, slave.trust); - } - } else if (slave.trust < 95) { - if (slave.devotion < -20) { - makeSpan(c, "Bold", ["defiant", "bold"], true, slave.trust); - } else { - makeSpan(c, "Trust", ["trust", "trusting"], true, slave.trust); - } - } else { - if (slave.devotion < -20) { - makeSpan(c, "Defiant", ["defiant", "full"], true, slave.trust); - } else { - makeSpan(c, "VTrust", ["trust", "prof-trusting"], true, slave.trust); - } - } - } + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + skin: function(slave, c) { + const s = data.short.skin[slave.skin]; + helpers.makeSpan(c, s ? s : helpers.firstThreeUc(slave.skin)); + }, - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_devotion(slave, c) { - if (slave.fetish === "mindbroken") { - makeSpan(c, "Mindbroken.", "mindbroken"); - } else if (slave.devotion < -95) { - makeSpan(c, "Very hateful", ["devotion", "hateful"], true, slave.devotion); - } else if (slave.devotion < -50) { - makeSpan(c, "Hateful", ["devotion", "hateful"], true, slave.devotion); - } else if (slave.devotion < -20) { - makeSpan(c, "Resistant", ["devotion", "resistant"], true, slave.devotion); - } else if (slave.devotion <= 20) { - makeSpan(c, "Ambivalent", ["devotion", "ambivalent"], true, slave.devotion); - } else if (slave.devotion <= 50) { - makeSpan(c, "Accepting", ["devotion", "accept"], true, slave.devotion); - } else if (slave.devotion <= 95) { - makeSpan(c, "Devoted", ["devotion", "devoted"], true, slave.devotion); - } else { - makeSpan(c, "Worshipful", ["devotion", "worship"], true, slave.devotion); - } - if (slave.fetish === "mindbroken") { - return; - } else if (slave.trust < -95) { - makeSpan(c, "Extremely terrified", ["trust", "extremely-terrified"], true, slave.trust); - } else if (slave.trust < -50) { - makeSpan(c, "Terrified", ["trust", "terrified"], true, slave.trust); - } else if (slave.trust < -20) { - makeSpan(c, "Frightened", ["trust", "frightened"], true, slave.trust); - } else if (slave.trust <= 20) { - makeSpan(c, "Fearful", ["trust", "fearful"], true, slave.trust); - } else if (slave.trust <= 50) { - if (slave.devotion < -20) { - makeSpan(c, "Careful", ["defiant", "careful"], true, slave.trust); - } else { - makeSpan(c, "Careful", ["trust", "careful"], true, slave.trust); - } - } else if (slave.trust <= 95) { - if (slave.devotion < -20) { - makeSpan(c, "Bold", ["defiant", "bold"], true, slave.trust); - } else { - makeSpan(c, "Trusting", ["trust", "trusting"], true, slave.trust); - } - } else { - if (slave.devotion < -20) { - makeSpan(c, "Defiant", ["defiant", "full"], true, slave.trust); - } else { - makeSpan(c, "Profoundly trusting", ["trust", "prof-trusting"], true, slave.trust); - } - } - } + clothes: function() { }, - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_rules(slave, c) { - const styles = "strong"; - switch (slave.rules.living) { - case "luxurious": - makeSpan(c, "LS:Lux", styles); - break; - case "normal": - makeSpan(c, "LS:Nor", styles); - break; - default: - makeSpan(c, "LS:Spa", styles); - break; - } - if (canTalk(slave, false)) { - switch (slave.rules.speech) { - case "permissive": - makeSpan(c, "SpR:P", styles); - break; - case "accent elimination": - makeSpan(c, "SpR:NoAcc", styles); - break; - case "language lessons": - makeSpan(c, "SpR:LL", styles); - break; - default: - makeSpan(c, "SpR:R", styles); - break; + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + rulesets: function(slave, c) { + if (slave.useRulesAssistant === 0) { + helpers.makeSpan(c, "RA-Exmt", "lightgreen"); } - } - switch (slave.rules.relationship) { - case "permissive": - makeSpan(c, "ReR:P", styles); - break; - case "just friends": - makeSpan(c, "ReR:Fr", styles); - break; - default: - makeSpan(c, "ReR:R", styles); - break; - } - switch (slave.rules.punishment) { - case "confinement": - makeSpan(c, "Pun:Conf", styles); - break; - case "whipping": - makeSpan(c, "Pun:Whip", styles); - break; - case "chastity": - makeSpan(c, "Pun:Chas", styles); - break; - default: - makeSpan(c, "Pun:Situ", styles); - break; - } - switch (slave.rules.reward) { - case "relaxation": - makeSpan(c, "Rew:Relx", styles); - break; - case "drugs": - makeSpan(c, "Rew:Drug", styles); - break; - case "orgasm": - makeSpan(c, "Rew:Orga", styles); - break; - default: - makeSpan(c, "Rew:Situ", styles); - break; - } - makeSpan(c, "MaR:" + App.Utils.releaseSummaryShort(slave), styles); - } + }, - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_rules(slave, c) { - addText(c, `Living standard: ${slave.rules.living}. `); - if (canTalk(slave, false)) { - addText(c, `Speech rules: ${slave.rules.speech}. `); + origins: function() { }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + relations: function(slave, c) { + const b = bits.short; + b.family(slave, c); + b.clone(slave, c); + b.rival(slave, c); } - addText(c, `Relationship rules: ${slave.rules.relationship}. `); - addText(c, `Typical punishment: ${slave.rules.punishment}. `); - addText(c, `Typical reward: ${slave.rules.reward}. `); - addText(c, `Release rules: ${App.Utils.releaseSummaryLong(slave)}. `); - } - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_weight(slave, c) { - if (slave.weight < -95) { - makeSpan(c, "W---", ["red", "strong"], true, slave.weight); - } else if (slave.weight < -30) { - if (slave.hips < -1) { - makeSpan(c, "W--", "strong", true, slave.weight); - } else { - makeSpan(c, "W--", ["red", "strong>"], true, slave.weight); - } - } else if (slave.weight < -10) { - makeSpan(c, "W-", "strong", true, slave.weight); - } else if (slave.weight <= 10) { - makeSpan(c, "W", "strong", true, slave.weight); - } else if (slave.weight <= 30) { - makeSpan(c, "W+", "strong", true, slave.weight); - } else if (slave.weight <= 95) { - if (slave.hips > 1 || V.arcologies[0].FSHedonisticDecadence !== "unset") { - makeSpan(c, "W++", "strong", true, slave.weight); - } else { - makeSpan(c, "W++", ["red", "strong"], true, slave.weight); - } - } else if (slave.weight <= 130) { - if (slave.hips > 2 || V.arcologies[0].FSHedonisticDecadence !== "unset") { - makeSpan(c, "W+++", "strong", true, slave.weight); - } else { - makeSpan(c, "W+++", ["red", "strong"], true, slave.weight); + }; + + const longRenderers = { + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + devotion: function(slave, c) { + const makeSpan = helpers.makeSpan; + if (slave.fetish === "mindbroken") { + makeSpan(c, "Mindbroken.", "mindbroken"); + } else { + helpers.makeRatedStyledSpan(c, data.long.mental.devotion, slave.devotion, 100, true); + helpers.makeStyledSpan(c, helpers.getMultiNumericRating(data.long.mental.trust, [slave.trust + 100, slave.devotion + 100]), + slave.trust, true); + } + }, + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + health: function(slave, c) { + const b = bits.long; + b.health(slave, c); + b.illness(slave, c); + b.tired(slave, c); + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + weight: function(slave, c) { + helpers.makeStyledSpan(c, helpers.getMultiNumericRating(data.long.body.weight, + [slave.weight + 100, helpers.FSData.policy.HedonisticDecadence.active, slave.hips + 2]), slave.weight, true); + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + rules: function(slave, c) { + const addText = helpers.addText; + addText(c, `Living standard: ${slave.rules.living}. `); + if (canTalk(slave, false)) { + addText(c, `Speech rules: ${slave.rules.speech}. `); + } + addText(c, `Relationship rules: ${slave.rules.relationship}. `); + addText(c, `Typical punishment: ${slave.rules.punishment}. `); + addText(c, `Typical reward: ${slave.rules.reward}. `); + addText(c, `Release rules: ${App.Utils.releaseSummaryLong(slave)}. `); + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + genitalia: function(slave, c) { + if (slave.dick > 0) { + let dickDesc = slave.balls === 0 ? "Gelded." : ""; + const dickBallsDesc = helpers.getMultiNumericRating(data.long.body.genitalia.dickBalls, [slave.dick, slave.balls]); + if (dickBallsDesc) { + dickDesc += ` ${dickBallsDesc}`; + } + if (dickDesc) { + helpers.makeSpan(c, dickDesc, "pink"); + } } - } else if (slave.weight <= 160) { - if (V.arcologies[0].FSHedonisticDecadence !== "unset") { - makeSpan(c, "W++++", "strong", true, slave.weight); - } else { - makeSpan(c, "W++++", ["red", "strong"], true, slave.weight); + if (slave.vagina === 0) { + helpers.makeSpan(c, "Virgin.", "lime"); + } else if ((slave.pregKnown === 1) && canWalk(slave) && (slave.clothes === "no clothing" || slave.clothes === "body oil") && (slave.shoes === "none")) { + helpers.makeSpan(c, "Naked, barefoot, and pregnant.", "pink"); } - } else if (slave.weight <= 190) { - if (V.arcologies[0].FSHedonisticDecadence !== "unset") { - makeSpan(c, "W+++++", "strong", true, slave.weight); - } else { - makeSpan(c, "W+++++", ["red", "strong"], true, slave.weight); + if (slave.anus === 0) { + helpers.makeSpan(c, "Anal virgin.", "lime"); } - } else { - if (V.arcologies[0].FSHedonisticDecadence !== "unset") { - makeSpan(c, "W++++++", "strong", true, slave.weight); - } else { - makeSpan(c, "W++++++", ["red", "strong"], true, slave.weight); + const holesDesc = helpers.getMultiNumericRating(data.long.body.genitalia.holes, [slave.vagina, slave.anus]); + if (holesDesc) { + helpers.makeSpan(c, holesDesc, "pink"); } - } - } + }, - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_weight(slave, c) { - if (slave.weight < -95) { - makeSpan(c, "Emaciated", "red", true, slave.weight); - } else if (slave.weight < -30) { - if (slave.hips < -1) { - makeSpan(c, "Model-thin", null, true, slave.weight); - } else { - makeSpan(c, "Very thin", "red", true, slave.weight); - } - } else if (slave.weight < -10) { - makeSpan(c, "Thin", null, true, slave.weight); - } else if (slave.weight <= 10) { - makeSpan(c, "Trim", null, true, slave.weight); - } else if (slave.weight <= 30) { - makeSpan(c, "Plush", null, true, slave.weight); - } else if (slave.weight <= 95) { - if (slave.hips > 1 || V.arcologies[0].FSHedonisticDecadence !== "unset") { - makeSpan(c, "Nicely chubby", null, true, slave.weight); - } else { - makeSpan(c, "Overweight", "red", true, slave.weight); + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + diet: function(slave, c) { + helpers.makeMappedSpan(c, data.long.diet, slave.diet, "teal"); + const sd = data.long.specialDiet[slave.dietCum + 3 * slave.dietMilk]; + if (sd) { + helpers.addText(c, "Diet base: "); + helpers.makeSpan(c, sd, "cyan"); + } + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + drugs: function(slave, c) { + const makeSpan = helpers.makeSpan; + let swd = WombGetLittersData(slave); + if ((slave.drugs !== "no drugs") && (slave.drugs !== "none")) { + makeSpan(c, `On ${slave.drugs}.`, "tan"); + } + if (slave.curatives === 2) { + makeSpan(c, "On curatives.", "lightgreen"); + } else if (slave.curatives === 1) { + makeSpan(c, "On preventatives.", "lightgreen"); + } + if (slave.aphrodisiacs > 0) { + makeSpan(c, `On ${slave.aphrodisiacs > 1 ? 'extreme' : ''} aphrodisiacs.`, "lightblue"); + } else if (slave.aphrodisiacs === -1) { + makeSpan(c, "On anaphrodisiacs.", "lightblue"); + } + if (slave.addict !== 0) { + makeSpan(c, "Addict.", "cyan"); + } + if (slave.hormones > 1) { + makeSpan(c, "Heavy female hormones.", "lightsalmon"); + } else if (slave.hormones > 0) { + makeSpan(c, "Female hormones.", "lightsalmon"); + } else if (slave.hormones < -1) { + makeSpan(c, "Heavy male hormones.", "lightsalmon"); + } else if (slave.hormones < 0) { + makeSpan(c, "Male hormones.", "lightsalmon"); + } + let styles = "mediumseagreen"; + if ((slave.bellyImplant > -1)) { + makeSpan(c, "Belly Implant.", styles); + } else if ((slave.preg <= -2) && (slave.ovaries === 1 || slave.mpreg === 1)) { + makeSpan(c, "Barren.", styles); + } else if ((slave.ovaries === 0) && (slave.vagina !== -1) && (slave.genes === "XX")) { + makeSpan(c, "Barren.", styles); + } else if (slave.pubertyXX === 0 && (slave.ovaries === 1 || slave.mpreg === 1)) { + makeSpan(c, "Not ovulating yet.", styles); + } else if (slave.ovaryAge >= 47 && (slave.ovaries === 1 || slave.mpreg === 1)) { + makeSpan(c, "Menopausal.", styles); + } else if (slave.pregWeek < 0) { + makeSpan(c, "Postpartum.", styles); + } else if (slave.preg === -1) { + makeSpan(c, "On contraceptives.", styles); + } else if (slave.preg === 0 && (slave.ovaries === 1 || slave.mpreg === 1)) { + makeSpan(c, "Fertile.", styles); + } else if ((slave.preg >= 36) && (slave.broodmother > 0)) { + makeSpan(c, "Permanently pregnant.", styles); + } else if (swd.litters.length > 1) { + let pregTxt = `Concurrent pregnancies: (${swd.litters.length} sets).`; + pregTxt += ` Max:${swd.litters[0]} / Min:${swd.litters[swd.litters.length - 1]} week(s).`; + makeSpan(c, pregTxt, "lime"); + } else if (((slave.preg < slave.pregData.normalBirth / 10) && (slave.preg > 0) && slave.pregKnown === 0) || slave.pregWeek === 1) { + makeSpan(c, "May be pregnant."); + } else if (slave.pregKnown === 1) { + if (slave.pregType < 2 || slave.broodmother > 0) { + makeSpan(c, `${slave.pregWeek} weeks pregnant.`); + } else { + let desc = `${slave.pregWeek} weeks pregnant with `; + if (slave.pregType >= 40) { + desc += `a tremendous brood of offspring.`; + } else if (slave.pregType >= 20) { + desc += `a brood of offspring.`; + } else if (slave.pregType >= 10) { + desc += `${slave.pregType} babies.`; + } else if (slave.pregType === 9) { + desc += `nonuplets.`; + } else if (slave.pregType === 8) { + desc += `octuplets.`; + } else if (slave.pregType === 7) { + desc += `septuplets.`; + } else if (slave.pregType === 6) { + desc += `sextuplets.`; + } else if (slave.pregType === 5) { + desc += `quintuplets.`; + } else if (slave.pregType === 4) { + desc += `quadruplets.`; + } else if (slave.pregType === 3) { + desc += `triplets.`; + } else { + desc += `twins.`; + } + makeSpan(c, desc); + } + if (slave.preg > slave.pregData.normalBirth && slave.broodmother === 0) { + makeSpan(c, "(Overdue.)"); + } } - } else if (slave.weight <= 130) { - if (slave.hips > 2 || V.arcologies[0].FSHedonisticDecadence !== "unset") { - makeSpan(c, "Pleasantly soft and shapely", null, true, slave.weight); - } else { - makeSpan(c, "Fat", "red", true, slave.weight); + if (slave.induce === 1) { + makeSpan(c, "Showing signs of early labor.", "orange"); } - } else if (slave.weight <= 160) { - if (V.arcologies[0].FSHedonisticDecadence !== "unset") { - makeSpan(c, "Amazingly voluptuous", null, true, slave.weight); - } else { - makeSpan(c, "Obese", "red", true, slave.weight); + if (slave.pubertyXY === 0 && slave.balls > 0) { + makeSpan(c, "Has not had first ejaculation."); } - } else if (slave.weight <= 190) { - if (V.arcologies[0].FSHedonisticDecadence !== "unset") { - makeSpan(c, "SSBBW", null, true, slave.weight); - } else { - makeSpan(c, "Super Obese", "red", true, slave.weight); + if (slave.balls > 0 && slave.vasectomy === 1) { + makeSpan(c, "Vasectomy."); } - } else { - if (V.arcologies[0].FSHedonisticDecadence !== "unset") { - makeSpan(c, "Perfectly massive", null, true, slave.weight); - } else { - makeSpan(c, "Dangerously Obese", "red", true, slave.weight); + if (slave.inflation === 3) { + makeSpan(c, `Filled with 8 liters of ${slave.inflationType}.`, "springgreen"); + } else if (slave.inflation === 2) { + makeSpan(c, `Filled with 4 liters of ${slave.inflationType}.`, "springgreen"); + } else if (slave.inflation === 1) { + makeSpan(c, `Filled with 2 liters of ${slave.inflationType}.`, "springgreen"); + } else if (slave.bellyFluid > 0) { + makeSpan(c, `Stuffed with ${slave.bellyFluid}ccs of ${slave.inflationType}.`, "springgreen"); } - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_diet(slave, c) { - let diet = makeSpan(null, "", ["teal", "strong"]); - switch (slave.diet) { - case "restricted": - diet.textContent = "Di:W-"; - break; - case "fattening": - diet.textContent = "Di:W+"; - break; - case "corrective": - diet.textContent = "Di:W="; - break; - case "XX": - diet.textContent = "Di:XX+"; - break; - case "XY": - diet.textContent = "Di:XY+"; - break; - case "XXY": - diet.textContent = "Di:XXY+"; - break; - case "muscle building": - diet.textContent = "Di:M+"; - break; - case "slimming": - diet.textContent = "Di:M-"; - break; - case "cum production": - diet.textContent = "Di:C+"; - break; - case "cleansing": - diet.textContent = "Di:H+"; - break; - case "fertility": - diet.textContent = "Di:F+"; - break; - } - if (diet.textContent.length > 0) { - c.appendChild(diet); - } - let specialDiet = makeSpan(null, "", ["cyan", "strong"]); - if (slave.dietCum === 2) { - specialDiet.textContent = "Cum++"; - } else if (((slave.dietCum === 1) && (slave.dietMilk === 0))) { - specialDiet.textContent = "Cum+"; - } else if (((slave.dietCum === 1) && (slave.dietMilk === 1))) { - specialDiet.textContent = "Cum+ Milk+"; - } else if (((slave.dietCum === 0) && (slave.dietMilk === 1))) { - specialDiet.textContent = "Milk+"; - } else if ((slave.dietMilk === 2)) { - specialDiet.textContent = ">Milk++"; - } - if (specialDiet.textContent.length > 0) { - c.appendChild(specialDiet); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_diet(slave, c) { - let dietDesc = ""; - switch (slave.diet) { - case "restricted": - dietDesc = `Dieting.`; - break; - case "fattening": - dietDesc = `Gaining weight.`; - break; - case "corrective": - dietDesc = `Corrective.`; - break; - case "XX": - dietDesc = `Estrogen rich.`; - break; - case "XY": - dietDesc = `Testosterone rich.`; - break; - case "XXY": - dietDesc = `Futanari mix.`; - break; - case "muscle building": - dietDesc = `Pumping iron.`; - break; - case "slimming": - dietDesc = `Slimming down.`; - break; - case "cum production": - dietDesc = `Cum production.`; - break; - case "cleansing": - dietDesc = `Cleansing.`; - break; - case "fertility": - dietDesc = `Fertility.`; - break; - } - - if (dietDesc) { - makeSpan(c, dietDesc, "teal"); - } - - function specialDiet(text) { - addText(c, "Diet base: "); - makeSpan(c, text, "cyan"); - } - - if (slave.dietCum === 2) { - specialDiet("Cum Based."); - } else if (((slave.dietCum === 1) && (slave.dietMilk === 0))) { - specialDiet("Cum Added."); - } else if (((slave.dietCum === 1) && (slave.dietMilk === 1))) { - specialDiet("Milk & Cum Added."); - } else if (((slave.dietCum === 0) && (slave.dietMilk === 1))) { - specialDiet("Milk Added."); - } else if ((slave.dietMilk === 2)) { - specialDiet("Milk Based."); - } - } + }, - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_health(slave, c) { - if (slave.health.health < -20) { - makeSpan(c, "H", ["red", "strong"], true, slave.health.health); - } else if (slave.health.health <= 20) { - makeSpan(c, "H", ["yellow", "strong"], true, slave.health.health); - } else if (slave.health.health > 20) { - makeSpan(c, "H", ["green", "strong"], true, slave.health.health); - } - if (passage() === "Clinic" && V.clinicUpgradeScanner) { - if (slave.chem > 15) { - makeSpan(c, `C${Math.ceil(slave.chem/10)}`, ["cyan", "strong"]); - } else if (slave.chem <= 15 && slave.assignment === "get treatment in the clinic") { - makeSpan(c, `CSafe`, ["green", "strong"]); + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + physicals: function(slave, c) { + const b = bits.long; + b.age(slave, c); + b.face(slave, c); + b.eyes(slave, c); + b.ears(slave, c); + b.lips(slave, c); + b.teeth(slave, c); + b.muscles(slave, c); + helpers.makeSpan(c, App.Desc.longLimbs(slave)); + b.voice(slave, c); + b.tits_ass(slave, c); + b.hips(slave, c); + b.waist(slave, c); + b.implants(slave, c); + b.lactation(slave, c); + b.mods(slave, c); + if (!jQuery.isEmptyObject(slave.brand)) { + helpers.makeSpan(c, 'Branded.'); } - } - } + }, - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_health(slave, c) { - if (slave.health.health < -90) { - makeSpan(c, "On the edge of death", ["red", "strong"], true, slave.health.health); - } else if (slave.health.health < -50) { - makeSpan(c, "Extremely unhealthy", ["red", "strong"], true, slave.health.health); - } else if (slave.health.health < -20) { - makeSpan(c, "Unhealthy", ["red", "strong"], true, slave.health.health); - } else if (slave.health.health <= 20) { - makeSpan(c, "healthy", "yellow", true, slave.health.health); - } else if (slave.health.health <= 50) { - makeSpan(c, "Very healthy", "green", true, slave.health.health); - } else if (slave.health.health <= 90) { - makeSpan(c, "Extremely healthy", "green", true, slave.health.health); - } else { - makeSpan(c, "Unnaturally healthy", "green", true, slave.health.health); - } - if (passage() === "Clinic" && V.clinicUpgradeScanner) { - if (slave.chem > 15) { - makeSpan(c, `Carcinogen buildup: ${Math.ceil(slave.chem/10)}.`, "cyan"); - } else if (slave.chem <= 15 && slave.assignment === "get treatment in the clinic") { - makeSpan(c, `Safe chem levels.`, "green"); + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + hormoneBalance: function(slave, c) { + const colorClass = slave.hormoneBalance <= -21 ? "deepskyblue" : "pink"; + const desc = helpers.getNumericRating(data.long.hormoneBalance, slave.hormoneBalance + 500); + helpers.makeSpan(c, desc + " hormone balance.", colorClass); + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + skills: function(slave, c) { + const b = bits.long; + b.intelligence(slave, c); + b.skills(slave, c); + b.prestige(slave, c); + b.porn_prestige(slave, c); + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + clothes: function(slave, c) { + const b = bits.long; + const dressingBlock = helpers.makeBlock(c); + if (slave.choosesOwnClothes === 1) { + helpers.makeSpan(dressingBlock, `Dressing ${getPronouns(slave).himself}.`); + } + b.clothes(slave, dressingBlock); + b.collar(slave, dressingBlock); + b.belly(slave, dressingBlock); + if (hasAnyArms(slave)) { + b.arms(slave, dressingBlock); + } + if (hasAnyLegs(slave)) { + b.legs(slave, dressingBlock); + b.shoes(slave, dressingBlock); + } + b.chastity(slave, dressingBlock); + b.vaginal_acc(slave, dressingBlock); + b.dick_acc(slave, dressingBlock); + b.buttplug(slave, dressingBlock); + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + mental: function(slave, c) { + const b = bits.long; + if (slave.fetish !== "mindbroken") { + if (slave.fetishKnown === 1) { + b.fetish(slave, c); + } + if (slave.attrKnown === 1) { + b.attraction(slave, c); + } + } + if (slave.clitPiercing === 3) { + b.smart_fetish(slave, c); + b.smart_attraction(slave, c); + } + b.behavior_flaw(slave, c); + b.sex_flaw(slave, c); + b.behavior_quirk(slave, c); + b.sex_quirk(slave, c); + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + race: function(slave, c) { + let raceStr = App.Data.SlaveSummary.long.race[slave.race]; + if (!raceStr) { + raceStr = capFirstChar(slave.race); + } + helpers.makeSpan(c, raceStr + '.', "tan"); + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + nationality: function(slave, c) { + function descStr(slave) { + switch (slave.nationality) { + case "a Cook Islander": + return `Cook Islander.`; + case "a Liechtensteiner": + return `Liechtensteiner.`; + case "a New Zealander": + return `New Zealander.`; + case "a Solomon Islander": + return `Solomon Islander.`; + case "Zimbabwean": + if (slave.race === "white") { + return `Rhodesian.`; + } else { + return `${slave.nationality}.`; + } + case "slave": + case "none": + case "": + case "Stateless": + return `Stateless.`; + default: + return `${slave.nationality}.`; + } } - } - } - - function short_illness(slave, c) { - if (slave.health.illness > 4) { - makeSpan(c, `Ill${slave.health.illness}`, ["red", "strong"], true, slave.health.illness); - } else if (slave.health.illness > 3) { - makeSpan(c, `Ill${slave.health.illness}`, ["red", "strong"], true, slave.health.illness); - } else if (slave.health.illness > 2) { - makeSpan(c, `Ill${slave.health.illness}`, ["red", "strong"], true, slave.health.illness); - } else if (slave.health.illness > 0) { - makeSpan(c, `Ill${slave.health.illness}`, ["yellow", "strong"], true, slave.health.illness); - } - } - - function long_illness(slave, c) { - if (slave.health.illness > 4) { - makeSpan(c, "Terribly ill", ["red", "strong"], true, slave.health.illness); - } else if (slave.health.illness > 3) { - makeSpan(c, "Very ill", ["red", "strong"], true, slave.health.illness); - } else if (slave.health.illness > 2) { - makeSpan(c, "Ill", ["red", "strong"], true, slave.health.illness); - } else if (slave.health.illness > 0) { - makeSpan(c, "Sick", "yellow", true, slave.health.illness); - } - } - function short_tired(slave, c) { - if (slave.health.tired > 90) { - makeSpan(c, "Exh", ["red", "strong"], true, slave.health.tired); - } else if (slave.health.tired > 60) { - makeSpan(c, "Tir+", "orange", true, slave.health.tired); - } else if (slave.health.tired > 30) { - makeSpan(c, "Tir", "yellow", true, slave.health.tired); - } else if (slave.health.tired < 0) { - makeSpan(c, "Ene", "green", true, slave.health.tired); - } - } + helpers.makeSpan(c, descStr(slave), "tan"); + }, - function long_tired(slave, c) { - if (slave.health.tired > 90) { - makeSpan(c, "Exhausted", ["red", "strong"], true, slave.health.tired); - } else if (slave.health.tired > 60) { - makeSpan(c, "Fatigued", "orange", true, slave.health.tired); - } else if (slave.health.tired > 30) { - makeSpan(c, "Tired", "yellow", true, slave.health.tired); - } else if (slave.health.tired < 0) { - makeSpan(c, "Energetic", "green", true, slave.health.tired); - } - } + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + skin: function(slave, c) { + helpers.makeSpan(c, `${capFirstChar(slave.skin)} skin.`); + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + rulesets: function(slave, c) { + if (slave.useRulesAssistant === 0) { + helpers.makeSpan(c, "RA-Exempt", "lightgreen"); + } else if ((slave.currentRules !== undefined) && (slave.currentRules.length > 0)) { + c.innerHTML = `Rules: ${V.defaultRules.filter(x => ruleApplied(slave, x)).map(x => x.name).join(", ")}`; + } + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + origins: function(slave, c) { + const para = helpers.makeParagraph(c); + para.classList.add("gray"); + const pronouns = getPronouns(slave); + para.textContent = `${slave.origin.replace(/\$([A-Z]?[a-z]+)/g, (match, cap1) => pronouns[cap1] || match)}`; + }, + + /** + * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} + */ + relations: function(slave, c) { + const b = bits.long; + b.family(slave, c); + b.clone(slave, c); + b.rival(slave, c); + } + }; + + return { + short: shortRenderers, + long: longRenderers, + empty: function(){} + }; +}(); + +App.UI.SlaveSummary = function() { + const emptyRenderer = (/** @type {App.Entity.SlaveState} */ slave, /** @type {Node} */ c) => { }; + const delegates = { + clothes: emptyRenderer, + devotion: emptyRenderer, + rules: emptyRenderer, + height: emptyRenderer, + diet: emptyRenderer, + health: emptyRenderer, + drugs: emptyRenderer, + race: emptyRenderer, + nationality: emptyRenderer, + genitalia: emptyRenderer, + physicals: emptyRenderer, + hormoneBalance: emptyRenderer, + skills: emptyRenderer, + mental: emptyRenderer, + weight: emptyRenderer, + skin: emptyRenderer, + origins: emptyRenderer, + rulesets: emptyRenderer, + relations: emptyRenderer + }; + + /** + * @returns {App.UI.SlaveSummary.State} + */ + function makeNewState() { + return { + abbreviation: { + clothes: 2, + devotion: 2, + diet: 2, + drugs: 2, + genitalia: 2, + health: 2, + mental: 2, + nationality: 2, + origins: 2, + physicals: 2, + race: 2, + rules: 2, + rulesets: 2, + skills: 2, + } + }; + } + + function delegateForSetting(name, setting) { + switch (setting) { + case 0: return App.UI.SlaveSummaryRenderers.empty; + case 1: return App.UI.SlaveSummaryRenderers.short[name]; + case 2: return App.UI.SlaveSummaryRenderers.long[name]; + } + } + + function initDelegates(settingsObj) { + try { + settingsObj = settingsObj || V.UI.slaveSummary; + /** @type {App.UI.SlaveSummary.AbbreviationState} */ + const abbrSettings = settingsObj.abbreviation; + for (const setting in abbrSettings) { + delegates[setting] = delegateForSetting(setting, abbrSettings[setting]); + } + delegates.weight = delegateForSetting("weight", abbrSettings.diet); + delegates.skin = delegateForSetting("skin", abbrSettings.physicals); + delegates.relations = delegateForSetting("relations", abbrSettings.mental); + // special settings + if (!V.seeRace) { + delegates.race = emptyRenderer; + } + } catch (ex){ + console.error(ex); + } + } + + function settingsChanged(newState) { + try { + const newStateIsOK = newState && newState.hasOwnProperty("UI") && newState.UI.hasOwnProperty("slaveSummary"); + const settingsObj = newStateIsOK ? newState.UI.slaveSummary : V.UI.slaveSummary; + + initDelegates(settingsObj); + App.UI.SlaveSummaryImpl.helpers.syncFSData(newState ? newState.arcologies[0] : V.arcologies[0]); + } catch (ex) { + console.error(ex); + } + } + + function societyChanged(arcology) { + App.UI.SlaveSummaryImpl.helpers.syncFSData(arcology); + } + + /** + * @param {App.Entity.SlaveState} slave + * @returns {DocumentFragment} + */ + function render(slave) { + /** @type {App.UI.SlaveSummary.AbbreviationState} */ + const abbrSettings = V.UI.slaveSummary.abbreviation; + const helpers = App.UI.SlaveSummaryImpl.helpers; + + const res = document.createDocumentFragment(); + let para = helpers.makeParagraph(res); - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_drugs(slave, c) { - let drugDesc = ""; - switch (slave.drugs) { - case "breast injections": - drugDesc = "Boobs+"; - break; - case "intensive breast injections": - drugDesc = "Boobs++"; - break; - case "hyper breast injections": - drugDesc = "Boobs+++"; - break; - case "nipple enhancers": - drugDesc = "Nipple+"; - break; - case "butt injections": - drugDesc = "Butt+"; - break; - case "intensive butt injections": - drugDesc = "Butt++"; - break; - case "hyper butt injections": - drugDesc = "Butt+++"; - break; - case "lip injections": - drugDesc = "Lip+"; - break; - case "fertility drugs": - drugDesc = "Fert+"; - break; - case "super fertility drugs": - drugDesc = "Fert++"; - break; - case "penis enhancement": - drugDesc = "Dick+"; - break; - case "intensive penis enhancement": - drugDesc = "Dick++"; - break; - case "hyper penis enhancement": - drugDesc = "Dick+++"; - break; - case "testicle enhancement": - drugDesc = "Balls+"; - break; - case "intensive testicle enhancement": - drugDesc = "Balls++"; - break; - case "hyper testicle enhancement": - drugDesc = "Balls+++"; - break; - case "psychosuppressants": - drugDesc = "Psych-"; - break; - case "psychostimulants": - drugDesc = "Psych+"; - break; - case "steroids": - drugDesc = "Ster"; - break; - case "female hormone injections": - drugDesc = "HormXX++"; - break; - case "male hormone injections": - drugDesc = "HormXY++"; - break; - case "hormone enhancers": - drugDesc = "Horm+"; - break; - case "hormone blockers": - drugDesc = "Horm-"; - break; - case "anti-aging cream": - drugDesc = "Age-"; - break; - case "appetite suppressors": - drugDesc = "ApSup"; - break; - case "penis atrophiers": - drugDesc = "Dick-"; - break; - case "testicle atrophiers": - drugDesc = "Balls-"; - break; - case "clitoris atrophiers": - drugDesc = "Clit-"; - break; - case "labia atrophiers": - drugDesc = "Labia-"; - break; - case "nipple atrophiers": - drugDesc = "Nipple-"; - break; - case "lip atrophiers": - drugDesc = "Lip-"; - break; - case "breast redistributors": - drugDesc = "Breast-"; - break; - case "butt redistributors": - drugDesc = "Butt-"; - break; - case "sag-B-gone": - drugDesc = "AntiSag"; - break; - case "growth stimulants": - drugDesc = "GroStim"; - break; - case "priapism agents": - drugDesc = "Erection"; - break; - } - if (drugDesc) { - makeSpan(c, "Dr:" + drugDesc, ["tan", "strong"]); - } - if (slave.curatives === 2) { - makeSpan(c, "Cura", ["lightgreen", "strong"]); - } else if (slave.curatives === 1) { - makeSpan(c, "Prev", ["lightgreen", "strong"]); - } - if (slave.aphrodisiacs !== 0) { - if (slave.aphrodisiacs === 1) { - makeSpan(c, "Aph", ["lightblue", "strong"]); - } else if (slave.aphrodisiacs === 2) { - makeSpan(c, "Aph++", ["lightblue", "strong"]); - } else { - makeSpan(c, "Anaph", ["lightblue", "strong"]); - } - } - if (slave.addict !== 0) { - makeSpan(c, "Add", "cyan"); - } - let styles = ["lightsalmon", "strong"]; - if (slave.hormones > 1) { - makeSpan(c, "Ho:F+", styles); - } else if (slave.hormones > 0) { - makeSpan(c, "Ho:F", styles); - } else if (slave.hormones < -1) { - makeSpan(c, "Ho:M+", styles); - } else if (slave.hormones < 0) { - makeSpan(c, "Ho:M", styles); + delegates.devotion(slave, para); + if (!slave.fuckdoll) { + delegates.rules(slave, para); } + delegates.weight(slave, para); + delegates.diet(slave, para); + delegates.health(slave, para); + delegates.drugs(slave, para); - styles = ["mediumseagreen", "strong"]; - if ((slave.bellyImplant > -1)) { - makeSpan(c, "Belly Imp", styles); - } else if (((slave.preg <= -2) || (slave.ovaries === 0)) && (slave.vagina !== -1)) { - makeSpan(c, "Barr", styles); - } else if (slave.pubertyXX === 0 && (slave.ovaries === 1 || slave.mpreg === 1)) { - makeSpan(c, "Prepub", styles); - } else if (slave.ovaryAge >= 47 && (slave.ovaries === 1 || slave.mpreg === 1)) { - makeSpan(c, "Meno", styles); - } else if (slave.pregWeek < 0) { - makeSpan(c, "Postpartum", styles); - } else if (slave.preg === -1) { - makeSpan(c, "CC", styles); - } else if (slave.preg === 0 && (slave.ovaries === 1 || slave.mpreg === 1)) { - makeSpan(c, "Fert+", styles); - } else if (((slave.preg < slave.pregData.normalBirth / 10) && (slave.preg > 0) && slave.pregKnown === 0) || slave.pregWeek === 1) { - makeSpan(c, "Preg?", styles); - } else if ((slave.preg >= 36) && (slave.broodmother > 0)) { - makeSpan(c, "Perm preg", styles); - } else if (slave.pregKnown === 1) { - makeSpan(c, `${slave.pregWeek} wks preg`, styles); - } - if (slave.induce === 1) { - makeSpan(c, "Early Labor", ["orange", "strong"]); + para = helpers.makeParagraph(res); + para.classList.add("pink"); + helpers.makeSpan(para, `${capFirstChar(SlaveTitle(slave))}${abbrSettings.physicals === 2 ? '.' : ''}`, ["coral", "strong"]); + delegates.race(slave, para); + delegates.nationality(slave, para); + delegates.skin(slave, para); + delegates.genitalia(slave, para); + delegates.physicals(slave, para); + delegates.hormoneBalance(slave, para); + + para = helpers.makeParagraph(res); + delegates.skills(slave, para); + delegates.mental(slave, para); + if (slave.custom.label) { + helpers.makeSpan(res, `${capFirstChar(slave.custom.label)}.`, ["yellow", "strong"]); } - if (slave.pubertyXY === 0 && slave.balls > 0) { - makeSpan(c, "Prepub balls", "strong"); + if ((slave.relationship !== 0) || (slave.relation !== 0) || (abbrSettings.clothes === 2) || (abbrSettings.rulesets === 2)) { + para = helpers.makeParagraph(res); } - if (slave.balls > 0 && slave.vasectomy === 1) { - makeSpan(c, "Vasect", "strong"); + delegates.relations(slave, para); + if (!slave.fuckdoll) { + delegates.clothes(slave, para); } - styles = ["springgreen", "strong"]; - if (slave.inflation === 3) { - makeSpan(c, `8 ltr ${slave.inflationType}`, styles); - } else if (slave.inflation === 2) { - makeSpan(c, `4 ltr ${slave.inflationType}`, styles); - } else if (slave.inflation === 1) { - makeSpan(c, `2 ltr ${slave.inflationType}`, styles); - } else if (slave.bellyFluid > 0) { - makeSpan(c, `${slave.bellyFluid}ccs ${slave.inflationType}`, styles); + const RABlock = helpers.makeBlock(para); + delegates.rulesets(slave, RABlock); + if (slave.origin !== 0) { + delegates.origins(slave, res); } + return res; } - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_drugs(slave, c) { - let swd = WombGetLittersData(slave); - if ((slave.drugs !== "no drugs") && (slave.drugs !== "none")) { - makeSpan(c, `On ${slave.drugs}.`, "tan"); - } - if (slave.curatives === 2) { - makeSpan(c, "On curatives.", "lightgreen"); - } else if (slave.curatives === 1) { - makeSpan(c, "On preventatives.", "lightgreen"); - } - if (slave.aphrodisiacs > 0) { - makeSpan(c, `On ${slave.aphrodisiacs > 1 ? 'extreme' : ''} aphrodisiacs.`, "lightblue"); - } else if (slave.aphrodisiacs === -1) { - makeSpan(c, "On anaphrodisiacs.", "lightblue"); - } - if (slave.addict !== 0) { - makeSpan(c, "Addict.", "cyan"); - } - if (slave.hormones > 1) { - makeSpan(c, "Heavy female hormones.", "lightsalmon"); - } else if (slave.hormones > 0) { - makeSpan(c, "Female hormones.", "lightsalmon"); - } else if (slave.hormones < -1) { - makeSpan(c, "Heavy male hormones.", "lightsalmon"); - } else if (slave.hormones < 0) { - makeSpan(c, "Male hormones.", "lightsalmon"); - } - let styles = "mediumseagreen"; - if ((slave.bellyImplant > -1)) { - makeSpan(c, "Belly Implant.", styles); - } else if ((slave.preg <= -2) && (slave.ovaries === 1 || slave.mpreg === 1)) { - makeSpan(c, "Barren.", styles); - } else if ((slave.ovaries === 0) && (slave.vagina !== -1) && (slave.genes === "XX")) { - makeSpan(c, "Barren.", styles); - } else if (slave.pubertyXX === 0 && (slave.ovaries === 1 || slave.mpreg === 1)) { - makeSpan(c, "Not ovulating yet.", styles); - } else if (slave.ovaryAge >= 47 && (slave.ovaries === 1 || slave.mpreg === 1)) { - makeSpan(c, "Menopausal.", styles); - } else if (slave.pregWeek < 0) { - makeSpan(c, "Postpartum.", styles); - } else if (slave.preg === -1) { - makeSpan(c, "On contraceptives.", styles); - } else if (slave.preg === 0 && (slave.ovaries === 1 || slave.mpreg === 1)) { - makeSpan(c, "Fertile.", styles); - } else if ((slave.preg >= 36) && (slave.broodmother > 0)) { - makeSpan(c, "Permanently pregnant.", styles); - } else if (swd.litters.length > 1) { - let pregTxt = `Concurrent pregnancies: (${swd.litters.length} sets).`; - pregTxt += ` Max:${swd.litters[0]} / Min:${swd.litters[swd.litters.length-1]} week(s).`; - makeSpan(c, pregTxt, "lime"); - } else if (((slave.preg < slave.pregData.normalBirth / 10) && (slave.preg > 0) && slave.pregKnown === 0) || slave.pregWeek === 1) { - makeSpan(c, "May be pregnant."); - } else if (slave.pregKnown === 1) { - if (slave.pregType < 2 || slave.broodmother > 0) { - makeSpan(c, `${slave.pregWeek} weeks pregnant.`); - } else { - let desc = `${slave.pregWeek} weeks pregnant with `; - if (slave.pregType >= 40) { - desc += `a tremendous brood of offspring.`; - } else if (slave.pregType >= 20) { - desc += `a brood of offspring.`; - } else if (slave.pregType >= 10) { - desc += `${slave.pregType} babies.`; - } else if (slave.pregType === 9) { - desc += `nonuplets.`; - } else if (slave.pregType === 8) { - desc += `octuplets.`; - } else if (slave.pregType === 7) { - desc += `septuplets.`; - } else if (slave.pregType === 6) { - desc += `sextuplets.`; - } else if (slave.pregType === 5) { - desc += `quintuplets.`; - } else if (slave.pregType === 4) { - desc += `quadruplets.`; - } else if (slave.pregType === 3) { - desc += `triplets.`; - } else { - desc += `twins.`; - } - makeSpan(c, desc); - } - if (slave.preg > slave.pregData.normalBirth && slave.broodmother === 0) { - makeSpan(c, "(Overdue.)"); - } - } - if (slave.induce === 1) { - makeSpan(c, "Showing signs of early labor.", "orange"); - } - if (slave.pubertyXY === 0 && slave.balls > 0) { - makeSpan(c, "Has not had first ejaculation."); - } - if (slave.balls > 0 && slave.vasectomy === 1) { - makeSpan(c, "Vasectomy."); - } - if (slave.inflation === 3) { - makeSpan(c, `Filled with 8 liters of ${slave.inflationType}.`, "springgreen"); - } else if (slave.inflation === 2) { - makeSpan(c, `Filled with 4 liters of ${slave.inflationType}.`, "springgreen"); - } else if (slave.inflation === 1) { - makeSpan(c, `Filled with 2 liters of ${slave.inflationType}.`, "springgreen"); - } else if (slave.bellyFluid > 0) { - makeSpan(c, `Stuffed with ${slave.bellyFluid}ccs of ${slave.inflationType}.`, "springgreen"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @returns {string} - */ - function long_race(slave) { - switch (slave.race) { - case "white": - return `Caucasian.`; - case "asian": - return `Asian.`; - case "indo-aryan": - return `Indo-aryan.`; - case "latina": - return `Latina.`; - case "middle eastern": - return `Middle Eastern.`; - case "black": - return `Black.`; - case "pacific islander": - return `Pacific Islander.`; - case "malay": - return `Malay.`; - case "amerindian": - return `Amerindian.`; - case "semitic": - return `Semitic.`; - case "southern european": - return `Southern European.`; - case "mixed race": - return `Mixed race.`; - default: - return `${slave.race.charAt(0).toUpperCase() + slave.race.slice(1)}.`; - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @returns {string} - */ - function short_race(slave) { - switch (slave.race) { - case "white": - return `C`; - case "asian": - return `A`; - case "indo-aryan": - return `I`; - case "latina": - return `L`; - case "middle eastern": - return `ME`; - case "black": - return `B`; - case "pacific islander": - return `PI`; - case "malay": - return `M`; - case "amerindian": - return `AI`; - case "semitic": - return `S`; - case "southern european": - return `SE`; - case "mixed race": - return `MR`; - default: - return `${slave.race.charAt(0).toUpperCase() + slave.race.charAt(1) + slave.race.charAt(2)}`; - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @returns {string} - */ - function short_nationality(slave) { - switch (slave.nationality) { - case "Afghan": - return "Afg"; - case "Albanian": - return "Alb"; - case "Algerian": - return "Alg"; - case "American": - return "USA"; - case "Andorran": - return "And"; - case "Angolan": - return "Ang"; - case "Antiguan": - return "AB"; - case "Argentinian": - return "Arg"; - case "Armenian": - return "Arm"; - case "Aruban": - return "Aru"; - case "Australian": - return "Aus"; - case "Austrian": - return "Aut"; - case "Azerbaijani": - return "Aze"; - case "Bahamian": - return "Bah"; - case "Bahraini": - return "Bah"; - case "Bangladeshi": - return "Bgd"; - case "Barbadian": - return "Bar"; - case "Belarusian": - return "Ber"; - case "Belgian": - return "Bel"; - case "Belizean": - return "Blz"; - case "Beninese": - return "Ben"; - case "Bermudian": - return "Bmd"; - case "Bhutanese": - return "Bhu"; - case "Bissau-Guinean": - return "GB"; - case "Bolivian": - return "Bol"; - case "Bosnian": - return "Bos"; - case "Brazilian": - return "Bra"; - case "British": - return "UK"; - case "Bruneian": - return "Bru"; - case "Bulgarian": - return "Bul"; - case "Burkinabé": - return "BF"; - case "Burmese": - return "Bur"; - case "Burundian": - return "Bnd"; - case "Cambodian": - return "Kam"; - case "Cameroonian": - return "Cam"; - case "Canadian": - return "Can"; - case "Cape Verdean": - return "CV"; - case "Catalan": - return "Cat"; - case "Central African": - return "CAR"; - case "Chadian": - return "Cha"; - case "Chilean": - return "Chl"; - case "Chinese": - return "Chi"; - case "Colombian": - return "Col"; - case "Comorian": - return "Com"; - case "Congolese": - return "RC"; - case "a Cook Islander": - return "CI"; - case "Costa Rican": - return "CR"; - case "Croatian": - return "Cro"; - case "Cuban": - return "Cub"; - case "Curaçaoan": - return "Cur"; - case "Cypriot": - return "Cyp"; - case "Czech": - return "Cze"; - case "Danish": - return "Den"; - case "Djiboutian": - return "Dji"; - case "Dominican": - return "DR"; - case "Dominiquais": - return "Dom"; - case "Dutch": - return "Nld"; - case "East Timorese": - return "ET"; - case "Ecuadorian": - return "Ecu"; - case "Egyptian": - return "Egy"; - case "Emirati": - return "UAE"; - case "Equatoguinean": - return "EG"; - case "Eritrean": - return "Eri"; - case "Estonian": - return "Est"; - case "Ethiopian": - return "Eth"; - case "Fijian": - return "Fij"; - case "Filipina": - return "Phl"; - case "Finnish": - return "Fin"; - case "French": - return "Fra"; - case "French Guianan": - return "FG"; - case "French Polynesian": - return "FP"; - case "Gabonese": - return "Gab"; - case "Gambian": - return "Gam"; - case "Georgian": - return "Geo"; - case "German": - return "Ger"; - case "Ghanan": - return "Gha"; - case "Greek": - return "Gre"; - case "Greenlandic": - return "Grn"; - case "Grenadian": - return "Gda"; - case "Guamanian": - return "Gua"; - case "Guatemalan": - return "Gtm"; - case "Guinean": - return "Gui"; - case "Guyanese": - return "Guy"; - case "Haitian": - return "Hai"; - case "Honduran": - return "Hon"; - case "Hungarian": - return "Hun"; - case "I-Kiribati": - return "Kir"; - case "Icelandic": - return "Ice"; - case "Indian": - return "Ind"; - case "Indonesian": - return "Idn"; - case "Iranian": - return "Irn"; - case "Iraqi": - return "Irq"; - case "Irish": - return "Irl"; - case "Israeli": - return "Isr"; - case "Italian": - return "Ita"; - case "Ivorian": - return "IC"; - case "Jamaican": - return "Jam"; - case "Japanese": - return "Jpn"; - case "Jordanian": - return "Jor"; - case "Kazakh": - return "Kaz"; - case "Kenyan": - return "Ken"; - case "Kittitian": - return "SKN"; - case "Korean": - return "Kor"; - case "Kosovan": - return "Kos"; - case "Kurdish": - return "Kur"; - case "Kuwaiti": - return "Kuw"; - case "Kyrgyz": - return "Kyr"; - case "Laotian": - return "Lao"; - case "Latvian": - return "Lat"; - case "Lebanese": - return "Lbn"; - case "Liberian": - return "Lib"; - case "Libyan": - return "Lby"; - case "a Liechtensteiner": - return "Lie"; - case "Lithuanian": - return "Lit"; - case "Luxembourgian": - return "Lux"; - case "Macedonian": - return "Mac"; - case "Malagasy": - return "Mad"; - case "Malawian": - return "Mwi"; - case "Malaysian": - return "Mys"; - case "Maldivian": - return "Mdv"; - case "Malian": - return "Mal"; - case "Maltese": - return "Mlt"; - case "Marshallese": - return "MI"; - case "Mauritanian": - return "Mta"; - case "Mauritian": - return "Mts"; - case "Mexican": - return "Mex"; - case "Micronesian": - return "FSM"; - case "Moldovan": - return "Mol"; - case "Monégasque": - return "Mnc"; - case "Mongolian": - return "Mon"; - case "Montenegrin": - return "Mng"; - case "Moroccan": - return "Mor"; - case "Mosotho": - return "Les"; - case "Motswana": - return "Bot"; - case "Mozambican": - return "Moz"; - case "Namibian": - return "Nam"; - case "Nauruan": - return "Nau"; - case "Nepalese": - return "Npl"; - case "New Caledonian": - return "NC"; - case "a New Zealander": - return "NZ"; - case "Ni-Vanuatu": - return "Van"; - case "Nicaraguan": - return "Nic"; - case "Nigerian": - return "Nga"; - case "Nigerien": - return "Ngr"; - case "Niuean": - return "Niu"; - case "Norwegian": - return "Nor"; - case "Omani": - return "Omn"; - case "Pakistani": - return "Pak"; - case "Palauan": - return "Plu"; - case "Palestinian": - return "Pal"; - case "Panamanian": - return "Pan"; - case "Papua New Guinean": - return "PNG"; - case "Paraguayan": - return "Par"; - case "Peruvian": - return "Per"; - case "Polish": - return "Pol"; - case "Portuguese": - return "Por"; - case "Puerto Rican": - return "PR"; - case "Qatari": - return "Qat"; - case "Romanian": - return "Rom"; - case "Russian": - return "Rus"; - case "Rwandan": - return "Rwa"; - case "Sahrawi": - return "Sah"; - case "Saint Lucian": - return "SL"; - case "Salvadoran": - return "ES"; - case "Sammarinese": - return "SM"; - case "Samoan": - return "Sam"; - case "São Toméan": - return "STP"; - case "Saudi": - return "Sau"; - case "Scottish": - return "Sco"; - case "Senegalese": - return "Sen"; - case "Serbian": - return "Srb"; - case "Seychellois": - return "Sey"; - case "Sierra Leonean": - return "Sie"; - case "Singaporean": - return "Sng"; - case "Slovak": - return "Svk"; - case "Slovene": - return "Svn"; - case "a Solomon Islander": - return "SI"; - case "Somali": - return "Som"; - case "South African": - return "RSA"; - case "South Sudanese": - return "SS"; - case "Spanish": - return "Spa"; - case "Sri Lankan": - return "Sri"; - case "Sudanese": - return "Sud"; - case "Surinamese": - return "Sur"; - case "Swazi": - return "Swa"; - case "Swedish": - return "Swe"; - case "Swiss": - return "Swi"; - case "Syrian": - return "Syr"; - case "Taiwanese": - return "Tai"; - case "Tajik": - return "Taj"; - case "Tanzanian": - return "Tza"; - case "Thai": - return "Tha"; - case "Tibetan": - return "Tib"; - case "Togolese": - return "Tog"; - case "Tongan": - return "Ton"; - case "Trinidadian": - return "TT"; - case "Tunisian": - return "Tun"; - case "Turkish": - return "Tur"; - case "Turkmen": - return "Tkm"; - case "Tuvaluan": - return "Tuv"; - case "Ugandan": - return "Uga"; - case "Ukrainian": - return "Ukr"; - case "Uruguayan": - return "Uru"; - case "Uzbek": - return "Uzb"; - case "Vatican": - return "VC"; - case "Venezuelan": - return "Ven"; - case "Vietnamese": - return "Vnm"; - case "Vincentian": - return "SVG"; - case "Yemeni": - return "Yem"; - case "Zairian": - return "DRC"; - case "Zambian": - return "Zam"; - case "Zimbabwean": - if (slave.race === "white") { - return `Rho`; - } else { - return `Zwe`; - } - case "Ancient Chinese Revivalist": - return `Chi Rev`; - case "Ancient Egyptian Revivalist": - return `Egy Rev`; - case "Arabian Revivalist": - return `Ara Rev`; - case "Aztec Revivalist": - return `Azt Rev`; - case "Edo Revivalist": - return `Edo Rev`; - case "Roman Revivalist": - return `Rom Rev`; - case "": - case "none": - case "slave": - case "Stateless": - return "None"; - default: - return `${slave.nationality.charAt(0) + slave.nationality.charAt(1) + slave.nationality.charAt(2)}`; - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @returns {string} - */ - function long_nationality(slave) { - switch (slave.nationality) { - case "a Cook Islander": - return `Cook Islander.`; - case "a Liechtensteiner": - return `Liechtensteiner.`; - case "a New Zealander": - return `New Zealander.`; - case "a Solomon Islander": - return `Solomon Islander.`; - case "Zimbabwean": - if (slave.race === "white") { - return `Rhodesian.`; - } else { - return `${slave.nationality}.`; - } - case "slave": - case "none": - case "": - case "Stateless": - return `Stateless.`; - default: - return `${slave.nationality}.`; - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @returns {string} - */ - function short_skin(slave) { - switch (slave.skin) { - case "pure white": - return `P. Whi`; - case "extremely fair": - return `E. Fai`; - case "very fair": - return `V. Fai`; - case "extremely pale": - return `E. Pal`; - case "very pale": - return `V. Pal`; - case "light brown": - return `L. Br`; - case "dark brown": - return `D. Br`; - case "light olive": - return `L. Oli`; - case "dark olive": - return `D. Oli`; - case "light beige": - return `L. Bei`; - case "dark beige": - return `D. Bei`; - case "tan": - return `Tan`; - case "bronze": - return `Bron`; - case "ebony": - return `Ebon`; - case "pure black": - return `P. Bla`; - case "dark": - case "fair": - case "pale": - return `${slave.skin.charAt(0).toUpperCase() + slave.skin.slice(1)}`; - default: - return `${slave.skin.charAt(0).toUpperCase() + slave.skin.charAt(1) + slave.skin.charAt(2)}`; - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_genitals(slave, c) { - if (slave.dick > 0) { - let dickDesc = ""; - if (slave.balls === 0) { - dickDesc += `Geld`; - } - if ((slave.dick > 8) && (slave.balls > 8)) { - dickDesc += `Junk+++`; - } else if ((slave.dick > 5) && (slave.balls > 5)) { - dickDesc += `Junk++`; - } else if ((slave.dick > 4) && (slave.balls > 4)) { - dickDesc += `Junk+`; - } else if ((slave.dick > 3) && (slave.balls > 3)) { - dickDesc += `Junk`; - } else if (slave.dick > 8) { - dickDesc += `Dick+++`; - } else if (slave.dick > 5) { - dickDesc += `Dick++`; - } else if (slave.dick > 4) { - dickDesc += `Dick+`; - } else if (slave.dick > 3) { - dickDesc += `Dick`; - } else if (slave.balls > 10) { - dickDesc += `Balls+++`; - } else if (slave.balls > 5) { - dickDesc += `Balls++`; - } else if (slave.balls > 4) { - dickDesc += `Balls+`; - } else if (slave.balls > 3) { - dickDesc += `Balls`; - } - if (dickDesc.length) { - makeSpan(c, dickDesc, "pink"); - } - } - if (slave.vagina === 0) { - makeSpan(c, "VV", "lime"); - } else if ((slave.pregKnown === 1) && canWalk(slave) && (slave.clothes === "no clothing" || slave.clothes === "body oil") && (slave.shoes === "none")) { - makeSpan(c, "NBP", "pink"); - } - if (slave.anus === 0) { - makeSpan(c, "AV", "lime"); - } - let holesDesc = ""; - if ((slave.vagina > 3) && (slave.anus > 3)) { - holesDesc += `V++A++`; - } else if ((slave.vagina > 2) && (slave.anus > 2)) { - holesDesc += `V+A+`; - } else if (slave.vagina > 3) { - holesDesc += `V++`; - } else if (slave.vagina > 2) { - holesDesc += `V+`; - } else if (slave.anus > 3) { - holesDesc += `A++`; - } else if (slave.anus > 2) { - holesDesc += `A+`; - } - if (holesDesc.length) { - makeSpan(c, holesDesc, "pink"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_genitals(slave, c) { - if (slave.dick > 0) { - let dickDesc = ""; - if (slave.balls === 0) { - dickDesc += 'Gelded.'; - } - if ((slave.dick > 8) && (slave.balls > 8)) { - dickDesc += `Hyper dick & balls.`; - } else if ((slave.dick > 5) && (slave.balls > 5)) { - dickDesc += `Monster dick & balls.`; - } else if ((slave.dick > 4) && (slave.balls > 4)) { - dickDesc = `Huge dick & balls.`; - } else if ((slave.dick > 3) && (slave.balls > 3)) { - dickDesc = `Big dick & balls.`; - } else if (slave.dick > 8) { - dickDesc = `Hyper dong.`; - } else if (slave.dick > 5) { - dickDesc = `Monster dong.`; - } else if (slave.dick > 4) { - dickDesc = `Huge dick.`; - } else if (slave.dick > 3) { - dickDesc = `Big dick.`; - } else if (slave.balls > 8) { - dickDesc = `Hyper balls.`; - } else if (slave.balls > 5) { - dickDesc = `Monstrous balls.`; - } else if (slave.balls > 4) { - dickDesc = `Huge balls.`; - } else if (slave.balls > 3) { - dickDesc = `Big balls.`; - } - if (dickDesc.length) { - makeSpan(c, dickDesc, "pink"); - } - } - if (slave.vagina === 0) { - makeSpan(c, "Virgin.", "lime"); - } else if ((slave.pregKnown === 1) && canWalk(slave) && (slave.clothes === "no clothing" || slave.clothes === "body oil") && (slave.shoes === "none")) { - makeSpan(c, "Naked, barefoot, and pregnant.", "pink"); - } - if (slave.anus === 0) { - makeSpan(c, "Anal virgin.", "lime"); - } - let holesDesc = ""; - if ((slave.vagina > 3) && (slave.anus > 3)) { - holesDesc += `Blown out holes.`; - } else if ((slave.vagina > 2) && (slave.anus > 2)) { - holesDesc += `High mileage.`; - } else if (slave.vagina > 3) { - holesDesc += `Cavernous pussy.`; - } else if (slave.vagina > 2) { - holesDesc += `Loose pussy.`; - } else if (slave.anus > 3) { - holesDesc += `Permagaped anus.`; - } else if (slave.anus > 2) { - holesDesc += `Gaping anus.`; - } - if (holesDesc.length) { - makeSpan(c, holesDesc, "pink"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_age(slave, c) { - let r = makeSpan(c, "", "pink"); - if (V.showAgeDetail === 1) { - r.textContent += slave.actualAge.toString(); - } else if (slave.actualAge >= 40) { - r.textContent += "40s"; - } else if (slave.actualAge >= 35) { - r.textContent += "Lt30s"; - } else if (slave.actualAge >= 30) { - r.textContent += "Ea30s"; - } else if (slave.actualAge >= 25) { - r.textContent += "Lt20s"; - } else if (slave.actualAge >= 20) { - r.textContent += "Ea20s"; - } else if (slave.actualAge >= 18) { - r.textContent += slave.actualAge.toString(); - } - if (slave.actualAge !== slave.physicalAge) { - r.textContent += ` w ${slave.physicalAge}y-bdy`; - } - if (slave.visualAge !== slave.physicalAge) { - r.textContent += ` Lks${slave.visualAge}`; - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_face(slave, c) { - if (slave.face < -95) { - makeSpan(c, "Face---", "red", true, slave.face); - } else if (slave.face < -40) { - makeSpan(c, "Face--", "red", true, slave.face); - } else if (slave.face < -10) { - makeSpan(c, "Face-", "red", true, slave.face); - } else if (slave.face <= 10) { - makeSpan(c, "Face", null, true, slave.face); - } else if (slave.face <= 40) { - makeSpan(c, "Face+", "pink", true, slave.face); - } else if (slave.face <= 95) { - makeSpan(c, "Face++", "pink", true, slave.face); - } else { - makeSpan(c, "Face+++", "pink", true, slave.face); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_eyes(slave, c) { - if (!canSee(slave)) { - makeSpan(c, "Blind", "red"); - } else if (!canSeePerfectly(slave)) { - makeSpan(c, "Sight-", "yellow"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_ears(slave, c) { - if (slave.hears === -2) { - makeSpan(c, "Deaf", "red"); - } else if ((slave.hears === -1) && (slave.earwear !== "hearing aids")) { - makeSpan(c, "Hearing-", "yellow"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_lips(slave, c) { - if (slave.lips > 95) { - makeSpan(c, "Facepussy"); - } else if (slave.lips > 70) { - makeSpan(c, "Lips+++", null, true, slave.lips); - } else if (slave.lips > 40) { - makeSpan(c, "Lips++", null, true, slave.lips); - } else if (slave.lips > 20) { - makeSpan(c, "Lips+", null, true, slave.lips); - } else if (slave.lips > 10) { - makeSpan(c, "Lips", null, true, slave.lips); - } else { - makeSpan(c, "Lips-", "red", true, slave.lips); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_teeth(slave, c) { - if (slave.teeth === "crooked") { - makeSpan(c, "Cr Teeth", "yellow"); - } else if (slave.teeth === "gapped") { - makeSpan(c, "Gap", "yellow"); - } else if (slave.teeth === "cosmetic braces") { - makeSpan(c, `Cos Braces`); - } else if (slave.teeth === "straightening braces") { - makeSpan(c, `Braces`); - } else if (slave.teeth === "removable") { - makeSpan(c, `Rem Teeth`); - } else if (slave.teeth === "pointy") { - makeSpan(c, `Fangs`); - } else if (slave.teeth === "baby") { - makeSpan(c, `Baby`); - } else if (slave.teeth === "mixed") { - makeSpan(c, `Mixed`); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_muscles(slave, c) { - if (slave.muscles > 95) { - makeSpan(c, "Musc++", undefined, true, slave.muscles); - } else if (slave.muscles > 50) { - makeSpan(c, "Musc+", undefined, true, slave.muscles); - } else if (slave.muscles > 30) { - makeSpan(c, "Fit", undefined, true, slave.muscles); - } else if (slave.muscles > 5) { - makeSpan(c, "Toned", undefined, true, slave.muscles); - } else if (slave.muscles > -6) { - makeSpan(c, "Soft", undefined, true, slave.muscles); - } else if (slave.muscles > -31) { - if (V.arcologies[0].FSPhysicalIdealist === "unset") { - makeSpan(c, "Weak", "red", true, slave.muscles); - } else { - makeSpan(c, "Soft", undefined, true, slave.muscles); - } - } else if (slave.muscles > -96) { - if (V.arcologies[0].FSPhysicalIdealist === "unset") { - makeSpan(c, "Weak+", "red", true, slave.muscles); - } else { - makeSpan(c, "Soft+", undefined, true, slave.muscles); - } - } else { - makeSpan(c, "Weak++", "red", true, slave.muscles); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_voice(slave, c) { - if (slave.voice === 0) { - makeSpan(c, "Mute", "red"); - } else { - if (slave.accent === 3) { - makeSpan(c, "Acc--", "red"); - } else if (slave.accent === 2) { - makeSpan(c, "Acc-"); - } else if (slave.accent === 4) { - makeSpan(c, "Acc--"); - } else if (slave.accent === 1) { - makeSpan(c, "Acc", "pink"); - } - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_tits_ass(slave, c) { - let styles = "pink"; - if ((slave.boobs >= 12000) && (slave.butt > 9)) { - makeSpan(c, "T&A+++", styles); - } else if ((slave.boobs > 4000) && (slave.butt > 8)) { - makeSpan(c, "T&A++", styles); - } else if ((slave.boobs > 2000) && (slave.butt > 6)) { - makeSpan(c, "T&A+", styles); - } else if ((slave.boobs > 800) && (slave.butt > 4)) { - makeSpan(c, "T&A", styles); - } else if ((slave.boobs < 500) && (slave.butt < 3) && (slave.weight <= 10) && (slave.muscles <= 30)) { - makeSpan(c, "Girlish", styles); - } else if (slave.boobs >= 12000) { - makeSpan(c, "Boobs+++", styles); - } else if (slave.boobs > 4000) { - makeSpan(c, "Boobs++", styles); - } else if (slave.boobs > 2000) { - makeSpan(c, "Boobs+", styles); - } else if (slave.boobs > 800) { - makeSpan(c, "Boobs", styles); - } else if (slave.butt > 9) { - makeSpan(c, "Ass+++", styles); - } else if (slave.butt > 8) { - makeSpan(c, "Ass++", styles); - } else if (slave.butt > 6) { - makeSpan(c, "Ass+", styles); - } else if (slave.butt > 4) { - makeSpan(c, "Ass", styles); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_hips(slave, c) { - let desc = ""; - if (slave.hips < -1) { - if (slave.butt > 2 && (V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset")) { - desc = `Disp+`; - } - } else if (slave.hips < 0) { - if (slave.butt > 4 && (V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset")) { - desc = `Disp+`; - } - } else if (slave.hips > 2) { - if (slave.butt <= 8) { - desc = `Disp-`; - } - } else if (slave.hips > 1) { - if (slave.butt <= 3 && (V.arcologies[0].FSSlimnessEnthusiast === "unset" || (slave.boobs >= 500))) { - desc = `Disp-`; - } - } else if (slave.hips > 0) { - if (slave.butt > 8) { - if ((V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset")) { - desc = `Disp+`; - } - } else if (slave.butt <= 2 && (V.arcologies[0].FSSlimnessEnthusiast === "unset" || (slave.boobs >= 500))) { - desc = `Disp-`; - } - } else { - if (slave.butt > 6) { - if ((V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset")) { - desc = `Disp+`; - } - } else if (slave.butt <= 1 && (V.arcologies[0].FSSlimnessEnthusiast === "unset" || (slave.boobs >= 500))) { - desc = `Disp-`; - } - } - if (desc) { - makeSpan(c, desc, "red"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_waist(slave, c) { - if (slave.waist > 95) { - makeSpan(c, "Wst---", "red", false, slave.waist); - } else if (slave.waist > 40) { - makeSpan(c, "Wst--", "red", false, slave.waist); - } else if (slave.waist > 10) { - makeSpan(c, "Wst-", "red", false, slave.waist); - } else if (slave.waist >= -10) { - makeSpan(c, "Wst", undefined, false, slave.waist); - } else if (slave.waist >= -40) { - makeSpan(c, "Wst+", "pink", false, slave.waist); - } else if (slave.waist >= -95) { - makeSpan(c, "Wst++", "pink", false, slave.waist); - } else { - makeSpan(c, "Wst+++", "pink", false, slave.waist); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_implants(slave, c) { - if ((slave.boobsImplant === 0) && (slave.buttImplant === 0) && (slave.waist >= -95) && (slave.lipsImplant === 0) && (slave.faceImplant <= 5) && (slave.bellyImplant === -1)) { - makeSpan(c, "Natr", "pink"); - } else { - makeSpan(c, "Impl", "pink"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_lactation(slave, c) { - if (slave.lactation === 1) { - makeSpan(c, "Lact", "pink"); - } else if (slave.lactation === 2) { - makeSpan(c, "Lact", "pink"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_mods(slave, c) { - V.modScore = SlaveStatsChecker.modScore(slave); - if (slave.corsetPiercing === 0 && V.piercingScore < 3 && V.tatScore < 2) { - return; - } else if (V.modScore > 15 || (V.piercingScore > 8 && V.tatScore > 5)) { - makeSpan(c, "Mods++"); - } else if (V.modScore > 7) { - makeSpan(c, "Mods+"); - } else { - makeSpan(c, "Mods"); - } - if (!jQuery.isEmptyObject(slave.brand)) { - makeSpan(c, "Br"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_age(slave, c) { - let r = makeSpan(c, "", "pink"); - if (V.showAgeDetail === 1) { - r.textContent += `Age ` + `${slave.actualAge}` + `.`; - } else if (slave.actualAge >= 40) { - r.textContent += `Forties.`; - } else if (slave.actualAge >= 35) { - r.textContent += `Late thirties.`; - } else if (slave.actualAge >= 30) { - r.textContent += `Early thirties.`; - } else if (slave.actualAge >= 25) { - r.textContent += `Late twenties.`; - } else if (slave.actualAge >= 20) { - r.textContent += `Early twenties.`; - } else if (slave.actualAge >= 19) { - r.textContent += `Nineteen.`; - } else if (slave.actualAge >= 18) { - r.textContent += `Eighteen.`; - } else { - r.textContent += `Underage.`; - } - /* - ** No NCS, then do the standard, However because of the wrinkles of Incubators, as long as visual age is greater - ** than or equal to physical age, we do the old physical body/Looks for fresh out of the can NCS slaves. - */ - if (((slave.geneMods.NCS === 0) || (slave.visualAge >= slave.physicalAge))) { - if (slave.actualAge !== slave.physicalAge) { - r.textContent += ` ${slave.physicalAge}` + ` year old body.`; - } - if (slave.visualAge !== slave.physicalAge) { - r.textContent += ` Looks ` + `${slave.visualAge}` + `.`; - } - } else { - /* - ** Now the rub. The use of physical Age for the year old body above, basically conflicts with the changes - ** that NCS introduces, so here to *distinguish* the changes, we use visual age with the 'year old body' - ** and appears, for example: Slave release from incubator at age 10, Her summary would show, 'Age 0. 10 - ** year old body.' But if she's given NCS a few weeks after release, while she's still before her first - ** birthday, it'll appear the same. But once her birthday fires, if we ran with the above code it would - ** say: 'Age 1. 11 year old body.' -- this conflicts with the way NCS works though, because she hasn't - ** visually aged, so our change here makes it say 'Age 1. Appears to have a 10 year old body.' - */ - r.textContent += ` Appears to have a ` + `${slave.visualAge}` + ` year old body.`; - } - if (slave.geneMods.NCS === 1) { - makeSpan(r, "NCS", "orange"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_face(slave, c) { - if (slave.face < -95) { - makeSpan(c, `Very ugly ${slave.faceShape} face`, "red", true, slave.face); - } else if (slave.face < -40) { - makeSpan(c, `Ugly ${slave.faceShape} face`, "red", true, slave.face); - } else if (slave.face < -10) { - makeSpan(c, `Unattractive ${slave.faceShape} face`, "red", true, slave.face); - } else if (slave.face <= 10) { - makeSpan(c, `Average ${slave.faceShape} face`, null, true, slave.face); - } else if (slave.face <= 40) { - makeSpan(c, `Attractive ${slave.faceShape} face`, "pink", true, slave.face); - } else if (slave.face <= 95) { - makeSpan(c, `Beautiful ${slave.faceShape} face`, "pink", true, slave.face); - } else { - makeSpan(c, `Very beautiful ${slave.faceShape} face`, "pink", true, slave.face); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_eyes(slave, c) { - if (!canSee(slave)) { - makeSpan(c, "Blind.", "red"); - } else if (!canSeePerfectly(slave)) { - makeSpan(c, "Nearsighted.", "yellow"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_ears(slave, c) { - if (slave.hears <= -2) { - makeSpan(c, "Deaf.", "red"); - } else if ((slave.hears === -1) && (slave.earwear !== "hearing aids")) { - makeSpan(c, "Hard of hearing.", "yellow"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_lips(slave, c) { - if (slave.lips > 95) { - makeSpan(c, "Facepussy", undefined, true, slave.lips); - } else if (slave.lips > 70) { - makeSpan(c, "Huge lips", undefined, true, slave.lips); - } else if (slave.lips > 40) { - makeSpan(c, "Big lips", undefined, true, slave.lips); - } else if (slave.lips > 20) { - makeSpan(c, "Pretty lips", undefined, true, slave.lips); - } else if (slave.lips > 10) { - makeSpan(c, "Normal lips", undefined, true, slave.lips); - } else { - makeSpan(c, "Thin lips", "red", true, slave.lips); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_teeth(slave, c) { - if (slave.teeth === "crooked") { - makeSpan(c, "Crooked teeth.", "yellow"); - } else if (slave.teeth === "gapped") { - makeSpan(c, "Tooth gap.", "yellow"); - } else if (slave.teeth === "cosmetic braces") { - makeSpan(c, "Cosmetic braces."); - } else if (slave.teeth === "straightening braces") { - makeSpan(c, "Braces."); - } else if (slave.teeth === "removable") { - makeSpan(c, "Removable teeth."); - } else if (slave.teeth === "pointy") { - makeSpan(c, "Sharp fangs."); - } else if (slave.teeth === "baby") { - makeSpan(c, "Baby teeth."); - } else if (slave.teeth === "mixed") { - makeSpan(c, "Mixed teeth."); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_muscles(slave, c) { - if (slave.muscles > 95) { - makeSpan(c, "Hugely muscular", undefined, true, slave.muscles); - } else if (slave.muscles > 50) { - makeSpan(c, "Muscular", undefined, true, slave.muscles); - } else if (slave.muscles > 30) { - makeSpan(c, "Fit", undefined, true, slave.muscles); - } else if (slave.muscles > 5) { - makeSpan(c, "Toned", undefined, true, slave.muscles); - } else if (slave.muscles > -6) { - makeSpan(c, "Soft", undefined, true, slave.muscles); - } else if (slave.muscles > -31) { - if (V.arcologies[0].FSPhysicalIdealist === "unset") { - makeSpan(c, "Weak", "red", true, slave.muscles); - } else { - makeSpan(c, "Weak", undefined, true, slave.muscles); - } - } else if (slave.muscles > -96) { - if (V.arcologies[0].FSPhysicalIdealist === "unset") { - makeSpan(c, "Very weak", "red", true, slave.muscles); - } else { - makeSpan(c, "Very weak", undefined, true, slave.muscles); - } - } else { - makeSpan(c, "Frail", "red", true, slave.muscles); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_voice(slave, c) { - if (slave.voice === 0) { - makeSpan(c, "Mute.", "red"); - } else { - if (slave.accent === 3) { - makeSpan(c, "Bad accent.", "red"); - } else if (slave.accent === 4) { - makeSpan(c, "No language skills.", "red"); - } else if (slave.accent === 2) { - makeSpan(c, "Accent."); - } else if (slave.accent === 1) { - makeSpan(c, "Cute accent.", "pink"); - } - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_tits_ass(slave, c) { - const styles = "pink"; - if ((slave.boobs >= 12000) && (slave.butt > 9)) { - makeSpan(c, "Hyper T&A.", styles); - } else if ((slave.boobs > 4000) && (slave.butt > 8)) { - makeSpan(c, "Enormous T&A.", styles); - } else if ((slave.boobs > 2000) && (slave.butt > 6)) { - makeSpan(c, "Huge T&A.", styles); - } else if ((slave.boobs > 800) && (slave.butt > 4)) { - makeSpan(c, "Big T&A.", styles); - } else if ((slave.boobs < 500) && (slave.butt < 3) && (slave.weight <= 10) && (slave.muscles <= 30)) { - makeSpan(c, "Girlish figure.", styles); - } else if (slave.boobs >= 12000) { - makeSpan(c, "Immobilizing tits.", styles); - } else if (slave.boobs > 4000) { - makeSpan(c, "Monstrous tits.", styles); - } else if (slave.boobs > 2000) { - makeSpan(c, "Huge tits.", styles); - } else if (slave.boobs > 800) { - makeSpan(c, "Big tits.", styles); - } else if (slave.butt > 9) { - makeSpan(c, "Hyper ass.", styles); - } else if (slave.butt > 8) { - makeSpan(c, "Titanic ass.", styles); - } else if (slave.butt > 6) { - makeSpan(c, "Huge ass.", styles); - } else if (slave.butt > 4) { - makeSpan(c, "Big ass.", styles); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_hips(slave, c) { - const styles = "red"; - if (slave.hips < -1) { - if (slave.butt > 2 && (V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset") && (V.arcologies[0].FSAssetExpansionist < 20 || V.arcologies[0].FSAssetExpansionist === "unset") && (V.arcologies[0].FSIntellectualDependencyLawBeauty === 0)) { - makeSpan(c, "Disproportionately big butt.", styles); - } - } else if (slave.hips < 0) { - if (slave.butt > 4 && (V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset") && (V.arcologies[0].FSAssetExpansionist < 20 || V.arcologies[0].FSAssetExpansionist === "unset") && (V.arcologies[0].FSIntellectualDependencyLawBeauty === 0)) { - makeSpan(c, "Disproportionately big butt.", styles); - } - } else if (slave.hips > 2) { - if (slave.butt <= 8) { - makeSpan(c, "Disproportionately small butt.", styles); - } - } else if (slave.hips > 1) { - if (slave.butt <= 3 && ((V.arcologies[0].FSSlimnessEnthusiast === "unset") || (slave.boobs >= 500))) { - makeSpan(c, "Disproportionately small butt.", styles); - } - } else if (slave.hips > 0) { - if (slave.butt > 8) { - if ((V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset") && (V.arcologies[0].FSAssetExpansionist < 20 || V.arcologies[0].FSAssetExpansionist === "unset") && (V.arcologies[0].FSIntellectualDependencyLawBeauty === 0)) { - makeSpan(c, "Disproportionately big butt.", styles); - } - } else if (slave.butt <= 2 && ((V.arcologies[0].FSSlimnessEnthusiast === "unset") || (slave.boobs >= 500))) { - makeSpan(c, "Disproportionately small butt.", styles); - } - } else { - if (slave.butt > 6) { - if ((V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset") && (V.arcologies[0].FSAssetExpansionist < 20 || V.arcologies[0].FSAssetExpansionist === "unset") && (V.arcologies[0].FSIntellectualDependencyLawBeauty === 0)) { - makeSpan(c, "Disproportionately big butt.", styles); - } - } else if (slave.butt <= 1 && ((V.arcologies[0].FSSlimnessEnthusiast === "unset") || (slave.boobs >= 500))) { - makeSpan(c, "Disproportionately small butt.", styles); - } - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_waist(slave, c) { - if (slave.waist > 95) { - makeSpan(c, "Masculine waist", "red", true, slave.waist); - } else if (slave.waist > 40) { - makeSpan(c, "Ugly waist", "red", true, slave.waist); - } else if (slave.waist > 10) { - makeSpan(c, "Unattractive waist", "red", true, slave.waist); - } else if (slave.waist >= -10) { - makeSpan(c, "Average waist", null, true, slave.waist); - } else if (slave.waist >= -40) { - makeSpan(c, "Feminine waist", "pink", true, slave.waist); - } else if (slave.waist >= -95) { - makeSpan(c, "Hourglass waist", "pink", true, slave.waist); - } else { - makeSpan(c, "Absurdly narrow waist", "pink", true, slave.waist); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_implants(slave, c) { - const styles = "pink"; - if ((slave.boobsImplant !== 0) || (slave.buttImplant !== 0) || (slave.lipsImplant !== 0) || (slave.bellyImplant !== -1)) { - makeSpan(c, "Implants.", styles); - } else if ((slave.faceImplant >= 30) || (slave.waist < -95)) { - makeSpan(c, "Surgery enhanced.", styles); - } else { - makeSpan(c, "All natural.", styles); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_lactation(slave, c) { - if (slave.lactation === 1) { - makeSpan(c, "Lactating naturally.", "pink"); - } else if (slave.lactation === 2) { - makeSpan(c, "Heavy lactation.", "pink"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_mods(slave, c) { - V.modScore = SlaveStatsChecker.modScore(slave); - if (slave.corsetPiercing === 0 && V.piercingScore < 3 && V.tatScore < 2) { - return; - } else if (V.modScore > 15 || (V.piercingScore > 8 && V.tatScore > 5)) { - makeSpan(c, "Extensive body mods."); - } else if (V.modScore > 7) { - makeSpan(c, "Noticeable body mods."); - } else { - makeSpan(c, "Light body mods."); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_intelligence(slave, c) { - const intelligence = slave.intelligence + slave.intelligenceImplant; - if (slave.fetish === "mindbroken") { - return; - } - let education = ""; - let naturalIntelligence = ""; - let styles = undefined; - if (slave.intelligenceImplant >= 30) { - education = "(e+)"; - } else if (slave.intelligenceImplant >= 15) { - education = "(e)"; - } else if (slave.intelligenceImplant <= -15) { - education = "(e-)"; - } - if (intelligence >= 130) { - naturalIntelligence = "I++++"; - styles = "deepskyblue"; - } else if (intelligence > 95) { - naturalIntelligence = "I+++"; - styles = "deepskyblue"; - } else if (intelligence > 50) { - naturalIntelligence = "I++"; - styles = "deepskyblue"; - } else if (intelligence > 15) { - naturalIntelligence = "I+"; - styles = "deepskyblue"; - } else if (intelligence >= -15) { - naturalIntelligence = "I"; - } else if (intelligence >= -50) { - naturalIntelligence = "I-"; - styles = "orangered"; - } else if (intelligence >= -95) { - naturalIntelligence = "I--"; - styles = "orangered"; - } else { - naturalIntelligence = "I---"; - styles = "orangered"; - } - makeSpan(c, `${naturalIntelligence}${education}`, styles, true, intelligence); - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_skills(slave, c) { - let _SSkills = slave.skill.anal + slave.skill.oral; - let r = makeSpan(c, "", "aquamarine"); - if (((_SSkills + slave.skill.whoring + slave.skill.entertainment) >= 400) && ((slave.vagina < 0) || (slave.skill.vaginal >= 100))) { - r.textContent += `MSS`; - } else { - _SSkills += slave.skill.vaginal; - _SSkills = Math.trunc(_SSkills); - if (_SSkills > 180) { - r.textContent += `S++`; - } else if ((_SSkills > 120) && (slave.vagina < 0)) { - r.textContent += `Sh++`; - } else if (_SSkills > 90) { - r.textContent += `S+`; - } else if (_SSkills > 30) { - r.textContent += `S`; - } else { - r.textContent += `S-`; - } - if (V.summaryStats) { - r.textContent += `[${_SSkills}]`; - } - r.textContent += " "; - if (slave.skill.whoring >= 100) { - r.textContent += `W+++`; - } else if (slave.skill.whoring > 60) { - r.textContent += `W++`; - } else if (slave.skill.whoring > 30) { - r.textContent += `W+`; - } else if (slave.skill.whoring > 10) { - r.textContent += `W`; - } - if (slave.skill.whoring > 10) { - if (V.summaryStats) { - r.textContent += `[${slave.skill.whoring}]`; - } - } - r.textContent += " "; - if (slave.skill.entertainment >= 100) { - r.textContent += `E+++`; - } else if (slave.skill.entertainment > 60) { - r.textContent += `E++`; - } else if (slave.skill.entertainment > 30) { - r.textContent += `E+`; - } else if (slave.skill.entertainment > 10) { - r.textContent += `E`; - } - if (slave.skill.entertainment > 10) { - if (V.summaryStats) { - r.textContent += `[${slave.skill.entertainment}]`; - } - } - } - if (slave.skill.combat > 0) { - r.textContent += " C"; - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_prestige(slave, c) { - if (slave.prestige > 0) { - const styles = "green"; - if (slave.prestige > 2) { - makeSpan(c, "Prest++", styles); - } else if (slave.prestige === 2) { - makeSpan(c, "Prest+", styles); - } else if (slave.prestige === 1) { - makeSpan(c, "Prest", styles); - } - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_porn_prestige(slave, c) { - if (slave.porn.prestige > 0) { - const styles = "green"; - if (slave.porn.prestige > 2) { - makeSpan(c, "PPrest++", styles); - } else if (slave.porn.prestige === 2) { - makeSpan(c, "PPrest+", styles); - } else if (slave.porn.prestige === 1) { - makeSpan(c, "PPrest", styles); - } - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_intelligence(slave, c) { - const intelligence = slave.intelligence + slave.intelligenceImplant; - if (slave.fetish === "mindbroken") { - return; - } - let education = ""; - let naturalIntelligence = ""; - let styles = undefined; - if (slave.intelligenceImplant >= 30) { - education = ", well educated"; - } else if (slave.intelligenceImplant >= 15) { - education = ", educated"; - } else if (slave.intelligenceImplant <= -15) { - education = ", hindered"; - } - if (intelligence >= 130) { - naturalIntelligence = "Genius"; - styles = "deepskyblue"; - } else if (intelligence > 95) { - naturalIntelligence = "Brilliant"; - styles = "deepskyblue"; - } else if (intelligence > 50) { - naturalIntelligence = "Very smart"; - styles = "deepskyblue"; - } else if (intelligence > 15) { - naturalIntelligence = "Smart"; - styles = "deepskyblue"; - } else if (intelligence >= -15) { - naturalIntelligence = "Average intelligence"; - } else if (intelligence >= -50) { - naturalIntelligence = "Slow"; - styles = "orangered"; - } else if (intelligence >= -95) { - naturalIntelligence = "Very slow"; - styles = "orangered"; - } else { - naturalIntelligence = "Moronic"; - styles = "orangered"; - } - makeSpan(c, `${naturalIntelligence}${education}`, styles, true, intelligence); - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_skills(slave, c) { - let _SSkills = (slave.skill.anal + slave.skill.oral); - if (((_SSkills + slave.skill.whoring + slave.skill.entertainment) >= 400) && ((slave.vagina < 0) || (slave.skill.vaginal >= 100))) { - makeSpan(c, "Masterful Sex Slave.", "aquamarine"); - } else { - let desc; - _SSkills += slave.skill.vaginal; - if (_SSkills > 180) { - desc = "Sex master"; - } else if ((_SSkills > 120) && (slave.vagina < 0)) { - desc = "Masterful shemale"; - } else if (_SSkills > 90) { - desc = "Sexual expert"; - } else if (_SSkills > 30) { - desc = "Sexually skilled"; - } else { - desc = "Sexually unskilled"; - } - if (desc) { - makeSpan(c, desc, "aquamarine", true, Math.trunc(_SSkills)); - desc = ""; - } - if (slave.skill.whoring >= 100) { - desc = "Masterful whore"; - } else if (slave.skill.whoring >= 60) { - desc = "Expert whore"; - } else if (slave.skill.whoring >= 30) { - desc = "Skilled whore"; - } else if (slave.skill.whoring >= 10) { - desc = "Basic whore"; - } - if (desc) { - makeSpan(c, desc, "aquamarine", true, slave.skill.whoring); - desc = ""; - } - if (slave.skill.entertainment >= 100) { - desc = "Masterful entertainer"; - } else if (slave.skill.entertainment >= 60) { - desc = "Expert entertainer"; - } else if (slave.skill.entertainment >= 30) { - desc = "Skilled entertainer"; - } else if (slave.skill.entertainment >= 10) { - desc = "Basic entertainer"; - } - if (desc) { - makeSpan(c, desc, "aquamarine", true, slave.skill.entertainment); - desc = ""; - } - } - if (slave.skill.combat > 0) { - makeSpan(c, "Trained fighter.", "aquamarine"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_prestige(slave, c) { - if (slave.prestige > 0) { - const styles = "green"; - if (slave.prestige > 2) { - makeSpan(c, "Extremely prestigious.", styles); - } else if (slave.prestige === 2) { - makeSpan(c, "Very prestigious.", styles); - } else if (slave.prestige === 1) { - makeSpan(c, "Prestigious.", styles); - } - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_porn_prestige(slave, c) { - if (slave.porn.prestige > 0) { - const styles = "green"; - if (slave.porn.prestige > 2) { - makeSpan(c, "Porn star.", styles); - } else if (slave.porn.prestige === 2) { - makeSpan(c, "Porn slut.", styles); - } else if (slave.porn.prestige === 1) { - makeSpan(c, "Porn amateur.", styles); - } - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_fetish(slave, c) { - let descStr = ""; - switch (slave.fetish) { - case "submissive": - if (slave.fetishStrength > 95) { - descStr = `Sub++`; - } else if (slave.fetishStrength > 60) { - descStr = `Sub+`; - } else { - descStr = `Sub`; - } - break; - case "cumslut": - if (slave.fetishStrength > 95) { - descStr = `Oral++`; - } else if (slave.fetishStrength > 60) { - descStr = `Oral+`; - } else { - descStr = `Oral`; - } - break; - case "humiliation": - if (slave.fetishStrength > 95) { - descStr = `Humil++`; - } else if (slave.fetishStrength > 60) { - descStr = `Humil+`; - } else { - descStr = `Humil`; - } - break; - case "buttslut": - if (slave.fetishStrength > 95) { - descStr = `Anal++`; - } else if (slave.fetishStrength > 60) { - descStr = `Anal+`; - } else { - descStr = `Anal`; - } - break; - case "boobs": - if (slave.fetishStrength > 95) { - descStr = `Boobs++`; - } else if (slave.fetishStrength > 60) { - descStr = `Boobs+`; - } else { - descStr = `Boobs`; - } - break; - case "sadist": - if (slave.fetishStrength > 95) { - descStr = `Sadist++`; - } else if (slave.fetishStrength > 60) { - descStr = `Sadist+`; - } else { - descStr = `Sadist`; - } - break; - case "masochist": - if (slave.fetishStrength > 95) { - descStr = `Pain++`; - } else if (slave.fetishStrength > 60) { - descStr = `Pain+`; - } else { - descStr = `Pain`; - } - break; - case "dom": - if (slave.fetishStrength > 95) { - descStr = `Dom++`; - } else if (slave.fetishStrength > 60) { - descStr = `Dom+`; - } else { - descStr = `Dom`; - } - break; - case "pregnancy": - if (slave.fetishStrength > 95) { - descStr = `Preg++`; - } else if (slave.fetishStrength > 60) { - descStr = `Preg+`; - } else { - descStr = `Preg`; - } - break; - default: - descStr = `Vanilla`; - break; - } - if (V.summaryStats) { - descStr += `[${slave.fetishStrength}]`; - } - makeSpan(c, descStr, "lightcoral"); - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_attraction(slave, c) { - if (slave.attrXY <= 5) { - makeSpan(c, "XY---", "red", false, slave.attrXY); - } else if (slave.attrXY <= 15) { - makeSpan(c, "XY--", "red", false, slave.attrXY); - } else if (slave.attrXY <= 35) { - makeSpan(c, "XY---", "red", false, slave.attrXY); - } else if (slave.attrXY <= 65) { - makeSpan(c, "XY", undefined, false, slave.attrXY); - } else if (slave.attrXY <= 85) { - makeSpan(c, "XY+", "green", false, slave.attrXY); - } else if (slave.attrXY <= 95) { - makeSpan(c, "XY++", "green", false, slave.attrXY); - } else if (slave.attrXX > 95) { - if (slave.energy <= 95) { - makeSpan(c, "Omni!", "green"); - } else { - makeSpan(c, "Omni+Nympho!!", "green"); - } - } else { - makeSpan(c, "XY+++", "green", false, slave.attrXY); - } - if (slave.attrXX <= 5) { - makeSpan(c, "XX---", "red", false, slave.attrXX); - } else if (slave.attrXX <= 15) { - makeSpan(c, "XX--", "red", false, slave.attrXX); - } else if (slave.attrXX <= 35) { - makeSpan(c, "XX-", "red", false, slave.attrXX); - } else if (slave.attrXX <= 65) { - makeSpan(c, "XX", undefined, false, slave.attrXX); - } else if (slave.attrXX <= 85) { - makeSpan(c, "XX+", "green", false, slave.attrXX); - } else if (slave.attrXX <= 95) { - makeSpan(c, "XX++", "green", false, slave.attrXX); - } else if (slave.attrXY <= 95) { - makeSpan(c, "XX+++", "green", false, slave.attrXX); - } - if (slave.energy > 95) { - if ((slave.attrXY <= 95) || (slave.attrXX <= 95)) { - makeSpan(c, "Nympho!", "green"); - } - } else if (slave.energy > 80) { - makeSpan(c, "SD++", "green", false, slave.energy); - } else if (slave.energy > 60) { - makeSpan(c, "SD+", "green", false, slave.energy); - } else if (slave.energy > 40) { - makeSpan(c, "SD", "green", false, slave.energy); - } else if (slave.energy > 20) { - makeSpan(c, "SD-", "red", false, slave.energy); - } else { - makeSpan(c, "SD--", "red", false, slave.energy); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_smart_fetish(slave, c) { - function settingStr() { - if (slave.fetishKnown === 1) { - if (slave.clitSetting === "off") { - return `SP-`; - } else if (((slave.fetish !== "submissive") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "submissive")) { - return `SP:sub`; - } else if (((slave.fetish !== "cumslut") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "oral")) { - return `SP:oral`; - } else if (((slave.fetish !== "humiliation") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "humiliation")) { - return `SP:humil`; - } else if (((slave.fetish !== "buttslut") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "anal")) { - return `SP:anal`; - } else if (((slave.fetish !== "boobs") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "boobs")) { - return `SP:boobs`; - } else if (((slave.fetish !== "sadist") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "sadist")) { - return `SP:sade`; - } else if (((slave.fetish !== "masochist") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "masochist")) { - return `SP:pain`; - } else if (((slave.fetish !== "dom") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "dom")) { - return `SP:dom`; - } else if (((slave.fetish !== "pregnancy") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "pregnancy")) { - return `SP:preg`; - } else if (((slave.fetish !== "none") && (slave.clitSetting === "vanilla"))) { - return `SP:vanilla`; - } else if ((slave.energy <= 95) && (slave.clitSetting === "all")) { - return `SP:all`; - } else if ((slave.energy > 5) && (slave.clitSetting === "none")) { - return `SP:none`; - } else if (!["anti-men", "anti-women", "men", "women"].includes(slave.clitSetting)) { - return `SP:monitoring`; - } - } else { - switch (slave.clitSetting) { - case "off": - return `SP-`; - case "submissive": - return `SP:sub`; - case "lesbian": - return `SP:les`; - case "oral": - return `SP:oral`; - case "humiliation": - return `SP:humil`; - case "anal": - return `SP:anal`; - case "boobs": - return `SP:boobs`; - case "sadist": - return `SP:sade`; - case "masochist": - return `SP:pain`; - case "dom": - return `SP:dom`; - case "pregnancy": - return `SP:pregnancy`; - case "vanilla": - return `SP:vanilla`; - case "all": - return `SP:all`; - case "none": - return `SP:none`; - } - } - return null; - } - const s = settingStr(); - if (s) { - makeSpan(c, settingStr()); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_smart_attraction(slave, c) { - function settingStr() { - if (slave.attrKnown === 1) { - if (slave.clitSetting === "women") { - if (slave.attrXX < 95) { - return `SP:women`; - } else { - return `SP:monitoring`; - } - } else if (slave.clitSetting === "men") { - if (slave.attrXY < 95) { - return `SP:men`; - } else { - return `SP:monitoring`; - } - } else if (slave.clitSetting === "anti-women") { - if (slave.attrXX > 0) { - return `SP:anti-women`; - } else { - return `SP:monitoring`; - } - } else if (slave.clitSetting === "anti-men") { - if (slave.attrXY > 0) { - return `SP:anti-men`; - } else { - return `SP:monitoring`; - } - } - } else { - if (slave.clitSetting === "women") { - return `SP:women`; - } else if (slave.clitSetting === "men") { - return `SP:men`; - } else if (slave.clitSetting === "anti-women") { - return `SP:anti-women`; - } else if (slave.clitSetting === "anti-men") { - return `SP:anti-men`; - } - } - return null; - } - const s = settingStr(); - if (s) { - makeSpan(c, settingStr()); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_behavior_flaw(slave, c) { - function descStr() { - switch (slave.behavioralFlaw) { - case "arrogant": - return `Arrog`; - case "bitchy": - return `Bitchy`; - case "odd": - return `Odd`; - case "hates men": - return `Men-`; - case "hates women": - return `Women-`; - case "gluttonous": - return `Glut`; - case "anorexic": - return `Ano`; - case "devout": - return `Dev`; - case "liberated": - return `Lib`; - default: - slave.behavioralFlaw = "none"; - return null; - } - } - const s = descStr(); - if (s) { - makeSpan(c, descStr(), "red"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_sex_flaw(slave, c) { - switch (slave.sexualFlaw) { - case "hates oral": - makeSpan(c, "Oral-", "red"); - break; - case "hates anal": - makeSpan(c, "Anal-", "red"); - break; - case "hates penetration": - makeSpan(c, "Fuck-", "red"); - break; - case "shamefast": - makeSpan(c, "Shame", "red"); - break; - case "idealistic": - makeSpan(c, "Ideal", "red"); - break; - case "repressed": - makeSpan(c, "Repre", "red"); - break; - case "apathetic": - makeSpan(c, "Apath", "red"); - break; - case "crude": - makeSpan(c, "Crude", "red"); - break; - case "judgemental": - makeSpan(c, "Judge", "red"); - break; - case "cum addict": - makeSpan(c, "CumAdd", "yellow"); - break; - case "anal addict": - makeSpan(c, "AnalAdd", "yellow"); - break; - case "attention whore": - makeSpan(c, "Attention", "yellow"); - break; - case "breast growth": - makeSpan(c, "BoobObsess", "yellow"); - break; - case "abusive": - makeSpan(c, "Abusive", "yellow"); - break; - case "malicious": - makeSpan(c, "Malice", "yellow"); - break; - case "self hating": - makeSpan(c, "SelfHatr", "yellow"); - break; - case "neglectful": - makeSpan(c, "SelfNeglect", "yellow"); - break; - case "breeder": - makeSpan(c, "BreedObsess", "yellow"); - break; - default: - slave.sexualFlaw = "none"; - break; - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_behavior_quirk(slave, c) { - function descStr() { - switch (slave.behavioralQuirk) { - case "confident": - return `Confid`; - case "cutting": - return `Cutting`; - case "funny": - return `Funny`; - case "fitness": - return `Fit`; - case "adores women": - return `Women+`; - case "adores men": - return `Men+`; - case "insecure": - return `Insec`; - case "sinful": - return `Sinf`; - case "advocate": - return `Advoc`; - default: - slave.behavioralQuirk = "none"; - return null; - } - } - const s = descStr(); - if (s) { - makeSpan(c, s, "green"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_sex_quirk(slave, c) { - function descStr() { - switch (slave.sexualQuirk) { - case "gagfuck queen": - return `Gagfuck`; - case "painal queen": - return `Painal`; - case "strugglefuck queen": - return `Struggle`; - case "tease": - return `Tease`; - case "romantic": - return `Romantic`; - case "perverted": - return `Perverted`; - case "caring": - return `Caring`; - case "unflinching": - return `Unflinch`; - case "size queen": - return `SizeQ`; - default: - slave.sexualQuirk = "none"; - return null; - } - } - const s = descStr(); - if (s) { - makeSpan(c, s, "green"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_fetish(slave, c) { - function fetishStr() { - switch (slave.fetish) { - case "submissive": - if (slave.fetishStrength > 95) { - return "Complete submissive"; - } else if (slave.fetishStrength > 60) { - return "Submissive"; - } else { - return "Submissive tendencies"; - } - case "cumslut": - if (slave.fetishStrength > 95) { - return "Cumslut"; - } else if (slave.fetishStrength > 60) { - return "Oral fixation"; - } else { - return "Prefers oral"; - } - case "humiliation": - if (slave.fetishStrength > 95) { - return "Humiliation slut"; - } else if (slave.fetishStrength > 60) { - return "Exhibitionist"; - } else { - return "Interest in humiliation"; - } - case "buttslut": - if (slave.fetishStrength > 95) { - return "Buttslut"; - } else if (slave.fetishStrength > 60) { - return "Anal fixation"; - } else { - return "Prefers anal"; - } - case "boobs": - if (slave.fetishStrength > 95) { - return "Boobslut"; - } else if (slave.fetishStrength > 60) { - return "Breast fixation"; - } else { - return "Loves boobs"; - } - case "sadist": - if (slave.fetishStrength > 95) { - return "Complete sadist"; - } else if (slave.fetishStrength > 60) { - return "Sadist"; - } else { - return "Sadistic tendencies"; - } - case "masochist": - if (slave.fetishStrength > 95) { - return "Complete masochist"; - } else if (slave.fetishStrength > 60) { - return "Masochist"; - } else { - return "Masochistic tendencies"; - } - case "dom": - if (slave.fetishStrength > 95) { - return "Complete dom"; - } else if (slave.fetishStrength > 60) { - return "Dominant"; - } else { - return "Dominant tendencies"; - } - case "pregnancy": - if (slave.fetishStrength > 95) { - return "Pregnancy fetish"; - } else if (slave.fetishStrength > 60) { - return "Pregnancy kink"; - } else { - return "Interest in impregnation"; - } - default: - return "Sexually vanilla"; - } - } - makeSpan(c, fetishStr(), "lightcoral", true, slave.fetishStrength); - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_attraction(slave, c) { - if (slave.attrXY <= 5) { - makeSpan(c, "Disgusted by men", "red", true, slave.attrXY); - } else if (slave.attrXY <= 15) { - makeSpan(c, "Turned off by men", "red", true, slave.attrXY); - } else if (slave.attrXY <= 35) { - makeSpan(c, "Not attracted to men", "red", true, slave.attrXY); - } else if (slave.attrXY <= 65) { - makeSpan(c, "Indifferent to men", undefined, true, slave.attrXY); - } else if (slave.attrXY <= 85) { - makeSpan(c, "Attracted to men", "green", true, slave.attrXY); - } else if (slave.attrXY <= 95) { - makeSpan(c, "Aroused by men", "green", true, slave.attrXY); - } else if (slave.attrXX > 95) { - if (slave.energy <= 95) { - makeSpan(c, "Omnisexual!", "green"); - } else { - makeSpan(c, "Omnisexual nymphomaniac!", "green"); - } - } else { - makeSpan(c, "Passionate about men", "green", true, slave.attrXY); - } - if (slave.attrXX <= 5) { - makeSpan(c, "disgusted by women", "red", true, slave.attrXX); - } else if (slave.attrXX <= 15) { - makeSpan(c, "turned off by women", "red", true, slave.attrXX); - } else if (slave.attrXX <= 35) { - makeSpan(c, "not attracted to women", "red", true, slave.attrXX); - } else if (slave.attrXX <= 65) { - makeSpan(c, "indifferent to women", undefined, true, slave.attrXX); - } else if (slave.attrXX <= 85) { - makeSpan(c, "attracted to women", "green", true, slave.attrXX); - } else if (slave.attrXX <= 95) { - makeSpan(c, "aroused by women", "green", true, slave.attrXX); - } else if (slave.attrXY <= 95) { - makeSpan(c, "passionate about women", "green", true, slave.attrXX); - } - if (slave.energy > 95) { - if ((slave.attrXY <= 95) || (slave.attrXX <= 95)) { - makeSpan(c, "Nymphomaniac!", "green"); - } - } else if (slave.energy > 80) { - makeSpan(c, "Powerful sex drive", "green", true, slave.energy); - } else if (slave.energy > 60) { - makeSpan(c, "Good sex drive", "green", true, slave.energy); - } else if (slave.energy > 40) { - makeSpan(c, "Average sex drive", "yellow", true, slave.energy); - } else if (slave.energy > 20) { - makeSpan(c, "Poor sex drive", "red", true, slave.energy); - } else { - makeSpan(c, "No sex drive", "red", true, slave.energy); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_smart_fetish(slave, c) { - function descStr() { - if (slave.fetishKnown === 1) { - if (slave.clitSetting === "off") { - return `SP off.`; - } else if (((slave.fetish !== "submissive") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "submissive")) { - return `SP: submissive.`; - } else if (((slave.fetish !== "cumslut") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "oral")) { - return `SP: oral.`; - } else if (((slave.fetish !== "humiliation") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "humiliation")) { - return `SP: humiliation.`; - } else if (((slave.fetish !== "buttslut") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "anal")) { - return `SP: anal.`; - } else if (((slave.fetish !== "boobs") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "boobs")) { - return `SP: breasts.`; - } else if (((slave.fetish !== "sadist") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "sadist")) { - return `SP: sadism.`; - } else if (((slave.fetish !== "masochist") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "masochist")) { - return `SP: masochism.`; - } else if (((slave.fetish !== "dom") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "dom")) { - return `SP: dominance.`; - } else if (((slave.fetish !== "pregnancy") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "pregnancy")) { - return `SP: pregnancy.`; - } else if ((slave.fetish !== "none") && (slave.clitSetting === "vanilla")) { - return `SP: vanilla.`; - } else if ((slave.energy <= 95) && (slave.clitSetting === "all")) { - return `SP: all.`; - } else if ((slave.energy > 5) && (slave.clitSetting === "none")) { - return `SP: none.`; - } else if (!["anti-men", "anti-women", "men", "women"].includes(slave.clitSetting)) { - return `SP: monitoring.`; - } - } else { - switch (slave.clitSetting) { - case "off": - return `SP off.`; - case "submissive": - return `SP: submissive.`; - case "oral": - return `SP: oral.`; - case "humiliation": - return `SP: humiliation.`; - case "anal": - return `SP: anal.`; - case "boobs": - return `SP: breasts.`; - case "sadist": - return `SP: sadism.`; - case "masochist": - return `SP: masochism.`; - case "dom": - return `SP: dominance.`; - case "pregnancy": - return `SP: pregnancy.`; - case "vanilla": - return `SP: vanilla.`; - case "all": - return `SP: all.`; - case "none": - return `SP: none.`; - } - } - return null; - } - const s = descStr(); - if (s) { - makeSpan(c, s); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_smart_attraction(slave, c) { - if (slave.attrKnown === 1) { - if ((slave.attrXX < 100) && (slave.clitSetting === "women")) { - makeSpan(c, `SP: women.`); - } else if ((slave.attrXY < 100) && (slave.clitSetting === "men")) { - makeSpan(c, `SP: men.`); - } - } else { - if (slave.clitSetting === "women") { - makeSpan(c, `SP: women.`); - } else if (slave.clitSetting === "men") { - makeSpan(c, `SP: men.`); - } - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_behavior_flaw(slave, c) { - function descStr() { - switch (slave.behavioralFlaw) { - case "arrogant": - return `Arrogant.`; - case "bitchy": - return `Bitchy.`; - case "odd": - return `Odd.`; - case "hates men": - return `Hates men.`; - case "hates women": - return `Hates women.`; - case "gluttonous": - return `Stress eater.`; - case "anorexic": - return `Anorexic.`; - case "devout": - return `Devoutly religious.`; - case "liberated": - return `Mentally liberated.`; - default: - slave.behavioralFlaw = "none"; - return null; - } - } - const s = descStr(); - if (s) { - makeSpan(c, s, "red"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_sex_flaw(slave, c) { - switch (slave.sexualFlaw) { - case "hates oral": - case "hates anal": - case "hates penetration": - case "shamefast": - makeSpan(c, slave.sexualFlaw, "red", true); - break; - case "idealistic": - case "repressed": - case "apathetic": - case "crude": - case "judgemental": - makeSpan(c, `Sexually ${slave.sexualFlaw}.`, "red"); - break; - case "cum addict": - case "anal addict": - case "attention whore": - makeSpan(c, slave.sexualFlaw, "yellow", true); - break; - case "breast growth": - makeSpan(c, `Breast obsession.`, "yellow"); - break; - case "abusive": - case "malicious": - makeSpan(c, `Sexually ${slave.sexualFlaw}.`, "yellow"); - break; - case "self hating": - makeSpan(c, `Self hatred.`, "yellow"); - break; - case "neglectful": - makeSpan(c, `Self neglectful.`, "yellow"); - break; - case "breeder": - makeSpan(c, `Breeding obsession.`, "yellow"); - break; - default: - slave.sexualFlaw = "none"; - break; - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_behavior_quirk(slave, c) { - switch (slave.behavioralQuirk) { - case "confident": - case "cutting": - case "funny": - case "fitness": - case "adores women": - case "adores men": - case "insecure": - case "sinful": - case "advocate": - makeSpan(c, slave.behavioralQuirk, "green", true); - break; - default: - slave.behavioralQuirk = "none"; - break; - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_sex_quirk(slave, c) { - switch (slave.sexualQuirk) { - case "gagfuck queen": - case "painal queen": - case "strugglefuck queen": - case "tease": - case "romantic": - case "perverted": - case "caring": - case "unflinching": - case "size queen": - makeSpan(c, slave.sexualQuirk, "green", true); - break; - default: - slave.sexualQuirk = "none"; - break; - } - } + function displayOptionsFragment() { + const res = document.createDocumentFragment(); + + // SAH is "Summarized, Abbreviated, Hidden" + const SAHOptions = { + "Summarized": 2, + "Abbreviated": 1, + "Hidden": 0 + }; + + function appendOption(name, desc, options) { + res.append(App.UI.DOM.Widgets.optionSelector((value) => { + V.UI.slaveSummary.abbreviation[name] = value; Engine.play(passage()); + }, + options, V.UI.slaveSummary.abbreviation[name], desc)); + } + + function appendSAHOption(name, desc) { + appendOption(name, desc, SAHOptions); + } + + appendSAHOption("devotion", "Mental stats are"); + appendSAHOption("mental", "Mental attributes are"); + appendSAHOption("rules", "Rules are"); + appendSAHOption("health", "Health is"); + appendSAHOption("diet", "Diet and weight are"); + appendSAHOption("drugs", "Drugs and addiction are"); + appendSAHOption("hormoneBalance", "Hormone balance is"); + appendSAHOption("genitalia", "Genitalia are"); + appendSAHOption("physicals", "Physical traits are"); + appendSAHOption("skills", "Skills are"); + appendSAHOption("nationality", "Nationality is"); + appendSAHOption("race", "Race is"); + appendOption("rulesets", "Rules Assistant rulesets are", { + "Summarized": 2, + "Abbreviated": 1 + }); + appendOption("clothes", "Clothes are", { + "Summarized": 2, + "Hidden": 0 + }); + appendOption("origins", "Origins are", { + "Summarized": 2, + "Hidden": 0 + }); - /** - * @param {App.Entity.SlaveState} slave - * @returns {string} - */ - function short_extended_family(slave) { - let res = ""; - let handled = 0; - if (slave.mother > 0) { - const _ssj = V.slaves.findIndex(s => s.ID === slave.mother); - if (_ssj !== -1) { - res += `${SlaveFullName(V.slaves[_ssj])}'s ${getPronouns(slave).daughter}`; - if (slave.relationshipTarget === V.slaves[_ssj].ID) { - const friendShipShort = relationshipTermShort(slave); - res += ` & ${friendShipShort}`; - handled = 1; - } - } - res += " "; - } else if (slave.mother === -1) { - res += `Your ${getPronouns(slave).daughter}`; - if (slave.relationship < -1) { - res += ` & ${PCrelationshipTerm(slave)}`; - handled = 1; - } - res += " "; - } else if (slave.mother in V.missingTable && V.showMissingSlavesSD && V.showMissingSlaves) { - res += `${V.missingTable[slave.mother].fullName}'s ${getPronouns(slave).daughter} `; - } - if (slave.father > 0 && slave.father !== slave.mother) { - const _ssj = V.slaves.findIndex(s => s.ID === slave.father); - if (_ssj !== -1) { - res += `${SlaveFullName(V.slaves[_ssj])}'s ${getPronouns(slave).daughter}`; - if (slave.relationshipTarget === V.slaves[_ssj].ID && handled !== 1) { - const friendShipShort = relationshipTermShort(slave); - res += ` & ${friendShipShort}`; - handled = 1; - } - } - res += " "; - } else if (slave.father === -1 && slave.mother !== -1) { - res += `Your ${getPronouns(slave).daughter}`; - if (slave.relationship < -1) { - res += ` & ${PCrelationshipTerm(slave)}`; - handled = 1; - } - res += " "; - } else if (slave.father in V.missingTable && slave.father !== slave.mother && V.showMissingSlavesSD && V.showMissingSlaves) { - res += `${V.missingTable[slave.father].fullName}'s ${getPronouns(slave).daughter}`; - } - if (slave.daughters === 1) { - let _ssj = V.slaves.findIndex(s => s.mother === slave.ID); - if (_ssj !== -1) { - res += `${SlaveFullName(V.slaves[_ssj])}'s mother`; - if (slave.relationshipTarget === V.slaves[_ssj].ID) { - const friendShipShort = relationshipTermShort(slave); - res += ` & ${friendShipShort}`; - handled = 1; - } - } - res += " "; - _ssj = V.slaves.findIndex(s => s.father === slave.ID); - if (_ssj !== -1) { - res += `${SlaveFullName(V.slaves[_ssj])}'s father`; - if (slave.relationshipTarget === V.slaves[_ssj].ID && handled !== 1) { - const friendShipShort = relationshipTermShort(slave); - res += ` & ${friendShipShort}`; - handled = 1; - } - } - res += " "; - } else if (slave.daughters > 1) { - res += `multiple daughters `; - } - if (slave.sisters === 1) { - const _ssj = V.slaves.findIndex(s => areSisters(s, slave) > 0); - if (_ssj !== -1) { - res += `${SlaveFullName(V.slaves[_ssj])}'s ${getPronouns(slave).sister}`; - if (slave.relationshipTarget === V.slaves[_ssj].ID) { - const friendShipShort = relationshipTermShort(slave); - res += `& ${friendShipShort}`; - handled = 1; - } - } - res += " "; - } else if (slave.sisters > 1) { - res += `multiple sisters `; - } - if (slave.relationship > 0 && handled !== 1) { - const _ssj = V.slaves.findIndex(s => s.ID === slave.relationshipTarget); - if (_ssj !== -1) { - res += `${SlaveFullName(V.slaves[_ssj])}'s`; - const friendShipShort = relationshipTermShort(slave); - res += ` ${friendShipShort}`; - } - } else if (slave.relationship === -3 && slave.mother !== -1 && slave.father !== -1) { - res += `Your ${getPronouns(slave).wife}`; - } else if (slave.relationship === -2) { - res += `E Bonded`; - } else if (slave.relationship === -1) { - res += `E Slut`; - } return res; } - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_clone(slave, c) { - if (slave.clone !== 0) { - makeSpan(c, "Clone"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function short_rival(slave, c) { - if (slave.rivalry !== 0) { - const block = makeBlock(c, "lightsalmon"); - const _ssj = V.slaves.findIndex(s => s.ID === slave.rivalryTarget); - if (_ssj !== -1) { - if (slave.rivalry <= 1) { - block.textContent = `Disl ${SlaveFullName(V.slaves[_ssj])}`; - } else if (slave.rivalry <= 2) { - block.textContent = `${SlaveFullName(V.slaves[_ssj])}'s rival`; - } else { - block.textContent = `Hates ${SlaveFullName(V.slaves[_ssj])}`; - } - } - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_extended_family(slave, c) { - let handled = 0; - const block = makeBlock(); - if (slave.mother > 0) { - const _ssj = V.slaves.findIndex(s => s.ID === slave.mother); - if (_ssj !== -1) { - addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); - const tmpSpan = makeSpan(block, getPronouns(slave).daughter, "lightgreen"); - if (slave.relationshipTarget === V.slaves[_ssj].ID) { - const friendShipShort = relationshipTerm(slave); - tmpSpan.textContent += ` and ${friendShipShort}`; - handled = 1; - } - tmpSpan.textContent += '.'; - } - } else if (slave.mother === -1) { - addText(block, `Your `); - if (slave.relationship < -1) { - makeSpan(block, `${getPronouns(slave).daughter} and ${PCrelationshipTerm(slave)}.`, "lightgreen"); - handled = 1; - } else { - makeSpan(block, `${getPronouns(slave).daughter}.`, "lightgreen"); - } - } else if (slave.mother in V.missingTable && V.showMissingSlavesSD && V.showMissingSlaves) { - addText(block, `${V.missingTable[slave.mother].fullName}'s `); - makeSpan(block, `${getPronouns(slave).daughter}.`, "lightgreen"); - } - if (slave.father > 0 && slave.father !== slave.mother) { - const _ssj = V.slaves.findIndex(s => s.ID === slave.father); - if (_ssj !== -1) { - addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); - const tmpSpan = makeSpan(block, getPronouns(slave).daughter, "lightgreen"); - if (slave.relationshipTarget === V.slaves[_ssj].ID) { - const friendShipShort = relationshipTerm(slave); - tmpSpan.textContent += ` and ${friendShipShort}`; - handled = 1; - } - tmpSpan.textContent += '.'; - } - } else if (slave.father === -1 && slave.father !== slave.mother) { - addText(block, `Your `); - if (slave.relationship < -1) { - makeSpan(block, `${getPronouns(slave).daughter} and ${PCrelationshipTerm(slave)}.`, "lightgreen"); - handled = 1; - } else { - makeSpan(block, `${getPronouns(slave).daughter}.`, "lightgreen"); - } - } else if (slave.father in V.missingTable && slave.father !== slave.mother && V.showMissingSlavesSD && V.showMissingSlaves) { - addText(block, `${V.missingTable[slave.father].fullName}'s `); - makeSpan(block, `${getPronouns(slave).daughter}.`, "lightgreen"); - } - if (areSisters(V.PC, slave) > 0) { - addText(block, `Your `); - if (slave.relationship < -1) { - makeSpan(block, `${relativeTerm(V.PC, slave)} and ${PCrelationshipTerm(slave)}.`, "lightgreen"); - handled = 1; - } else { - makeSpan(block, `${relativeTerm(V.PC, slave)}.`, "lightgreen"); - } - } - if (slave.daughters === 1) { - let _ssj = V.slaves.findIndex(s => s.mother === slave.ID); - if (_ssj !== -1) { - addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); - const tmpSpan = makeSpan(block, "mother", "lightgreen"); - if (slave.relationshipTarget === V.slaves[_ssj].ID) { - const friendShipShort = relationshipTerm(slave); - tmpSpan.textContent += ` and ${friendShipShort}`; - handled = 1; - } - tmpSpan.textContent += '.'; - } - _ssj = V.slaves.findIndex(s => s.father === slave.ID); - if (_ssj !== -1) { - addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); - const tmpSpan = makeSpan(block, "father", "lightgreen"); - if (slave.relationshipTarget === V.slaves[_ssj].ID) { - const friendShipShort = relationshipTerm(slave); - tmpSpan.textContent += ` and ${friendShipShort}`; - handled = 1; - } - tmpSpan.textContent += '.'; - } - } else if (slave.daughters > 1) { - if (slave.daughters > 10) { - makeSpan(block, "Has tons of daughters.", "lightgreen"); - } else if (slave.daughters > 5) { - makeSpan(block, "Has many daughters.", "lightgreen"); - } else { - makeSpan(block, "Has several daughters.", "lightgreen"); - } - } - if (slave.sisters === 1) { - const _ssj = V.slaves.findIndex(s => areSisters(s, slave) > 0); - if (_ssj !== -1) { - addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); - const tmpSpan = makeSpan(block, getPronouns(slave).sister, "lightgreen"); - if (slave.relationshipTarget === V.slaves[_ssj].ID) { - const friendShipShort = relationshipTerm(slave); - tmpSpan.textContent += ` and ${friendShipShort}`; - handled = 1; - } - tmpSpan.textContent += '.'; - } - } else if (slave.sisters > 1) { - if (slave.sisters > 10) { - makeSpan(block, "One of many sisters.", "lightgreen"); - } else if (slave.sisters > 5) { - makeSpan(block, "Has many sisters.", "lightgreen"); - } else { - makeSpan(block, "Has several sisters.", "lightgreen"); - } - } - if (slave.relationship > 0 && handled !== 1) { - const _ssj = V.slaves.findIndex(s => s.ID === slave.relationshipTarget); - if (_ssj !== -1) { - const friendship = relationshipTerm(slave); - addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); - makeSpan(block, `${friendship}.`, "lightgreen"); - } - } else if (slave.relationship === -3 && slave.mother !== -1 && slave.father !== -1 && areSisters(V.PC, slave) === 0) { - makeSpan(block, `Your ${getPronouns(slave).wife}.`, "lightgreen"); - } else if (slave.relationship === -2) { - makeSpan(block, "Emotionally bonded to you.", "lightgreen"); - } else if (slave.relationship === -1) { - makeSpan(block, "Emotional slut.", "lightgreen"); - } - - if (block.textContent.length > 0) { - c.appendChild(block); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_clone(slave, c) { - if (slave.clone !== 0) { - makeSpan(c, `Clone of ${slave.clone}.`, "skyblue"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_rival(slave, c) { - if (slave.rivalry !== 0) { - const block = makeBlock(c); - const _ssj = V.slaves.findIndex(s => s.ID === slave.rivalryTarget); - if (_ssj !== -1) { - if (slave.rivalry <= 1) { - makeSpan(block, "Dislikes", "lightsalmon"); - block.appendChild(document.createTextNode(` ${SlaveFullName(V.slaves[_ssj])}.`)); - } else if (slave.rivalry <= 2) { - block.appendChild(document.createTextNode(`${SlaveFullName(V.slaves[_ssj])}'s `)); - makeSpan(block, "rival.", "lightsalmon"); - } else { - makeSpan(block, "Hates", "lightsalmon"); - block.appendChild(document.createTextNode(` ${SlaveFullName(V.slaves[_ssj])}.`)); - } - } - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_clothes(slave, c) { - function descStr() { - switch (slave.clothes) { - case "attractive lingerie": - return `Nice lingerie.`; - case "a succubus outfit": - return `Succubus outfit.`; - case "a string bikini": - return `String bikini.`; - case "a scalemail bikini": - return `Scalemail bikini.`; - case "striped panties": - return `Striped panties.`; - case "a monokini": - return `Monokini.`; - case "an apron": - return `Apron.`; - case "a cybersuit": - return `Cybersuit.`; - case "cutoffs and a t-shirt": - return `Cutoffs, t-shirt.`; - case "a slutty outfit": - return `Slutty outfit.`; - case "uncomfortable straps": - return `Leather straps.`; - case "a fallen nuns habit": - return `Slutty habit.`; - case "a chattel habit": - return `Chattel habit.`; - case "a penitent nuns habit": - return `Cilice.`; - case "slutty jewelry": - return `Bangles.`; - case "attractive lingerie for a pregnant woman": - return `Preggo lingerie.`; - case "a maternity dress": - return `Maternity dress.`; - case "stretch pants and a crop-top": - return `Stretch pants, crop-top.`; - case "harem gauze": - return `Harem outfit.`; - case "a slave gown": - return `Slave gown.`; - case "a halter top dress": - return `Halter top dress.`; - case "a mini dress": - return `Mini dress.`; - case "a ball gown": - return `Ball gown.`; - case "slutty business attire": - return `Slutty suit.`; - case "nice business attire": - return `Nice suit.`; - case "a comfortable bodysuit": - return `Bodysuit.`; - case "a military uniform": - return `Military uniform.`; - case "a schutzstaffel uniform": - return `Schutzstaffel uniform.`; - case "a slutty schutzstaffel uniform": - return `Slutty Schutzstaffel uniform.`; - case "a red army uniform": - return `Red Army uniform.`; - case "a long qipao": - return `Long Qipao.`; - case "battlearmor": - return `Battlearmor.`; - case "a mounty outfit": - return `Mounty outfit.`; - case "a dirndl": - return `Dirndl.`; - case "lederhosen": - return `Lederhosen.`; - case "a biyelgee costume": - return `Biyelgee costume.`; - case "a leotard": - return `Leotard.`; - case "a bunny outfit": - return `Bunny outfit.`; - case "a slutty maid outfit": - return `Slutty maid.`; - case "a nice maid outfit": - return `Nice maid.`; - case "a slutty nurse outfit": - return `Slutty nurse.`; - case "a nice nurse outfit": - return `Nice nurse.`; - case "a schoolgirl outfit": - return `Schoolgirl outfit.`; - case "a kimono": - return `Kimono.`; - case "a hijab and abaya": - return `Hijab and abaya.`; - case "battledress": - return `Battledress.`; - case "a latex catsuit": - return `Nice latex.`; - case "restrictive latex": - return `Bondage latex.`; - case "conservative clothing": - return `Conservative clothing.`; - case "chains": - return `Chains.`; - case "overalls": - return `Overalls.`; - case "a cheerleader outfit": - return `Cheerleader.`; - case "clubslut netting": - return `Netting.`; - case "shibari ropes": - return `Shibari.`; - case "Western clothing": - return `Chaps.`; - case "body oil": - return `Body oil.`; - case "a toga": - return `Toga.`; - case "a huipil": - return `Huipil.`; - case "a slutty qipao": - return `Slutty qipao.`; - case "spats and a tank top": - return `Spats, tank top.`; - case "a burkini": - return `Burkini.`; - case "a niqab and abaya": - return `Niqab and abaya.`; - case "a klan robe": - return `Klan robe.`; - case "a hijab and blouse": - return `Hijab and blouse.`; - case "a burqa": - return `Burqa.`; - case "kitty lingerie": - return `Kitty lingerie.`; - case "a tube top and thong": - return `Tube top, thong.`; - case "a button-up shirt and panties": - return `Button-up shirt, panties.`; - case "a gothic lolita dress": - return `Gothic lolita dress.`; - case "a hanbok": - return `Hanbok.`; - case "a bra": - return `Nice bra.`; - case "a button-up shirt": - return `Nice button-up shirt.`; - case "a nice pony outfit": - return `Nice pony outfit.`; - case "a sweater": - return `Nice sweater.`; - case "a tank-top": - return `Nice tank-top.`; - case "a thong": - return `Nice thong.`; - case "a tube top": - return `Nice tube top.`; - case "a one-piece swimsuit": - return `Swimsuit.`; - case "a police uniform": - return `Police uniform.`; - case "a striped bra": - return `Striped bra.`; - case "a skimpy loincloth": - return `Skimpy loincloth.`; - case "a slutty klan robe": - return `Slutty klan robe.`; - case "a slutty pony outfit": - return `Slutty pony outfit.`; - case "a Santa dress": - return `Santa dress.`; - case "a sports bra": - return `Sports bra.`; - case "a sweater and panties": - return `Sweater, panties.`; - case "a t-shirt": - return `T-shirt.`; - case "a tank-top and panties": - return `Tank-top, panties.`; - case "a t-shirt and thong": - return `Thong, t-shirt.`; - case "an oversized t-shirt and boyshorts": - return `Over-sized t-shirt, boy shorts.`; - case "an oversized t-shirt": - return `Nice over-sized t-shirt.`; - case "a t-shirt and jeans": - return `Blue jeans, t-shirt.`; - case "boyshorts": - return `Boy shorts.`; - case "cutoffs": - return `Jean shorts.`; - case "leather pants and pasties": - return `Leather pants, pasties.`; - case "leather pants": - return `Nice leather pants.`; - case "panties": - return `Nice panties.`; - case "sport shorts and a t-shirt": - return `Nice sport shorts, shirt.`; - case "a t-shirt and panties": - return `Panties, t-shirt.`; - case "panties and pasties": - return `Pasties, panties.`; - case "pasties": - return `Pasties.`; - case "striped underwear": - return `Striped underwear`; - case "sport shorts and a sports bra": - return `Shorts, bra.`; - case "jeans": - return `Tight blue jeans.`; - case "a sweater and cutoffs": - return `Jean shorts, sweater.`; - case "leather pants and a tube top": - return `Leather pants, tube top.`; - case "sport shorts": - return `Shorts.`; - case "a bimbo outfit": - return `Bimbo outfit.`; - case "a courtesan dress": - return `Courtesan dress.`; - default: - return `Naked.`; - } - } - makeSpan(c, descStr()); - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_collar(slave, c) { - function descStr() { - switch (slave.collar) { - case "uncomfortable leather": - return `Leather collar.`; - case "tight steel": - return `Steel collar.`; - case "preg biometrics": - return `Pregnancy biometrics collar.`; - case "cruel retirement counter": - return `Cruel counter collar.`; - case "shock punishment": - return `Shock collar.`; - case "dildo gag": - return `Dildo gag.`; - case "massive dildo gag": - return `Throat-bulging dildo gag.`; - case "neck corset": - return `Neck corset.`; - case "stylish leather": - return `Stylish leather collar.`; - case "satin choker": - return `Satin choker.`; - case "silk ribbon": - return `Silken ribbon.`; - case "heavy gold": - return `Gold collar.`; - case "bowtie": - return `Bowtie collar.`; - case "pretty jewelry": - return `Pretty collar.`; - case "nice retirement counter": - return `Nice counter collar.`; - case "bell collar": - return `Bell collar.`; - case "leather with cowbell": - return `Cowbell collar.`; - case "ancient Egyptian": - return `Wesekh.`; - case "ball gag": - return `Ball gag.`; - case "bit gag": - return `Bit gag.`; - case "porcelain mask": - return `Porcelain mask.`; - default: - return null; - } - } - const s = descStr(); - if (s) { - makeSpan(c, s); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_belly(slave, c) { - function descStr() { - switch (slave.bellyAccessory) { - case "shapewear": - return `Shapewear.`; - case "a small empathy belly": - return `Small fake belly.`; - case "a medium empathy belly": - return `Medium fake belly.`; - case "a large empathy belly": - return `Large fake belly.`; - case "a huge empathy belly": - return `Huge fake belly.`; - case "a corset": - return `Corset.`; - case "an extreme corset": - return `Extreme corsetage.`; - case "a support band": - return `Support band.`; - default: - return null; - } - } - const s = descStr(); - if (s) { - makeSpan(c, s); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_arms(slave, c) { - if (["hand gloves", "elbow gloves"].includes(slave.armAccessory)) { - makeSpan(c, slave.armAccessory, undefined, true); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_legs(slave, c) { - if (slave.legAccessory === "short stockings") { - makeSpan(c, "Short stockings."); - } else if (slave.legAccessory === "long stockings") { - makeSpan(c, "Long stockings."); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_shoes(slave, c) { - if (["boots", "extreme heels", "extreme platform heels", "flats", "heels", "platform heels", "platform shoes", "pumps"].includes(slave.shoes)) { - makeSpan(c, slave.shoes, undefined, true); - } else if (slave.heels === 1) { - makeSpan(c, "Crawling.", "yellow"); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_chastity(slave, c) { - if (slave.chastityAnus === 1 && slave.chastityPenis === 1 && slave.chastityVagina === 1) { - makeSpan(c, "Full chastity."); - } else if (slave.chastityPenis === 1 && slave.chastityVagina === 1) { - makeSpan(c, "Genital chastity."); - } else if ((slave.chastityAnus === 1 && slave.chastityVagina === 1) || (slave.chastityAnus === 1 && slave.chastityPenis === 1)) { - makeSpan(c, "Combined chastity."); - } else if (slave.chastityVagina === 1) { - makeSpan(c, "Vaginal chastity."); - } else if (slave.chastityPenis === 1) { - makeSpan(c, "Chastity cage."); - } else if (slave.chastityAnus === 1) { - makeSpan(c, "Anal chastity."); - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_vaginal_acc(slave, c) { - if (slave.vaginalAttachment !== "vibrator") { - switch (slave.vaginalAccessory) { - case "bullet vibrator": - makeSpan(c, "Attached bullet vibrator."); - break; - case "smart bullet vibrator": - makeSpan(c, "Attached smart bullet vibrator."); - break; - case "dildo": - makeSpan(c, "Vaginal dildo."); - break; - case "large dildo": - makeSpan(c, "Large vaginal dildo."); - break; - case "huge dildo": - makeSpan(c, "Huge vaginal dildo."); - break; - case "long dildo": - makeSpan(c, "Long vaginal dildo."); - break; - case "long, large dildo": - makeSpan(c, "Long and large vaginal dildo."); - break; - case "long, huge dildo": - makeSpan(c, "Long and wide vaginal dildo."); - break; - } - } - if (slave.vaginalAttachment !== "none") { - switch (slave.vaginalAttachment) { - case "vibrator": - makeSpan(c, "Vibrating dildo."); - break; - } - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_dick_acc(slave, c) { - switch (slave.dickAccessory) { - case "sock": - makeSpan(c, "Cock sock."); - break; - case "bullet vibrator": - makeSpan(c, "Frenulum bullet vibrator."); - break; - case "smart bullet vibrator": - makeSpan(c, "Smart frenulum bullet vibrator."); - break; - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function long_buttplug(slave, c) { - switch (slave.buttplug) { - case "plug": - makeSpan(c, "Buttplug."); - break; - case "large plug": - makeSpan(c, "Large buttplug."); - break; - case "huge plug": - makeSpan(c, "Huge buttplug."); - break; - case "long plug": - makeSpan(c, "Long buttplug."); - break; - case "long, large plug": - makeSpan(c, "Large, long buttplug."); - break; - case "long, huge plug": - makeSpan(c, "Enormous buttplug."); - break; - } - switch (slave.buttplugAttachment) { - case "tail": - makeSpan(c, "Attached tail."); - break; - case "cat tail": - makeSpan(c, "Attached cat tail."); - break; - case "fox tail": - makeSpan(c, "Attached fox tail."); - break; - case "cow tail": - makeSpan(c, "Attached cow tail."); - break; - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function rules_assistant(slave, c) { - if (slave.useRulesAssistant === 0) { - makeSpan(c, "RA-Exempt", "lightgreen"); - } else if (V.abbreviateRulesets === 2 && (slave.currentRules !== undefined) && (slave.currentRules.length > 0)) { - c.innerHTML = `Rules: ${V.defaultRules.filter(x => ruleApplied(slave, x)).map(x => x.name).join(", ")}`; - } - } - - /** - * @param {App.Entity.SlaveState} slave - * @param {Node} c - * @returns {void} - */ - function origins(slave, c) { - const para = makeParagraph(c); - para.classList.add("gray"); - const pronouns = getPronouns(slave); - para.textContent = `${slave.origin.replace(/\$([A-Z]?[a-z]+)/g, (match, cap1) => pronouns[cap1] || match)}`; - } - - /** - * @param {HTMLElement} element - * @param {string|string[]} [classNames] - */ - function _addClassNames(element, classNames) { - if (classNames != undefined) { /* eslint-disable-line eqeqeq */ - if (Array.isArray(classNames)) { - element.classList.add(...classNames); - } else { - element.classList.add(classNames); - } - } - } - - /** - * @param {Node} container - * @param {string} text - * @param {string|string[]} [classNames] - * @param {boolean} [stdDecor=false] - * @param {number} [value] - */ - function makeSpan(container, text, classNames, stdDecor = false, value) { - let r = document.createElement("span"); - r.classList.add("ssi"); - _addClassNames(r, classNames); - if (value != undefined && V.summaryStats) { /* eslint-disable-line eqeqeq */ - text += `[${value}]`; - } - r.textContent = stdDecor ? `${capFirstChar(text)}.` : text; - if (container) { - container.appendChild(r); - } - return r; - } - - /** - * @param {Node} container - * @param {string} text - * @returns {Text} - */ - function addText(container, text) { - const r = document.createTextNode(text); - if (container) { - container.appendChild(r); - } - return r; - } - - /** - * @param {Node} [container] - * @param {string|string[]} [classNames] - */ - function makeBlock(container, classNames) { - let r = document.createElement("span"); - r.classList.add("ssb"); - _addClassNames(r, classNames); - if (container) { - container.appendChild(r); - } - return r; - } - - /** - * @param {Node} container - * @param {string|string[]} [classNames] - * @returns {HTMLParagraphElement} - */ - function makeParagraph(container, classNames) { - let r = document.createElement("p"); - r.classList.add("si"); - _addClassNames(r, classNames); - if (container) { - container.appendChild(r); - } - return r; - } - - return SlaveSummary; -})(); + return { + makeNewState: makeNewState, + settingsChanged: settingsChanged, + societyChanged: societyChanged, + render: render, + displayOptionsFragment: displayOptionsFragment + }; +}(); diff --git a/src/uncategorized/fsDevelopments.tw b/src/uncategorized/fsDevelopments.tw index b32cd29bc31d84da14275459bc071d8fe0b89d40..32433250947b235aac603a21e374c108a6d6de8a 100644 --- a/src/uncategorized/fsDevelopments.tw +++ b/src/uncategorized/fsDevelopments.tw @@ -1297,3 +1297,5 @@ <</if>> <</if>> <</if>> + +<<run App.UI.SlaveSummary.societyChanged()>> diff --git a/src/uncategorized/policies.tw b/src/uncategorized/policies.tw index 677cdced99dee85e636853ca48062b3edd5292da..9646d6669cfc93f2c7629039cde9a31dcd5f101f 100644 --- a/src/uncategorized/policies.tw +++ b/src/uncategorized/policies.tw @@ -7,6 +7,7 @@ </style> <<set $nextButton = "Back">> +<<set _passageSwitchHandler = App.EventHandlers.societyChanged>> <<if $arcologies[0].FSSupremacistLawME && $PC.race != $arcologies[0].FSSupremacistRace>> <<set $nextLink = "Gameover", $gameover = "Idiot Ball 2 The Dumbassening">> <<elseif $arcologies[0].FSSubjugationistLawME && $PC.race == $arcologies[0].FSSubjugationistRace>> diff --git a/src/uncategorized/summaryOptions.tw b/src/uncategorized/summaryOptions.tw index 507d35f4e91a147484f70da5603a9405cc706033..c839f964e8536e79801fe1106d8c59dcae6a1875 100644 --- a/src/uncategorized/summaryOptions.tw +++ b/src/uncategorized/summaryOptions.tw @@ -70,95 +70,7 @@ Sample summary: <<option 2 "Card">> <</options>> -<<options $abbreviateDevotion "Summary Options">> - Mental stats are - <<option 2 "Summarized">> - <<option 1 "Abbreviated">> - <<option 0 "Hidden">> -<</options>> - -<<options $abbreviateMental "Summary Options">> - Mental attributes are - <<option 2 "Summarized">> - <<option 1 "Abbreviated">> - <<option 0 "Hidden">> -<</options>> - -<<options $abbreviateRules "Summary Options">> - Rules are - <<option 2 "Summarized">> - <<option 1 "Abbreviated">> - <<option 0 "Hidden">> -<</options>> - -<<options $abbreviateHealth "Summary Options">> - Health is - <<option 2 "Summarized">> - <<option 1 "Abbreviated">> - <<option 0 "Hidden">> -<</options>> - -<<options $abbreviateDiet "Summary Options">> - Diet and weight are - <<option 2 "Summarized">> - <<option 1 "Abbreviated">> - <<option 0 "Hidden">> -<</options>> - -<<options $abbreviateDrugs "Summary Options">> - Drugs and addiction are - <<option 2 "Summarized">> - <<option 1 "Abbreviated">> - <<option 0 "Hidden">> -<</options>> - -<<options $abbreviateHormoneBalance "Summary Options">> - Hormone balance is - <<option 2 "Summarized">> - <<option 1 "Abbreviated">> - <<option 0 "Hidden">> -<</options>> - -<<options $abbreviateGenitalia "Summary Options">> - Genitalia are - <<option 2 "Summarized">> - <<option 1 "Abbreviated">> - <<option 0 "Hidden">> -<</options>> - -<<options $abbreviatePhysicals "Summary Options">> - Physical traits are - <<option 2 "Summarized">> - <<option 1 "Abbreviated">> - <<option 0 "Hidden">> -<</options>> - -<<options $abbreviateSkills "Summary Options">> - Skills are - <<option 2 "Summarized">> - <<option 1 "Abbreviated">> - <<option 0 "Hidden">> -<</options>> - -<<options $abbreviateNationality "Summary Options">> - Nationality is - <<option 2 "Summarized">> - <<option 1 "Abbreviated">> - <<option 0 "Hidden">> -<</options>> - -<<options $abbreviateRace "Summary Options">> - Race is - <<option 2 "Summarized">> - <<option 1 "Abbreviated">> - <<option 0 "Hidden">> -<</options>> - -<<options $abbreviateRulesets "Summary Options">> - Rules Assistant rulesets are - <<option 2 "Summarized">> - <<option 1 "Abbreviated">> -<</options>> +<<= App.UI.DOM.includeDOM(App.UI.SlaveSummary.displayOptionsFragment(), "dof") >> <<options $summaryStats "Summary Options">> Granular slave stat numbers are @@ -172,12 +84,6 @@ Main menu assignment shortcuts are <<option 0 "Hidden">> <</options>> -<<options $abbreviateOrigins "Summary Options">> - Origins are - <<option 2 "Summarized">> - <<option 0 "Hidden">> -<</options>> - <<if $showMissingSlaves>> <<options $showMissingSlavesSD "Summary Options">> Missing slave parents are @@ -187,5 +93,5 @@ Main menu assignment shortcuts are <</if>> <p style="font-style:italic"> - [[FC Dev's preferred options|Summary Options ][$seeDesk = 0, $seeFCNN = 0, $sortSlavesBy = "devotion",$sortSlavesOrder = "descending",$sortSlavesMain = 0,$rulesAssistantMain = 1,$abbreviateDevotion = 1,$abbreviateRules = 1,$abbreviateClothes = 2,$abbreviateHealth = 1,$abbreviateDiet = 1,$abbreviateDrugs = 1,$abbreviateRace = 1,$abbreviateGenitalia = 1,$abbreviatePhysicals = 1,$abbreviateSkills = 1,$abbreviateMental = 1,$abbreviateSidebar = 1]] + [[FC Dev's preferred options|Summary Options ][$seeDesk = 0, $seeFCNN = 0, $sortSlavesBy = "devotion",$sortSlavesOrder = "descending",$sortSlavesMain = 0,$rulesAssistantMain = 1, $UI.slaveSummary.abbreviation = {devotion: 1, mental: 1, rules: 1, clothes: 2, health: 1, diet: 1, drugs: 1, hormoneBalance: 1, race: 1, genitalia: 1, physicals: 1, skills: 1, nationality: 1, rulesets: 1, clothes: 0, origins: 0} ,$abbreviateSidebar = 1]] </p> diff --git a/src/zz1-last/setupEventHandlers.js b/src/zz1-last/setupEventHandlers.js index 9a41b2959c9a850010c0079626bf5252ab8ae5ee..190756ccced5b1ba246a99d25876336893d5d9dc 100644 --- a/src/zz1-last/setupEventHandlers.js +++ b/src/zz1-last/setupEventHandlers.js @@ -5,3 +5,7 @@ Config.saves.onSave = App.EventHandlers.onSave; $(document).on(':storyready', function(ev) { App.EventHandlers.storyReady(); }); + +$(document).one(':passagestart', function() { + App.EventHandlers.optionsChanged(); +});