diff --git a/src/endWeek/saRules_old.js b/src/endWeek/saRules_old.js index 8d16716be1aaccd7f49dc5235a9989b1588ede8c..c38d89822eaa5e767340f6d58cb65d3dafead484 100644 --- a/src/endWeek/saRules_old.js +++ b/src/endWeek/saRules_old.js @@ -1006,31 +1006,19 @@ break; case "humiliation": r += `demand that other slaves let ${him} fuck them in public. `; - if (assignmentVisible(slave)) { - if (!slave.rivalry) { - SlaveSort.IDs(V.RapeableIDs); - for (let dI = 0; dI < V.RapeableIDs.length; dI++) { - let - j = V.slaveIndices[V.RapeableIDs[dI]], - rival = slaves[j]; - - if (!rival.rivalry) { - if (assignmentVisible(rival) || rival.assignment === slave.assignment) { - if (rival.devotion <= 20 && rival.trust < -20) { - r += `Craving a rush, ${he} repeatedly forces a reluctant <<= SlaveFullName($slaves[_j])>> to have sex with ${him} in public. $slaves[_j].slaveName resents this, and $slaves[$i].slaveName's ongoing sexual abuse <span class="lightsalmon">starts a rivalry</span> between them. `; - slave.rivalry = 1; - rival.rivalry = 1; - slave.rivalryTarget = rival.ID; - rival.rivalryTarget = slave.ID; - SimpleSexAct.Slave(rival, 4); - if (canPenetrate(rival)) { - fuckCount = jsRandom(1, 3); - rival.counter.penetrative += fuckCount; - V.penetrativeTotal += fuckCount; - } - } - } - } + if (!slave.rivalry) { + let rival = randomRapeRivalryTarget(slave, (s) => { return s.devotion <= 20 && s.trust < -20; }); + if (jsDef(rival)) { + r += `Craving a rush, ${he} repeatedly forces a reluctant ${SlaveFullName(rival)} to have sex with ${him} in public. ${rival.slaveName} resents this, and ${slave.slaveName}'s ongoing sexual abuse <span class="lightsalmon">starts a rivalry</span> between them. `; + slave.rivalry = 1; + rival.rivalry = 1; + slave.rivalryTarget = rival.ID; + rival.rivalryTarget = slave.ID; + SimpleSexAct.Slave(rival, 4); + if (canPenetrate(rival)) { + fuckCount = jsRandom(1, 3); + rival.counter.penetrative += fuckCount; + V.penetrativeTotal += fuckCount; } } } @@ -1070,61 +1058,38 @@ break; case "sadist": r += `force the most reluctant slaves to let ${him} fuck them. `; - if (assignmentVisible(slave)) { - if (!slave.rivalry) { - SlaveSort.IDs(V.RapeableIDs); - for (let dI = 0; dI < V.RapeableIDs.length; dI++) { - let - j = V.slaveIndices[V.RapeableIDs[dI]], - rival = slaves[j]; - - const { - // eslint-disable-next-line no-unused-vars - he2, him2, his2, hers2, himself2, boy2, He2, His2 - } = getPronouns(rival).appendSuffix('2'); - - if (!rival.rivalry) { - if (assignmentVisible(rival) || rival.assignment === slave.assignment) { - if (rival.devotion <= 50) { - if (rival.sexualFlaw !== "none") { - r += `${He} focuses on ${SlaveFullName(rival)}, who has a sexual flaw ${slave.slaveName} can exploit. ${He} sadistically`; - switch (rival.sexualFlaw) { - case "hates oral": - r += `rapes the poor slave's face${!canAchieveErection(slave) ? ` with ${his} fingers` : ``}. ${rival.slaveName} hates oral`; - break; - case "hates anal": - case "hates penetration": - if (canDoVaginal(rival)) { - r += `rapes the poor slave's pussy${!canAchieveErection(slave) ? ` with ${his} fingers` : ``}. ${rival.slaveName} hates penetration`; - } else if (canDoAnal(rival)) { - r += `rapes the poor slave's ass${!canAchieveErection(slave) ? ` with ${his} fingers` : ``}. ${rival.slaveName} hates anal`; - } - break; - case "shamefast": - r += `rapes the poor slave in public. ${rival.slaveName} is terribly shamefast`; - break; - case "idealistic": - r += `rapes the poor slave every time ${he} catches ${him2} being romantic. ${rival.slaveName} is still idealistic`; - break; - default: - r += `rapes the poor slave every chance ${he} gets,`; - break; - } - r += `and the sexual abuse <span class="lightsalmon">starts a rivalry</span> between them. `; - slave.rivalry = 1; - rival.rivalry = 1; - slave.rivalryTarget = rival.ID; - rival.rivalryTarget = slave.ID; - SimpleSexAct.Slave(rival, 4); - if (canPenetrate(rival)) { - fuckCount = jsRandom(1, 3); - rival.counter.penetrative += fuckCount; - V.penetrativeTotal += fuckCount; - } - } - } - } - } + if (!slave.rivalry) { + let rival = randomRapeRivalryTarget(slave, (s) => { return s.devotion <= 50 && s.sexualFlaw !== "none"; }); + if (jsDef(rival)) { + const { + // eslint-disable-next-line no-unused-vars + he2, him2, his2, hers2, himself2, boy2, He2, His2 + } = getPronouns(rival).appendSuffix('2'); + + r += `${He} focuses on ${SlaveFullName(rival)}, who has a sexual flaw ${slave.slaveName} can exploit. ${He} sadistically`; + if (rival.sexualFlaw === "hates oral") { + r += `rapes the poor slave's face${!canAchieveErection(slave) ? ` with ${his} fingers` : ``}. ${rival.slaveName} hates oral`; + } else if (rival.sexualFlaw === "hates penetration" && canDoVaginal(rival)) { + r += `rapes the poor slave's pussy${!canAchieveErection(slave) ? ` with ${his} fingers` : ``}. ${rival.slaveName} hates penetration`; + } else if ((rival.sexualFlaw === "hates anal" || rival.sexualFlaw === "hates penetration") && canDoAnal(rival)) { + r += `rapes the poor slave's ass${!canAchieveErection(slave) ? ` with ${his} fingers` : ``}. ${rival.slaveName} hates anal`; + } else if (rival.sexualFlaw === "shamefast") { + r += `rapes the poor slave in public. ${rival.slaveName} is terribly shamefast`; + } else if (rival.sexualFlaw === "idealistic") { + r += `rapes the poor slave every time ${he} catches ${him2} being romantic. ${rival.slaveName} is still idealistic`; + } else { + r += `rapes the poor slave every chance ${he} gets,`; + } + r += ` and the sexual abuse <span class="lightsalmon">starts a rivalry</span> between them. `; + slave.rivalry = 1; + rival.rivalry = 1; + slave.rivalryTarget = rival.ID; + rival.rivalryTarget = slave.ID; + SimpleSexAct.Slave(rival, 4); + if (canPenetrate(rival)) { + fuckCount = jsRandom(1, 3); + rival.counter.penetrative += fuckCount; + V.penetrativeTotal += fuckCount; } } } @@ -1162,27 +1127,15 @@ break; case "dom": r += `force other slaves to submit to ${him}. `; - if (assignmentVisible(slave)) { - if (!slave.rivalry) { - SlaveSort.IDs(V.RapeableIDs); - for (let dI = 0; dI < V.RapeableIDs.length; dI++) { - let - j = V.slaveIndices[V.RapeableIDs[dI]], - rival = slaves[j]; - - if (!rival.rivalry) { - if (assignmentVisible(rival) || rival.assignment === slave.assignment) { - if (rival.devotion <= 20 && rival.trust < -20) { - r += `${He} repeatedly rapes a reluctant <<= SlaveFullName($slaves[_j])>>; ${he} can't seem to keep ${his} hands off the poor slave, who can't avoid ${him}. Not surprisingly, $slaves[_j].slaveName resents this, and $slaves[$i].slaveName's ongoing sexual abuse <span class="lightsalmon">starts a rivalry</span> between them. `; - slave.rivalry = 1; - rival.rivalry = 1; - slave.rivalryTarget = rival.ID; - rival.rivalryTarget = slave.ID; - SimpleSexAct.Slave(rival, 4); - } - } - } - } + if (!slave.rivalry) { + let rival = randomRapeRivalryTarget(slave, (s) => { return s.devotion <= 20 && s.trust < -20; }); + if (jsDef(rival)) { + r += `${He} repeatedly rapes a reluctant ${SlaveFullName(rival)}; ${he} can't seem to keep ${his} hands off the poor slave, who can't avoid ${him}. Not surprisingly, ${rival.slaveName} resents this, and ${slave.slaveName}'s ongoing sexual abuse <span class="lightsalmon">starts a rivalry</span> between them. `; + slave.rivalry = 1; + rival.rivalry = 1; + slave.rivalryTarget = rival.ID; + rival.rivalryTarget = slave.ID; + SimpleSexAct.Slave(rival, 4); } } SimpleSexAct.Slave(slave, 7); diff --git a/src/js/utilJS.js b/src/js/utilJS.js index e449acae44b6208241736bc114dd9c922b8d7eef..44b6cb949fc224c38aa95340c8f24d1373d1da26 100644 --- a/src/js/utilJS.js +++ b/src/js/utilJS.js @@ -3237,6 +3237,31 @@ window.disobedience = function(slave) { return Math.round(devotionFactor * trustFactor); }; +/** + * Returns a valid rape target for a slave who is going to rape one of his peers into rivalry with him. + * @param {App.Entity.SlaveState} slave + * @param {function} predicate + * @returns {App.Entity.SlaveState | undefined} + */ +window.randomRapeRivalryTarget = function(slave, predicate) { + function canBeARapeRival(s) { + return (s.devotion <= 95 && s.energy <= 95 && !s.rivalry && !s.fuckdoll && s.fetish !== "mindbroken"); + } + + function canRape(rapist, rapee) { + const opportunity = (assignmentVisible(rapist) && assignmentVisible(rapee)) || rapist.assignment === rapee.assignment; + const desire = !(rapist.relationship >= 3 && rapist.relationshipTarget === rapee.id); + return opportunity && desire; + } + + if (typeof predicate !== 'function') { + predicate = (() => true); + } + + const arr = V.slaves.filter((s) => { return canBeARapeRival(s) && canRape(slave, s); }).shuffle(); + return arr.find(predicate); +} + /** * Topological sorting algorithm * https://gist.github.com/shinout/1232505 diff --git a/src/uncategorized/saRivalries.tw b/src/uncategorized/saRivalries.tw index ea30dfb7850771d8425fa6a04122aeade94ef631..4fcf79a5bf85a486a8e1ee04256997440f867d39 100644 --- a/src/uncategorized/saRivalries.tw +++ b/src/uncategorized/saRivalries.tw @@ -244,7 +244,7 @@ <</if>> <</if>> <<if $familyTesting>> - <<if areRelated($slaves[$i], $slaves[_j])> + <<if areRelated($slaves[$i], $slaves[_j])>> <<if _roll > 70 && $slaves[$i].rivalry < 3 && _lightenedRivalry != 1>> $slaves[$i].slaveName and <<= SlaveFullName($slaves[_j])>> @@.lightsalmon;pursue their family rivalry.@@ <<set $slaves[_j].rivalry += 1, $slaves[$i].rivalry += 1>> diff --git a/src/uncategorized/slaveAssignmentsReport.tw b/src/uncategorized/slaveAssignmentsReport.tw index f82ba3678cd1f11ef4c2ab2b4dfdc8a705496183..8b3acc232b590b34afd97f4b0e787919a65a2305 100644 --- a/src/uncategorized/slaveAssignmentsReport.tw +++ b/src/uncategorized/slaveAssignmentsReport.tw @@ -1,6 +1,6 @@ :: Slave Assignments Report [nobr] -<<set $nextLink = "Economics", $nextButton = "Continue", _SL = $slaves.length, $RapeableIDs = []>> +<<set $nextLink = "Economics", $nextButton = "Continue", _SL = $slaves.length>> <h1> $arcologies[0].name Weekly Slave Report - Week $week</h1> @@ -776,18 +776,6 @@ $sexDemandResult.topClass = Math.trunc((($NPCSexSupply.topClass + $slaveJobValue <<set $shelterGirlsIDs.push($slaves[$i].ID)>> <</if>> -<<if $slaves[$i].devotion <= 95>> - <<if $slaves[$i].energy <= 95>> - <<if !$slaves[$i].rivalry>> - <<if !$slaves[$i].fuckdoll>> - <<if $slaves[$i].fetish != "mindbroken">> - <<set $RapeableIDs.push($slaves[$i].ID)>> - <</if>> - <</if>> - <</if>> - <</if>> -<</if>> - <<if $slaves[$i].bellyPain != 0>> <<set $slaves[$i].bellyPain = 0>> <</if>> diff --git a/src/utility/saRulesWidgets.tw b/src/utility/saRulesWidgets.tw index 5ee00e65d1b4e0f40aff2e9e9478ac2c259c1fcb..9875b5bdd95078b45c87d543589992d0f77d843f 100644 --- a/src/utility/saRulesWidgets.tw +++ b/src/utility/saRulesWidgets.tw @@ -437,28 +437,16 @@ and <<set $slaves[$i].counter.oral += _fuckCount, $oralTotal += _fuckCount>> <<elseif ($slaves[$i].fetish == "humiliation")>> demand that other slaves let $him fuck them in public. - <<if assignmentVisible($slaves[$i])>> - <<if !$slaves[$i].rivalry>> - <<SlaveIDSort $RapeableIDs>> - <<for _dI = 0; _dI < $RapeableIDs.length; _dI++>> - <<set _j = $slaveIndices[$RapeableIDs[_dI]]>> - <<if !$slaves[_j].rivalry>> - <<if assignmentVisible($slaves[_j]) || $slaves[_j].assignment == $slaves[$i].assignment>> - <<if $slaves[_j].devotion <= 20>> - <<if $slaves[_j].trust < -20>> - Craving a rush, $he repeatedly forces a reluctant <<= SlaveFullName($slaves[_j])>> to have sex with $him in public. $slaves[_j].slaveName resents this, and $slaves[$i].slaveName's ongoing sexual abuse @@.lightsalmon;starts a rivalry@@ between them. - <<set $slaves[$i].rivalry = 1, $slaves[_j].rivalry = 1, $slaves[$i].rivalryTarget = $slaves[_j].ID, $slaves[_j].rivalryTarget = $slaves[$i].ID>> - <<run SimpleSexAct.Slave($slaves[_j], 4)>> - <<if canPenetrate($slaves[_j])>> - <<set _fuckCount = random(1,3)>> - <<set $slaves[_j].counter.penetrative += _fuckCount, $penetrativeTotal += _fuckCount>> - <</if>> - <<break>> - <</if>> - <</if>> - <</if>> - <</if>> - <</for>> + <<if !$slaves[$i].rivalry>> + <<set _rival = randomRapeRivalryTarget($slaves[$i], (s) => { return (s.devotion <= 20 && s.trust < -20); })>> + <<if def _rival>> + Craving a rush, $he repeatedly forces a reluctant <<= SlaveFullName(_rival)>> to have sex with $him in public. _rival.slaveName resents this, and $slaves[$i].slaveName's ongoing sexual abuse @@.lightsalmon;starts a rivalry@@ between them. + <<set $slaves[$i].rivalry = 1, _rival.rivalry = 1, $slaves[$i].rivalryTarget = _rival.ID, _rival.rivalryTarget = $slaves[$i].ID>> + <<run SimpleSexAct.Slave(_rival, 4)>> + <<if canPenetrate(_rival)>> + <<set _fuckCount = random(1,3)>> + <<set _rival.counter.penetrative += _fuckCount, $penetrativeTotal += _fuckCount>> + <</if>> <</if>> <</if>> <<run SimpleSexAct.Slave($slaves[$i], 4)>> @@ -490,43 +478,30 @@ and <<set $slaves[$i].counter.mammary += _fuckCount, $mammaryTotal += _fuckCount>> <<elseif ($slaves[$i].fetish == "sadist")>> force the most reluctant slaves to let $him fuck them. - <<if assignmentVisible($slaves[$i])>> - <<if !$slaves[$i].rivalry>> - <<SlaveIDSort $RapeableIDs>> - <<for _dI = 0; _dI < $RapeableIDs.length; _dI++>> - <<set _j = $slaveIndices[$RapeableIDs[_dI]]>> - <<setLocalPronouns $slaves[_j] 2>> - <<if !$slaves[_j].rivalry>> - <<if assignmentVisible($slaves[_j]) || $slaves[_j].assignment == $slaves[$i].assignment>> - <<if $slaves[_j].devotion <= 50>> - <<if $slaves[_j].sexualFlaw != "none">> - $He focuses on <<= SlaveFullName($slaves[_j])>>, who has a sexual flaw $slaves[$i].slaveName can exploit. $He sadistically - <<if $slaves[_j].sexualFlaw == "hates oral">> - rapes the poor slave's face<<if !canAchieveErection($slaves[$i])>> with <<if (hasAnyArms($slaves[$i]))>>$his fingers<<else>>a strap-on<</if>><</if>>. $slaves[_j].slaveName hates oral - <<elseif $slaves[_j].sexualFlaw == "hates penetration" && canDoVaginal($slaves[_j])>> - rapes the poor slave's pussy<<if !canAchieveErection($slaves[$i])>> with <<if (hasAnyArms($slaves[$i]))>>$his fingers<<else>>a strap-on<</if>><</if>>. $slaves[_j].slaveName hates penetration - <<elseif ($slaves[_j].sexualFlaw == "hates anal" || $slaves[_j].sexualFlaw == "hates penetration") && canDoAnal($slaves[_j])>> - rapes the poor slave's ass<<if !canAchieveErection($slaves[$i])>> with <<if (hasAnyArms($slaves[$i]))>>$his fingers<<else>>a strap-on<</if>><</if>>. $slaves[_j].slaveName hates anal - <<elseif $slaves[_j].sexualFlaw == "shamefast">> - rapes the poor slave in public. $slaves[_j].slaveName is terribly shamefast - <<elseif $slaves[_j].sexualFlaw == "idealistic">> - rapes the poor slave every time $he catches _him2 being romantic. $slaves[_j].slaveName is still idealistic - <<else>> - rapes the poor slave every chance $he gets, - <</if>> - and the sexual abuse @@.lightsalmon;starts a rivalry@@ between them. - <<set $slaves[$i].rivalry = 1, $slaves[_j].rivalry = 1, $slaves[$i].rivalryTarget = $slaves[_j].ID, $slaves[_j].rivalryTarget = $slaves[$i].ID>> - <<break>> - <<run SimpleSexAct.Slave($slaves[_j], 4)>> - <<if canPenetrate($slaves[_j])>> - <<set _fuckCount = random(1,3)>> - <<set $slaves[_j].counter.penetrative += _fuckCount, $penetrativeTotal += _fuckCount>> - <</if>> - <</if>> - <</if>> - <</if>> - <</if>> - <</for>> + <<if !$slaves[$i].rivalry>> + <<set _rival = randomRapeRivalryTarget($slaves[$i], (s) => { return (s.devotion <= 50 && s.sexualFlaw !== "none"); })>> + <<if def _rival>> + $He focuses on <<= SlaveFullName(_rival)>>, who has a sexual flaw $slaves[$i].slaveName can exploit. $He sadistically + <<if _rival.sexualFlaw == "hates oral">> + rapes the poor slave's face<<if !canAchieveErection($slaves[$i])>> with <<if (hasAnyArms($slaves[$i]))>>$his fingers<<else>>a strap-on<</if>><</if>>. _rival.slaveName hates oral + <<elseif _rival.sexualFlaw == "hates penetration" && canDoVaginal(_rival)>> + rapes the poor slave's pussy<<if !canAchieveErection($slaves[$i])>> with <<if (hasAnyArms($slaves[$i]))>>$his fingers<<else>>a strap-on<</if>><</if>>. _rival.slaveName hates penetration + <<elseif (_rival.sexualFlaw == "hates anal" || _rival.sexualFlaw == "hates penetration") && canDoAnal(_rival>> + rapes the poor slave's ass<<if !canAchieveErection($slaves[$i])>> with <<if (hasAnyArms($slaves[$i]))>>$his fingers<<else>>a strap-on<</if>><</if>>. _rival.slaveName hates anal + <<elseif _rival.sexualFlaw == "shamefast">> + rapes the poor slave in public. _rival.slaveName is terribly shamefast + <<elseif _rival.sexualFlaw == "idealistic">> + rapes the poor slave every time $he catches _him2 being romantic. _rival.slaveName is still idealistic + <<else>> + rapes the poor slave every chance $he gets, + <</if>> + and the sexual abuse @@.lightsalmon;starts a rivalry@@ between them. + <<set $slaves[$i].rivalry = 1, _rival.rivalry = 1, $slaves[$i].rivalryTarget = _rival.ID, _rival.rivalryTarget = $slaves[$i].ID>> + <<run SimpleSexAct.Slave(_rival, 4)>> + <<if canPenetrate(_rival)>> + <<set _fuckCount = random(1,3)>> + <<set _rival.counter.penetrative += _fuckCount, $penetrativeTotal += _fuckCount>> + <</if>> <</if>> <</if>> <<run SimpleSexAct.Slave($slaves[$i], 4)>> @@ -557,24 +532,12 @@ and <<run SimpleSexAct.Slave($slaves[$i], 12)>> <<elseif ($slaves[$i].fetish == "dom")>> force other slaves to submit to $him. - <<if assignmentVisible($slaves[$i])>> - <<if !$slaves[$i].rivalry>> - <<SlaveIDSort $RapeableIDs>> - <<for _dI = 0; _dI < $RapeableIDs.length; _dI++>> - <<set _j = $slaveIndices[$RapeableIDs[_dI]]>> - <<if !$slaves[_j].rivalry>> - <<if assignmentVisible($slaves[_j]) || $slaves[_j].assignment == $slaves[$i].assignment>> - <<if $slaves[_j].devotion <= 20>> - <<if $slaves[_j].trust < -20>> - $He repeatedly rapes a reluctant <<= SlaveFullName($slaves[_j])>>; $he can't seem to keep $his hand<<if (hasBothArms($slaves[$i]) || !hasAnyArms($slaves[$i]))>>s<</if>><<if (!hasAnyArms($slaves[$i]))>> (so to speak)<</if>> off the poor slave, who can't avoid $him. Not surprisingly, $slaves[_j].slaveName resents this, and $slaves[$i].slaveName's ongoing sexual abuse @@.lightsalmon;starts a rivalry@@ between them. - <<set $slaves[$i].rivalry = 1, $slaves[_j].rivalry = 1, $slaves[$i].rivalryTarget = $slaves[_j].ID, $slaves[_j].rivalryTarget = $slaves[$i].ID>> - <<break>> - <<run SimpleSexAct.Slave($slaves[_j], 4)>> - <</if>> - <</if>> - <</if>> - <</if>> - <</for>> + <<if !$slaves[$i].rivalry>> + <<set _rival = randomRapeRivalryTarget($slaves[$i], (s) => { return (s.devotion <= 20 && s.trust < -20); })>> + <<if def _rival>> + $He repeatedly rapes a reluctant <<= SlaveFullName(_rival)>>; $he can't seem to keep $his hand<<if (hasBothArms($slaves[$i]) || !hasAnyArms($slaves[$i]))>>s<</if>><<if (!hasAnyArms($slaves[$i]))>> (so to speak)<</if>> off the poor slave, who can't avoid $him. Not surprisingly, _rival.slaveName resents this, and $slaves[$i].slaveName's ongoing sexual abuse @@.lightsalmon;starts a rivalry@@ between them. + <<set $slaves[$i].rivalry = 1, _rival.rivalry = 1, $slaves[$i].rivalryTarget = _rival.ID, _rival.rivalryTarget = $slaves[$i].ID>> + <<run SimpleSexAct.Slave(_rival, 4)>> <</if>> <</if>> <<run SimpleSexAct.Slave($slaves[$i], 7)>>