diff --git a/src/endWeek/saPorn.js b/src/endWeek/saPorn.js index 93ab5aa36c52c40b03030d04339859f23b79298d..d988e7048009e725cb659d8fc453f0dd5f492e95 100644 --- a/src/endWeek/saPorn.js +++ b/src/endWeek/saPorn.js @@ -1,116 +1,393 @@ -/* to later be rolled into saPorn */ +window.saPorn = (function saPorn() { + "use strict"; -/** - * @param {App.Entity.SlaveState} slave - * @returns {object} - */ -window.getHighestPorn = function(slave) { - let max = {value: 0, type: "none"}; + let r; + let he, him, his, hers, himself, girl, loli, He, His; + let decayRate; + let viewership; - if (slave.porn.fame.general > max.value) { - max = {value: slave.porn.fame.general, type: "generic"}; - } - if (slave.porn.fame.fuckdoll > max.value) { - max = {value: slave.porn.fame.fuckdoll, type: "fuckdoll"}; - } - if (slave.porn.fame.rape > max.value) { - max = {value: slave.porn.fame.rape, type: "rape"}; - } - if (slave.porn.fame.preggo > max.value) { - max = {value: slave.porn.fame.preggo, type: "preggo"}; - } - if (slave.porn.fame.BBW > max.value) { - max = {value: slave.porn.fame.BBW, type: "BBW"}; - } - if (slave.porn.fame.gainer > max.value) { - max = {value: slave.porn.fame.gainer, type: "weight gain"}; - } - if (slave.porn.fame.stud > max.value) { - max = {value: slave.porn.fame.stud, type: "big dick"}; - } - if (slave.porn.fame.loli > max.value) { - max = {value: slave.porn.fame.loli, type: "underage"}; - } - if (slave.porn.fame.deepThroat > max.value) { - max = {value: slave.porn.fame.deepThroat, type: "deepthroat"}; - } - if (slave.porn.fame.struggleFuck > max.value) { - max = {value: slave.porn.fame.struggleFuck, type: "unwilling"}; - } - if (slave.porn.fame.painal > max.value) { - max = {value: slave.porn.fame.painal, type: "hardcore anal"}; - } - if (slave.porn.fame.tease > max.value) { - max = {value: slave.porn.fame.tease, type: "softcore"}; - } - if (slave.porn.fame.romantic > max.value) { - max = {value: slave.porn.fame.romantic, type: "romantic"}; - } - if (slave.porn.fame.pervert > max.value) { - max = {value: slave.porn.fame.pervert, type: "really perverted"}; - } - if (slave.porn.fame.caring > max.value) { - max = {value: slave.porn.fame.caring, type: "voyeur"}; - } - if (slave.porn.fame.unflinching > max.value) { - max = {value: slave.porn.fame.unflinching, type: "unspeakable"}; - } - if (slave.porn.fame.sizeQueen > max.value) { - max = {value: slave.porn.fame.sizeQueen, type: "huge insertion"}; - } - if (slave.porn.fame.neglectful > max.value) { - max = {value: slave.porn.fame.neglectful, type: "orgasm denial"}; - } - if (slave.porn.fame.cumAddict > max.value) { - max = {value: slave.porn.fame.cumAddict, type: "cum addiction"}; - } - if (slave.porn.fame.analAddict > max.value) { - max = {value: slave.porn.fame.analAddict, type: "anal addiction"}; - } - if (slave.porn.fame.attentionWhore > max.value) { - max = {value: slave.porn.fame.attentionWhore, type: "exhibition"}; - } - if (slave.porn.fame.breastGrowth > max.value) { - max = {value: slave.porn.fame.breastGrowth, type: "breast expansion"}; - } - if (slave.porn.fame.abusive > max.value) { - max = {value: slave.porn.fame.abusive, type: "abuse"}; - } - if (slave.porn.fame.malicious > max.value) { - max = {value: slave.porn.fame.malicious, type: "sexual torture"}; + return saPorn; + + function saPorn(slave) { + ({ + he, him, his, hers, himself, girl, He, His, loli + } = getPronouns(slave)); + + let oldFame = slave.porn.viewerCount; + + if (V.studio === 1 && slave.porn.feed === 1) { + calcBaseViewership(slave); + + r += `The studio regularly releases clips of ${his} daily affairs. `; + if (V.cheatMode === 1) { + r += `(Decay: ${decayRate} Viewership: ${viewership} Last week's fame: ${oldFame}) `; + } + + prestigeCommentary(slave); + faceCommentary(slave); + hack(); + + genreViews(slave); + updateViewerCount(slave); + if (oldFame > slave.porn.viewerCount) { + r += `Overall, ${his} online fame <span class="red">dropped</span> this week. `; + } else if (oldFame < slave.porn.viewerCount) { + r += `Overall, ${his} online fame <span class="green">rose</span> this week. `; + if (oldFame < 100 && slave.porn.viewerCount >= 100 && V.studioFeed === 1) { + r += `${He} <span class="yellow">has accrued enough views to determine prospective porn genres.</span> `; + } + } else if (slave.porn.viewerCount !== 0) { + r += `Surprisingly, ${his} online fame <span class="yellow">remained consistent</span> this week despite how fickle watchers can be. `; + } else { + r += `${He} went <span class="red">completely overlooked</span> this week and failed to gain any hits at all. `; + } + + if (slave.porn.viewerCount > 0) { + let donations = Math.floor(slave.porn.viewerCount / jsRandom(10, 15 + viewerSoaking)); + if (donations > 0) { + r += `Fans donated a total of <span class="cash inc">${cashFormat(donations)}</span> to ${his} account this week. `; + cashX(donations, "porn", slave); + } + } + if (slave.porn.spending > 0) { + cashX(forceNeg(slave.porn.spending / V.PCSlutContacts), "porn", slave); + } + + prestigeGen(slave); + } else { /* popularity decay from lack of new content */ + if (slave.porn.prestige > 1) { // 500k + decayRate = 5000; + } else if (slave.porn.prestige > 0) { // 10k + decayRate = 500; + } else { + decayRate = 30; + } + + genreDecay(slave); + updateViewerCount(slave); + + prestigeDecay(slave); + } + + return r; } - if (slave.porn.fame.selfHating > max.value) { - max = {value: slave.porn.fame.selfHating, type: "self hating"}; + + function genreDecay(slave) { + for (let genre of App.Porn.getAllGenres()) { + if (slave.porn.fame[genre.fameName] > 0) { + const oldPorn = slave.porn.fame[genre.fameName]; + slave.porn.fame[genre.fameName] = Math.clamp(slave.porn.fame[genre.fameName] - (decayRate * 2), 0, 100000); + r += cheatDelta(genre.uiName(), oldPorn, slave.porn.fame[genre.fameName]); + } + } } - if (slave.porn.fame.breeder > max.value) { - max = {value: slave.porn.fame.breeder, type: "breeder"}; + + function updateViewerCount(slave) { + slave.porn.viewerCount = Math.trunc(App.Porn.getAllGenres().reduce((acc, cur) => acc + slave.porn.fame[cur.fameVar])); } - if (slave.porn.fame.sub > max.value) { - max = {value: slave.porn.fame.sub, type: "submissive"}; + + function prestigeDecay(slave) { + if (slave.porn.prestige > 0) { + const genre = App.Porn.getGenreByFameName(slave.porn.fameType); + if (slave.porn.fame[genre.fameName] < 40000 && slave.porn.prestige === 2) { + slave.porn.prestige = 1; + slave.porn.prestigeDesc = `$He has a following in slave pornography. ${genre.prestigeDesc1}.`; + r +=`With the lack of any new content, <span class="red">${his} popularity in ${slave.porn.fameType} pornography has dropped considerably,</span> though some viewers still cling to the hope that ${he}'ll come back. `; + } else if (slave.porn.fame[genre.fameName] < 5000) { + slave.porn.prestige = 0; + slave.porn.prestigeDesc = 0; + slave.porn.fameType = "none"; + r += `With no new ${slave.porn.fameType} content coming out, <span class="red">${his} popularity has faded away.</span> `; + } + } } - if (slave.porn.fame.cumSlut > max.value) { - max = {value: slave.porn.fame.cumSlut, type: "cum"}; + + function calcBaseViewership(slave) { + let face; + + if (slave.porn.prestige > 1) { + decayRate = 5000; + if (slave.fuckdoll > 0) { + face = 50; + } else if (slave.collar === "porcelain mask") { + face = 20; + } else { + face = slave.face * 4; + } + viewership = ((500/V.HackingSkillMultiplier)+(slave.porn.spending)+(face)+(slave.prestige*10)-(decayRate)); + } else if (slave.porn.prestige > 0) { + decayRate = 500; + if (slave.fuckdoll > 0) { + face = 20; + } else if (slave.collar === "porcelain mask") { + face = 50; + } else { + face = slave.face * 2; + } + viewership = ((900/V.HackingSkillMultiplier)+(slave.porn.spending/15)+(face)+(slave.prestige*250)-(decayRate)); + } else { + decayRate = 30; + if (slave.fuckdoll > 0) { + face = 0; + } else if (slave.collar === "porcelain mask") { + face = 0; + } else { + face = slave.face / 20; + } + viewership = ((300/V.HackingSkillMultiplier)+(slave.porn.spending > 0 ? 1.01*slave.porn.spending : 200)+(face)+(slave.prestige*20)-(decayRate)); + } + viewership = Math.trunc(viewership); } - if (slave.porn.fame.anal > max.value) { - max = {value: slave.porn.fame.anal, type: "buttslut"}; + + function prestigeCommentary(slave) { + if (slave.porn.prestige > 1) { + r += `${He} is widely regarded in ${slave.porn.fameType} porn, but with so many watchers, turn over is high. `; + } else if (slave.porn.prestige > 0) { + if (slave.porn.fameType === "generic") { + r += `${He} has claimed a niche in slave porn, so there is a constant cycle of new arrivals and bored ex-watchers. `; + } else { + r += `${He} has claimed a niche for ${himself} in ${slave.porn.fameType} porn, so there is a constant cycle of new arrivals and bored ex-watchers. `; + } + } else { + r += `${He} is borderline unknown, so $he tends to hold onto the few watchers ${he} has. `; + } + + if (slave.prestige > 1) { + r += `Interest in porn of ${him} is very high, since ${he}'s already quite prestigious. `; + } else if (slave.prestige > 0) { + r += `Interest in porn of ${him} is high, since ${he}'s already prestigious. `; + } } - if (slave.porn.fame.humiliation > max.value) { - max = {value: slave.porn.fame.humiliation, type: "humiliating"}; + + function faceCommentary(slave) { + if (slave.fuckdoll > 0) { + return; + } else if (slave.collar === "porcelain mask") { + r += `${His} mask adds an air of mystery to $him, `; + if (slave.porn.prestige > 1) { + r += `but people wonder if $he is trying to hide something. `; + } else if (slave.porn.prestige > 0) { + r += `tantalizing viewers with what it hides. `; + } else { + r += `but viewers are more interested in ${his} body. `; + } + } else if (slave.face > 95) { + r += `${His} unbelievably beautiful face seizes the attention of all who see it. `; + } else if (slave.face > 40) { + r += `${His} gorgeous face draws viewers in and keeps them watching. `; + } else if (slave.face > 10) { + r += `${His} pretty face draws viewers in. `; + } else if (slave.face > 0) { + r += `${His} face is attractive, but it attracts few viewers. `; + } else if (slave.face === 0) { + r += `${His} face is completely average and makes no difference to ${his} viewers. `; + } else if (slave.face >= -10) { + r += `${His} face, while attractive, is so average it turns off some viewers. `; + } else if (slave.face >= -40) { + r += `${His} unattractive face causes viewers to move on. `; + } else if (slave.face >= -95) { + r += `${His} ugly face drives viewers off. `; + } else { + r += `${His} face chases off all but the most desperate viewers. `; + } } - if (slave.porn.fame.boobs > max.value) { - max = {value: slave.porn.fame.boobs, type: "breast"}; + + function hack() { + if (V.PC.skill.hacking > 10) { + r += `With your hacking skills, you manage to tweak search algorithms to display ${his} content more often. `; + } else if (V.PC.skill.hacking < 0) { + r += `With your lack of skill with computers you manage to misidentify ${his} content, complicating searches. `; + IncreasePCSkills('hacking', 0.1); + } + IncreasePCSkills('hacking', 0.1); } - if (slave.porn.fame.dom > max.value) { - max = {value: slave.porn.fame.dom, type: "dominant"}; + + function viewershipDelta(newPorn, oldPorn) { + if (newPorn > oldPorn) { + return `Viewership <span class="green">increased</span> this week. `; + } else if (newPorn < oldPorn) { + return `Viewership <span class="red">decreased</span> this week. `; + } else { + return `Viewership <span class="yellow">was stable</span> this week. `; + } } - if (slave.porn.fame.sadist > max.value) { - max = {value: slave.porn.fame.sadist, type: "sadistic"}; + + function cheatDelta(name, oldPorn, newPorn) { + if (V.cheatMode === 1) { + return `(${name}: ${oldPorn} to ${newPorn}). `; + } + return ``; } - if (slave.porn.fame.masochist > max.value) { - max = {value: slave.porn.fame.masochist, type: "masochistic"}; + + function genreViews(slave) { + let viewerSoaking = 1; + let adjustedViewership = viewership; + + /* Paraphilias have the highest take of viewers */ + for (let genre of App.Porn.getGenresByType('paraphilia')) { + const oldPorn = slave.porn.fame[genre.fameVar]; + if (genre.valid(slave)) { + if (slave.porn.focus === genre.focusName || slave.porn.fameType === genre.fameName) { + adjustedViewership = viewership * 1.5; + } else if (slave.porn.focus !== "none") { + adjustedViewership = viewership * 0.5; + } + slave.porn.fame[genre.fameVar] += adjustedViewership + slave.fetishStrength*2 - ((decayRate/10)*(V.pornStars[genre.fameVar].p1count-1)); + slave.porn.fame[genre.fameVar] = Math.clamp(slave.porn.fame[genre.fameVar], 0, 150000); + viewerSoaking++; + + if (slave.porn.focus === genre.focusName || slave.porn.fameType === genre.fameName) { + r += `${hitText} `; + r += viewershipDelta(slave.porn.fame[genre.fameVar], oldPorn); + } + r += cheatDelta(genre.uiName(), oldPorn, slave.porn.fame[genre.fameVar]); + } else if (slave.porn.fame[genre.fameVar] > 0) { + slave.porn.fame[genre.fameVar] = Math.clamp(slave.porn.fame[genre.fameVar] - decayRate*2, 0, 150000); + r += cheatDelta(genre.uiName(), oldPorn, slave.porn.fame[genre.fameVar]); + } + } + + /* Fetishes */ + for (let genre of App.Porn.getGenresByType('fetish')) { + const oldPorn = slave.porn.fame[genre.fameVar]; + if (genre.valid(slave)) { + if (slave.porn.focus === genre.focusName || slave.porn.fameType === genre.fameName) { + adjustedViewership = viewership * 2.0; + } else if (slave.porn.focus !== "none") { + adjustedViewership = viewership * 0.5; + } + slave.porn.fame[genre.fameVar] += adjustedViewership/viewerSoaking + slave.fetishStrength - ((decayRate/10)*(V.pornStars[genre.fameVar].p1count-1)); + slave.porn.fame[genre.fameVar] = Math.clamp(slave.porn.fame[genre.fameVar], 0, 150000); + viewerSoaking++; + + if (slave.porn.focus === genre.focusName || slave.porn.fameType === genre.fameName) { + r += `${hitText} `; + r += viewershipDelta(slave.porn.fame[genre.fameVar], oldPorn); + } + r += cheatDelta(genre.uiName(), oldPorn, slave.porn.fame[genre.fameVar]); + } else if (slave.porn.fame[genre.fameVar] > 0) { + slave.porn.fame[genre.fameVar] = Math.clamp(slave.porn.fame[genre.fameVar] - decayRate*2, 0, 150000); + r += cheatDelta(genre.uiName(), oldPorn, slave.porn.fame[genre.fameVar]); + } + } + + /* General */ + for (let genre of App.Porn.getGenresByType('general')) { + const oldPorn = slave.porn.fame[genre.fameVar]; + if (genre.valid(slave)) { + if (slave.porn.focus === genre.focusName || slave.porn.fameType === genre.fameName) { + adjustedViewership = viewership * 4.0; + } else if (slave.porn.focus !== "none") { + adjustedViewership = viewership * 0.5; + } + slave.porn.fame[genre.fameVar] += adjustedViewership/viewerSoaking - ((decayRate/10)*(V.pornStars[genre.fameVar].p1count-1)); + slave.porn.fame[genre.fameVar] = Math.clamp(slave.porn.fame[genre.fameVar], 0, 150000); + viewerSoaking++; + + if (slave.porn.focus === genre.focusName || slave.porn.fameType === genre.fameName) { + r += `${hitText} `; + r += viewershipDelta(slave.porn.fame[genre.fameVar], oldPorn); + } + r += cheatDelta(genre.uiName(), oldPorn, slave.porn.fame[genre.fameVar]); + } else if (slave.porn.fame[genre.fameVar] > 0) { + slave.porn.fame[genre.fameVar] = Math.clamp(slave.porn.fame[genre.fameVar] - decayRate*2, 0, 150000); + r += cheatDelta(genre.uiName(), oldPorn, slave.porn.fame[genre.fameVar]); + } + } + + /* Quirks are low and unlikely, requiring focus to push into the limelight */ + for (let genre of App.Porn.getGenresByType('quirk')) { + const oldPorn = slave.porn.fame[genre.fameVar]; + if (genre.valid(slave)) { + if (slave.porn.focus === genre.focusName || slave.porn.fameType === genre.fameName) { + adjustedViewership = viewership * 6.0; + } else if (slave.porn.focus !== "none") { + adjustedViewership = viewership * 0.5; + } + slave.porn.fame[genre.fameVar] += adjustedViewership/viewerSoaking - ((decayRate/10)*(V.pornStars[genre.fameVar].p1count-1)); + slave.porn.fame[genre.fameVar] = Math.clamp(slave.porn.fame[genre.fameVar], 0, 150000); + + if (slave.porn.focus === genre.focusName || slave.porn.fameType === genre.fameName) { + r += `${hitText} `; + r += viewershipDelta(slave.porn.fame[genre.fameVar], oldPorn); + } + r += cheatDelta(genre.uiName(), oldPorn, slave.porn.fame[genre.fameVar]); + } else if (slave.porn.fame[genre.fameVar] > 0) { + slave.porn.fame[genre.fameVar] = Math.clamp(slave.porn.fame[genre.fameVar] - decayRate*2, 0, 150000); + r += cheatDelta(genre.uiName(), oldPorn, slave.porn.fame[genre.fameVar]); + } + } } - if (slave.porn.fame.pregnancy > max.value) { - max = {value: slave.porn.fame.pregnancy, type: "pregnancy fetish"}; + + function prestigeGen(slave) { + const highestPorn = getHighestPorn(slave); + if (slave.porn.prestige === 0 && slave.porn.viewerCount >= 100000) { + const pornFameGrabBag = App.Porn.getAllGenres().filter((g) => slave.porn.fame[g.fameVar] >= 10000); + if (pornFameGrabBag.length > 0) { + const genre = pornFameGrabBag.pluck(); + slave.porn.fameType = genre.fameName; + slave.porn.prestige = 1; + + r += `<span style="green">${He} has gained a following in ${slave.porn.fameType} pornography!</span> ${genre.prestigeDesc1}, but he isn't famous enough to be called presigious yet. `; + slave.porn.prestigeDesc = `$He has a following in slave pornography. ${genre.prestigeDesc1}.`; + if (genre.type === "fetish" && slave.fetishKnown !== 1) { + slave.fetishKnown = 1; + } + } + } else if (slave.porn.prestige === 1) { + const swapPoint = 1.2; + const genre = App.Porn.getGenreByFameName(slave.porn.fameType); + if (slave.porn.fame[genre.fameVar] >= 50000) { + slave.porn.prestige = 2; + slave.porn.prestigeDesc = `$He is well known from $his career in slave pornography. ${genre.prestigeDesc2}.`; + r += `<span class="green">${He} has gained a hold in ${slave.porn.fameType} pornography!</span> ${genre.prestigeDesc2}, so it is now prestigious to own ${him}. `; + } else if (highestPorn.value >= slave.porn.fame[genre.fameVar] * swapPoint) { + r += `${His} fame in ${slave.porn.fameType} pornography has been overwhelmed by $his surging popularity in other aspects. <span class="yellow">${He} is now better known for ${his} ${highestPorn.type} porn.</span> `; + const newGenre = App.Porn.getGenreByFameName(highestPorn.type); + slave.porn.fameType = newGenre.fameName; + slave.porn.prestigeDesc = `$He has a following in slave pornography. ${newGenre.prestigeDesc1}.`; + if (newGenre.type === "fetish" && slave.fetishKnown !== 1) { + slave.fetishKnown = 1; + } + } else if (slave.porn.fame[genre.fameVar] < 5000) { + slave.porn.prestige = 0; + slave.porn.prestigeDesc = 0; + r += `<span class="red">${His} popularity in ${slave.porn.fameType} pornography has faded.</span> ${He} is once again relatively unknown. `; + slave.porn.fameType = "none"; + } + } else if (slave.porn.prestige === 2) { + const genre = App.Porn.getGenreByFameName(slave.porn.fameType); + if (slave.porn.fame[genre.fameVar] >= 150000 && V.pornStars[genre.fameVar].p3ID === 0) { + slave.porn.prestige = 3; + slave.porn.fame[genre.fameVar] = 250000; + slave.porn.viewerCount = 250000; + V.pornStars[genre.fameVar].p3ID = slave.ID; + slave.porn.prestigeDesc = `$He is world famous for $his career in slave pornography. ${genre.prestigeDesc3}.`; + r += `<span class="green">${He} has become world famous for ${his} career in ${slave.porn.fameType} pornography!</span> ${genre.prestigeDesc3}, so it is now extremely presitigious to own ${him}. `; + V.trinkets.push(`a framed shot from porn starring ${slave.slaveName} ${genre.trinketShotDesc}`); + + r += `Further paid publicity cannot increase ${his} fame, so subsidy of porn featuring ${him} has stopped. `; + slave.porn.spending = 0; + } else if (slave.porn.fame[genre.fameVar] < 40000) { + slave.porn.prestige = 1; + slave.porn.prestigeDesc = `$He has a following in slave pornography. ${genre.prestigeDesc1}.`; + r += `<span class="red">${His} popularity in ${slave.porn.fameType} pornography has dropped considerably,</span> though ${he} still retains a core fanbase. `; + } + } + } +})(); + +/** + * @param {App.Entity.SlaveState} slave + * @returns {object} + */ +window.getHighestPorn = function(slave) { + let max = {value: 0, type: "none"}; + + for (const genre of App.Porn.getAllGenres()) { + if (slave.porn.fame[genre.fameVar] > max.value) { + max = {value: slave.porn.fame[genre.fameVar], type: genre.fameName}; + } } return max; diff --git a/src/js/porn.js b/src/js/porn.js new file mode 100644 index 0000000000000000000000000000000000000000..a08723cd1f2d590a0a720ac32ba1a3cc09dd2df0 --- /dev/null +++ b/src/js/porn.js @@ -0,0 +1,36 @@ +App.Porn = {}; +App.Porn.Genre = {}; + +App.Porn.Genre.cumAddict = { + fameVar: "cumAddict", + fameName: "cum addiction", + focusName: "cum addict", + hitText: "$His complete obsession with cum makes $him a hit with viewers that enjoy bukkake and cum drinking.", + type: "paraphilia", /* paraphilia, fetish, general, quirk */ + prestigeDesc1: "Thousands have enjoyed watching $him do anything and everything for cum", + prestigeDesc2: "$His many fans relish the sight of $him doing anything for cum", + prestigeDesc3: "Millions are intimately familiar with the sight of $him doing anything for cum", + trinketShotDesc: "showing $him bathing in a tub of cum", + valid: function(slave) { return slave.sexualFlaw === "cum addict"; }, + uiName: function() { return capFirstChar(this.focusName); } + + /* TODO: need pornstarvar too (probably reorg pornstar stuff to $pornStar[fameVar].p2count/p3ID */ + /* TODO: hit up updateSlaveObject with the porn-prestige description reset stuff */ + /* TODO: hit up slaveInteract too */ +}; + +App.Porn.getGenreByFameName = function(fameName) { + return App.Porn.Genre.values().find((g) => g.fameName === fameName); +}; + +App.Porn.getGenreByFocusName = function(focusName) { + return App.Porn.Genre.values().find((g) => g.focusName === focusName); +}; + +App.Porn.getAllGenres = function() { + return App.Porn.Genre.values(); +}; + +App.Porn.getGenresByType = function(type) { + return App.Porn.Genre.values().filter((g) => g.type === type); +};