diff --git a/js/003-data/gameVariableData.js b/js/003-data/gameVariableData.js index 5f3b16b062ca900630adea8bc754990bbf58a939..eb454a556895f595aa5c88e658319f8043548e24 100644 --- a/js/003-data/gameVariableData.js +++ b/js/003-data/gameVariableData.js @@ -128,10 +128,6 @@ App.Data.defaultGameStateVariables = { profiler: 0, realRoyalties: 0, retainCareer: 1, - RIERemaining: 0, - RIEPerWeek: 1, - /** @type {number[]} */ - RIESkip: [], rulesAssistantAuto: 0, rulesAssistantMain: 1, seeAge: 1, @@ -179,6 +175,38 @@ App.Data.defaultGameStateVariables = { seeAnimation: false, animFPS: 12, + // Tracking random events + eventControl: { + /** @type {number} + * Random individual events to play each week + */ + RIEPerWeek: 1, + /** @type {number[]} + * Slaves who have starred in random individual events the current week + */ + RIESkip: [], + /** @type {number} + * Random individual events remaining the current week + */ + RIERemaining: 0, + /** @type {number} + * Number of weeks to track events + * 0: no tracking, + * 2: soft, + * 4: medium, + * 8: high + */ + level: 0, + /** @type {boolean} + * Track also other random events + */ + otherTrack: false, + /** @type {{name: string, weeksPassed: number, triggered: number}[]} + * Events tracked in the tracking period + */ + events: [], + }, + // Stable Diffusion settings aiAdetailerFace: false, aiApiUrl: "http://localhost:7860", diff --git a/saveTools/fc_edit_save.py b/saveTools/fc_edit_save.py index 010d3cc07dd98f3bc855118b59ad1b24f14a86c7..ffe2c906a44e6ffa479e6aa24130955cad15b45c 100755 --- a/saveTools/fc_edit_save.py +++ b/saveTools/fc_edit_save.py @@ -94,7 +94,7 @@ IGNORE_IN_PC = [ "HGExclude", "NCSyouthening", "albinismOverride", "assignment", "attrKnown", "canRecruit", "choosesOwnAssignment", "choosesOwnChastity", "choosesOwnClothes", "clitSetting", "counter.PCChildrenFathered", - "counter.PCKnockedUp", "counter.births", "counter.pitKills", + "counter.PCKnockedUp", "counter.births", "counter.pitKills", "counter.events", "counter.publicUse", "currentRules", "custom.desc", "custom.hairVector", "custom.image", "custom.label", "custom.title", "custom.titleLisp", "death", "devotion", "dietCum", "dietMilk", "effectiveWhoreClass", "fetishKnown", @@ -1078,7 +1078,7 @@ def clone_slave(game_vars, orig_slave, same_parents=False): new_slave[zero_key] = 0 for counter in [ "PCChildrenFathered", "PCKnockedUp", "births", "birthsTotal", - "laborCount", "slavesFathered", "slavesKnockedUp" + "laborCount", "slavesFathered", "slavesKnockedUp", "events" ]: if counter in new_slave["counter"]: new_slave["counter"][counter] = 0 diff --git a/src/002-config/fc-version.js b/src/002-config/fc-version.js index 7e2da15ca209193873565698d2e7ae269548c8d1..1e4661de995c0d4a36d83225542f2a4402488488 100644 --- a/src/002-config/fc-version.js +++ b/src/002-config/fc-version.js @@ -2,5 +2,5 @@ App.Version = { base: "0.10.7.1", // The vanilla version the mod is based off of, this should never be changed. pmod: "4.0.0-alpha.31", commitHash: null, - release: 1251, // When getting close to 2000, please remove the check located within the onLoad() function defined at line five of src/js/eventHandlers.js. + release: 1252, // When getting close to 2000, please remove the check located within the onLoad() function defined at line five of src/js/eventHandlers.js. }; diff --git a/src/005-passages/eventsPassages.js b/src/005-passages/eventsPassages.js index 5ec2af02801321006de8c5eb05f26a1dfd98fad4..634507f2eb54176200b6c8138632d068502db6a1 100644 --- a/src/005-passages/eventsPassages.js +++ b/src/005-passages/eventsPassages.js @@ -20,18 +20,18 @@ new App.DomPassage("Random Individual Event", () => { V.nextButton = "Continue"; - if (V.RIERemaining <= 0) { + if (V.eventControl.RIERemaining <= 0) { // first event for this week: reset counter - V.RIERemaining = Math.max(1, Math.min(V.RIEPerWeek, Math.floor(getRieEligibleSlaves().length / 2))); + V.eventControl.RIERemaining = Math.max(1, Math.min(V.eventControl.RIEPerWeek, Math.floor(getRieEligibleSlaves().length / 2))); } - if (V.RIERemaining > 1) { + if (V.eventControl.RIERemaining > 1) { // return to self if we have more events to play V.nextLink = "Random Individual Event"; } else { // last event for this week: out to Next Week V.nextLink = "Next Week"; } - V.RIERemaining--; + V.eventControl.RIERemaining--; return App.Events.playRandomIndividualEvent(); }, ["end-week", "temporary-images"] diff --git a/src/cheats/cheatEditActor.js b/src/cheats/cheatEditActor.js index 689c7549def8185ae6e04e5a30074b2be655fddd..4cb506ef7eae9d5792bf0a3c869c084a6c0893d5 100644 --- a/src/cheats/cheatEditActor.js +++ b/src/cheats/cheatEditActor.js @@ -1718,6 +1718,10 @@ App.UI.Cheat.cheatEditActor = function(actor, actorType) { options.addOption("Elite event 6", "preggo", V.tempSlave.counter) .addValue("None", 0).off().showTextBox(); } + if (slave) { + options.addOption("Random slave events starred", "events", V.tempSlave.counter) + .addValue("None", 0).off().showTextBox(); + } el.append(options.render()); return el; diff --git a/src/data/backwardsCompatibility/backwardsCompatibility.js b/src/data/backwardsCompatibility/backwardsCompatibility.js index a44a32f72d5f9f0e48785632694360febad20e3e..85464a77b02d8ecc79edbfecf67aa99315fb735e 100644 --- a/src/data/backwardsCompatibility/backwardsCompatibility.js +++ b/src/data/backwardsCompatibility/backwardsCompatibility.js @@ -2840,6 +2840,24 @@ App.Update.oldVersions = function(node) { } }); } + if (V.releaseID < 1252) { + // Events Control + { + if (typeof V.RIEPerWeek !== "undefined") { + V.eventControl = { + RIEPerWeek: V.RIEPerWeek || 1, + RIERemaining: V.RIERemaining ?? 0, + RIESkip: V.RIESkip ?? [], + level: 0, + otherTrack: false, + events: [], + }; + delete V.RIEPerWeek; + delete V.RIERemaining; + delete V.RIESkip; + } + } + } node.append(`Done!`); }; diff --git a/src/data/backwardsCompatibility/datatypeCleanup.js b/src/data/backwardsCompatibility/datatypeCleanup.js index dcea747528e89786db4ad50f4a48ed9606ffee62..3b4076e8feaff72dcffe896663f10178b1d80443 100644 --- a/src/data/backwardsCompatibility/datatypeCleanup.js +++ b/src/data/backwardsCompatibility/datatypeCleanup.js @@ -235,6 +235,7 @@ App.Entity.Utils.SlaveDataSchemeCleanup = (function() { PCChildrenFathered: "PCChildrenFathered", slavesKnockedUp: "slavesKnockedUp", PCKnockedUp: "PCKnockedUp", + events: "events", }, false, true); } @@ -1058,6 +1059,7 @@ globalThis.SlaveDatatypeCleanup = (function SlaveDatatypeCleanup() { slave.counter.PCChildrenBeared = Math.max(+slave.counter.PCChildrenBeared, 0) || 0; slave.counter.timesBred = Math.max(+slave.counter.timesBred, 0) || 0; slave.counter.reHymen = Math.max(+slave.counter.reHymen, 0) || 0; + slave.counter.events = Math.max(+slave.counter.events, 0) || 0; slave.bodySwap = Math.max(+slave.bodySwap, 0) || 0; } diff --git a/src/data/newGamePlus.js b/src/data/newGamePlus.js index ea1cb7a996569a93fdc3ad5ce096af3c424f2a1f..c440e6bd2ca77511d64f1f43905bfd580840b878 100644 --- a/src/data/newGamePlus.js +++ b/src/data/newGamePlus.js @@ -220,6 +220,7 @@ App.Data.NewGamePlus = (function() { slave.counter.oral = 0; slave.counter.anal = 0; slave.counter.vaginal = 0; + slave.counter.events = 0; slave.partners = ngUpdatePartners(slave); slave.lifetimeCashExpenses = 0; slave.lifetimeCashIncome = 0; diff --git a/src/endWeek/nextWeek/nextWeek.js b/src/endWeek/nextWeek/nextWeek.js index 3c314e87883fb4223b2d8e485a522d3c0c35b634..9cc3b7df9416cbc716860963897d1bbf1a929f60 100644 --- a/src/endWeek/nextWeek/nextWeek.js +++ b/src/endWeek/nextWeek/nextWeek.js @@ -415,7 +415,9 @@ App.EndWeek.nextWeek = function() { V.prisonCircuitIndex = 0; } - V.RIESkip = []; + V.eventControl.RIESkip = []; + V.eventControl.events = V.eventControl.events.filter(e => e.weeksPassed < V.eventControl.level); + V.eventControl.events.forEach(e => (e.weeksPassed++)); V.independenceDay = 1; V.coursed = 0; V.JFC.reorder = 0; diff --git a/src/events/randomEvent.js b/src/events/randomEvent.js index bbb051815cf67bccf26d28076fc9343dcedd07ac..689c33eb45bc07b4bc49f5049b106d46159d8ec6 100644 --- a/src/events/randomEvent.js +++ b/src/events/randomEvent.js @@ -442,13 +442,14 @@ App.Events.getNonindividualRecruitmentEvents = function() { /** choose a valid, castable event from the given event list * @param {Array<App.Events.BaseEvent>} eventList - list of events to filter + * @param {Array} weight - alternate weight of the events: the default weight of the event will be used if there's no alternate weight in the array * @param {FC.SlaveState} [slave] - event slave (mandatory to cast in first actor slot). omit for nonindividual events. * @returns {Array<App.Events.BaseEvent>} */ -App.Events.getValidEvents = function(eventList, slave) { +App.Events.getValidEvents = function(eventList, weight = [], slave) { return eventList .filter(e => App.Events.canExecute(e, slave)) - .reduce((res, cur) => res.concat(Array(cur.weight).fill(cur)), []); + .reduce((res, cur) => res.concat(Array(weight[cur.eventName] ?? cur.weight).fill(cur)), []); }; App.Events.playRandomIndividualEvent = function() { @@ -463,7 +464,17 @@ App.Events.playRandomIndividualEvent = function() { if (V.event instanceof App.Events.BaseEvent) { // we've deserialized a saved game with an event active, or a player has picked one, so just play it immediately App.Events.runPassageEvent(V.event, d); - V.RIESkip.push(V.event.actors[0]); + V.eventControl.RIESkip.push(V.event.actors[0]); + getSlave(V.event.actors[0]).counter.events++; + if (V.eventControl.level > 0) { + const tracked = V.eventControl.events.findIndex(e => e.name === V.event.eventName); + if (tracked === -1) { + V.eventControl.events.push({name: V.event.eventName, weeksPassed: 0, triggered: 1}); + } else { + V.eventControl.events[tracked].triggered++; + V.eventControl.events[tracked].weeksPassed = 0; + } + } } else { const eligibleSlaves = getRieEligibleSlaves(); if (eligibleSlaves.length === 0) { @@ -472,13 +483,13 @@ App.Events.playRandomIndividualEvent = function() { } else if (V.debugMode > 0 && V.debugModeEventSelection > 0) { V.nextButton = "Refresh"; V.nextLink = passage(); - V.RIERemaining++; // we've consumed one of our event possibilities already, but we haven't played the event yet, so put it back + V.eventControl.RIERemaining++; // we've consumed one of our event possibilities already, but we haven't played the event yet, so put it back // show all the possible random individual events App.UI.DOM.appendNewElement("h2", d, "Random Individual Events"); - const countPara = App.UI.DOM.appendNewElement("p", d, `At most ${numberWithPluralOne(V.RIEPerWeek, "slave")} will get Random Individual Events per week, and you have ${num(V.RIERemaining)} left.`); - if (V.RIESkip.length > 0) { - countPara.append(` An event has already played for ${toSentence(V.RIESkip.map(s => SlaveFullName(getSlave(s))))}, so they are not eligible to play another.`); + const countPara = App.UI.DOM.appendNewElement("p", d, `At most ${numberWithPluralOne(V.eventControl.RIEPerWeek, "slave")} will get Random Individual Events per week, and you have ${num(V.eventControl.RIERemaining)} left.`); + if (V.eventControl.RIESkip.length > 0) { + countPara.append(` An event has already played for ${toSentence(V.eventControl.RIESkip.map(s => SlaveFullName(getSlave(s))))}, so they are not eligible to play another.`); } const slaveDiv = App.UI.DOM.appendNewElement("div", d, "Show events for this slave: "); @@ -496,7 +507,7 @@ App.Events.playRandomIndividualEvent = function() { const linkList = App.UI.DOM.appendNewElement("div", d, '', ["event-section"]); const writeEventList = (/** @type {FC.SlaveState} */eventSlave) => { $(linkList).empty(); - const events = App.Events.getValidEvents(App.Events.getIndividualEvents(), eventSlave); + const events = App.Events.getValidEvents(App.Events.getIndividualEvents(), [], eventSlave); if (events.length === 0) { events.push(makeNoEvent(eventSlave.ID)); } @@ -510,19 +521,85 @@ App.Events.playRandomIndividualEvent = function() { App.UI.DOM.appendNewElement("div", d, App.UI.DOM.passageLink("Skip week-end events", "Next Week")); d.append(App.Events.renderEventDebugger("Random Individual Event")); } else { - // pick a slave for a random individual event - const eventSlave = eligibleSlaves.random(); - - // pick a random individual event for that slave. Use RE No Event if there are none she's eligible for. - const events = App.Events.getValidEvents(App.Events.getIndividualEvents(), eventSlave); - const event = events.random() || makeNoEvent(eventSlave.ID); - + const rareEvents = [ // Add events with very specific requirements here + "RESSBirthdaySex", // only once a year for every actor eligible + "RESSFirstPeriod", // only triggers for some prepubertal female slaves for 6 months + "RESSWetDreams", // only triggers for some prepubertal male slaves for 6 months + "RESSBirthday", // can trigger only once a year for a few slaves + "RESSLanguageLesson", // slaves requisites are very specific + ]; + let events = []; + let selectSlaves = []; + let eventSlave = null; + let event = null; + let validEvents = App.Events.getIndividualEvents(); + if (V.eventControl.level > 0) { // Repeated events control active + let weight = []; + for (let xEvent = 0; xEvent < 3; xEvent++) { // up to 3 loops to look for valid events + validEvents.forEach(e => { + const isRare = rareEvents.includes(e.eventName); + let eventWeight = e.weight + xEvent + Math.floor(e.weight / 2) + (isRare ? e.weight : 1); // bonus for all events + let controlled = V.eventControl.events.findIndex(e2 => e2.name === e.eventName); + if (controlled !== -1) { // events triggered within the control time + eventWeight = V.eventControl.events[controlled].weeksPassed === 0 ? 0 : // played the present week + Math.max(isRare ? e.weight : 0, eventWeight // don't exclude rare events if they've not appeared in the current week; give them their base weight at least + - (V.eventControl.events[controlled].weeksPassed < 2 ? 1 : 0) // played last week + - (V.eventControl.events[controlled].weeksPassed < 3 && V.eventControl.level > 2 ? 1 : 0) // played in the last two weeks for medium or high control time + - (V.eventControl.events[controlled].weeksPassed < 6 && V.eventControl.level > 4 ? 1 : 0) // played in the last five weeks for high control time + - (V.eventControl.events[controlled].triggered > 1 ? V.eventControl.events[controlled].triggered > 2 ? 2 : 1 : 0) // times played within control time + - (V.eventControl.events[controlled].triggered > 1 && V.eventControl.level > 4 ? 1 : 0) // times played within control time with high control + - 2); // on the first round of xEvent, all the events with standard weight that are controlled will be excluded + }; + weight[e.eventName] = eventWeight; + }); + for (let xSlaves = 0; xSlaves < 3; xSlaves++) { // up to 3 loops to look for valid slaves with valid events + selectSlaves = getBestSlaves({part: "counter.events", count: Math.min(((xEvent + 1) ** 2 + (xSlaves + 1)) * (3 + (V.eventControl.level < 8 ? V.eventControl.level < 4 ? 2 : 1 : 0)), eligibleSlaves.length), largest: false}, eligibleSlaves); // look for a limited group of slaves among the ones that have been involved in less individual events + eventSlave = selectSlaves.random(); + events = App.Events.getValidEvents(validEvents, weight, eventSlave); + if (selectSlaves.length < eligibleSlaves.length && xEvent === 2) { // add rare events for an excluded slave on the last xEvent loop, if possible + eventSlave = eligibleSlaves.filter(s => !selectSlaves.some(ss => s.ID === ss.ID)).random(); + events = events.concat(App.Events.getValidEvents(validEvents.filter(re => rareEvents.includes(re.eventName) && (V.eventControl.events.find(fe => fe.name === re.eventName)?.weeksPassed ?? 1) !== 0), [], eventSlave)); + } + + if (events.length) { // if there are valid events, choose one and end loops + event = events.random(); + xEvent = xSlaves = 3; + } + } + } + } + if (!event) { // the repeated events handling didn't achieve its goal, do something else + eligibleSlaves.forEach(s => { // try to play a rare event + events = events.concat(App.Events.getValidEvents(validEvents.filter(e => (V.eventControl.events.find(fe => fe.name === e.eventName)?.weeksPassed ?? 3) <= (V.eventControl.level > 4 ? 3 : 1) && rareEvents.includes(e.eventName)), [], s)); + }); + if (events.length === 0) { + // pick a slave for a random individual event + eventSlave = eligibleSlaves.random(); + + // pick a random individual event for that slave + events = App.Events.getValidEvents(validEvents.filter(e => (V.eventControl.events.find(fe => fe.name === e.eventName)?.weeksPassed ?? 1) !== 0), [], eventSlave); // without the present week already played events + if (events.length === 0) { + events = App.Events.getValidEvents(validEvents, [], eventSlave); // do it the traditional way + } + } + event = events.random() || makeNoEvent(eventSlave.ID); // use RE No Event if there are none she's eligible for + } // record the chosen event in 'current' (pre-play!) history as well as current state so that it will serialize out correctly if saved from this passage // WARNING: THIS IS ***NOT*** THE ACTIVE STATE PAGE! // @ts-ignore - under-defined object State.current.variables.event = V.event = event; App.Events.runPassageEvent(event, d); - V.RIESkip.push(event.actors[0]); + V.eventControl.RIESkip.push(event.actors[0]); + getSlave(event.actors[0]).counter.events++; + if (V.eventControl.level > 0) { + const tracked = V.eventControl.events.findIndex(e => e.name === V.event.eventName); + if (tracked === -1) { + V.eventControl.events.push({name: V.event.eventName, weeksPassed: 0, triggered: 1}); + } else { + V.eventControl.events[tracked].triggered++; + V.eventControl.events[tracked].weeksPassed = 0; + } + } } } return d; @@ -534,9 +611,50 @@ App.Events.playRandomNonindividualEvent = function() { if (V.event instanceof App.Events.BaseEvent) { // we've deserialized a saved game with an event active, or a player has picked one, so just play it immediately App.Events.runPassageEvent(V.event, d); + if (V.eventControl.level > 0 && V.eventControl.otherTrack) { + const tracked = V.eventControl.events.findIndex(e => e.name === V.event.eventName); + if (tracked === -1) { + V.eventControl.events.push({name: V.event.eventName, weeksPassed: 0, triggered: 1}); + } else { + V.eventControl.events[tracked].triggered++; + V.eventControl.events[tracked].weeksPassed = 0; + } + } } else { let nonRecEvents = App.Events.getValidEvents(App.Events.getNonindividualEvents()); let recEvents = App.Events.getValidEvents(App.Events.getNonindividualRecruitmentEvents()); + if (V.eventControl.level > 0 && V.eventControl.otherTrack) { + nonRecEvents = nonRecEvents.filter(e => { + const controlled = V.eventControl.events.findIndex(e2 => e2.name === e.eventName); + if (controlled === -1) { + return true; + } + if (V.eventControl.events[controlled].weeksPassed > (V.eventControl.level > 2 ? 2 : 1)) { // not played last week, last 2 weeks with medium or high control level + if (V.eventControl.events[controlled].triggered < (V.eventControl.level > 4 ? 2 : 3)) { // not played more than 2 times within the control time, more than 1 with high control time + return true; + } + } + return false; + }); + recEvents = recEvents.filter(e => { + const controlled = V.eventControl.events.findIndex(e2 => e2.name === e.eventName); + if (controlled === -1) { + return true; + } + if (V.eventControl.events[controlled].weeksPassed > (V.eventControl.level > 2 ? 2 : 1)) { // not played last week, last 2 weeks with medium or high control level + if (V.eventControl.events[controlled].triggered < (V.eventControl.level > 4 ? 2 : 3)) { // not played more than 2 times within the control time, more than 1 with high control time + return true; + } + } + return false; + }); + if (nonRecEvents.length === 0){ + nonRecEvents = App.Events.getValidEvents(App.Events.getNonindividualEvents()); + } + if (recEvents.length === 0){ + recEvents = App.Events.getValidEvents(App.Events.getNonindividualRecruitmentEvents()); + } + } if (V.debugMode > 0 && V.debugModeEventSelection > 0) { V.nextButton = "Refresh"; V.nextLink = passage(); @@ -565,6 +683,15 @@ App.Events.playRandomNonindividualEvent = function() { // @ts-ignore - under-defined object State.current.variables.event = V.event = event; App.Events.runPassageEvent(event, d); + if (V.eventControl.level > 0 && V.eventControl.otherTrack) { + const tracked = V.eventControl.events.findIndex(e => e.name === V.event.eventName); + if (tracked === -1) { + V.eventControl.events.push({name: V.event.eventName, weeksPassed: 0, triggered: 1}); + } else { + V.eventControl.events[tracked].triggered++; + V.eventControl.events[tracked].weeksPassed = 0; + } + } } else { throw new Error("There should always be at least one eligible nonindividual event."); } diff --git a/src/gui/options/options.js b/src/gui/options/options.js index 8f8fb69f09bcf805067330f449366552f450f87e..7e75a275d9a44cc556c89970cafaeba974455bb9 100644 --- a/src/gui/options/options.js +++ b/src/gui/options/options.js @@ -792,6 +792,21 @@ App.UI.optionsPassage = function() { .addValue("Enabled", 1).on().addValue("Disabled", 0).off() .addComment("This will sort rule assistant output. You may benefit if you have a lot of rules, but only want to look out for a specific portion of it."); + options.addOption("Random slave events repeat control", "level", V.eventControl) + .addValue("No control", 0, () => V.eventControl.RIEPerWeek = Math.min(V.eventControl.RIEPerWeek, 3)) + .addValue("Soft", 2, () => V.eventControl.RIEPerWeek = Math.min(V.eventControl.RIEPerWeek, 3)) + .addValue("Medium", 4, () => V.eventControl.RIEPerWeek = Math.min(V.eventControl.RIEPerWeek, 3)) + .addValue("High", 8) + .addComment("This will control the repetition of random slave events and their actors to increase variation. The higher the control, the more weeks it will try to prevent the same event from happening again."); + + if (V.eventControl.level > 0) { + options.addOption("Other random events repeat control", "otherTrack", V.eventControl) + .addValue("Enabled", true).on().addValue("Disabled", false).off(); + + options.addOption("Maximum random slave events per week", "RIEPerWeek", V.eventControl) + .addValueList(V.eventControl.level > 4 ? [1, 2, 3, 4] : [1, 2, 3]); + } + el.append(options.render()); App.UI.DOM.appendNewElement("div", el, "Importing options into an in-progress game risks breaking the game, but you can export options from this game and import them into a new game.", ["warning"]); @@ -1039,8 +1054,8 @@ App.Intro.contentAndFlavor = function(isIntro) { } if (!isIntro) { - options.addOption("Maximum random slave events per week", "RIEPerWeek") - .addValueList([1, 2, 3]); + options.addOption("Maximum random slave events per week", "RIEPerWeek", V.eventControl) + .addValueList(V.eventControl.level > 4 ? [1, 2, 3, 4] : [1, 2, 3]); } options.addOption("Slaves falling ill is currently", "seeIllness") diff --git a/src/js/states/HumanState.js b/src/js/states/HumanState.js index 348b88c3b2c5ed41169632b7445d4442b70baee2..8f8cc31001ebd767f48d8943fd15ce993dde9361 100644 --- a/src/js/states/HumanState.js +++ b/src/js/states/HumanState.js @@ -2715,6 +2715,7 @@ App.Entity.HumanState = class HumanState { newCounter.slavesKnockedUp = 0; newCounter.timesBred = 0; newCounter.PCChildrenBeared = 0; + newCounter.events = 0; slave.counter = newCounter; slave.rules = new App.Entity.RuleState(); const newCustom = new App.Entity.CustomAddonsState(); diff --git a/src/js/states/SlaveState.js b/src/js/states/SlaveState.js index 026af77bab9c56a48241a2a40bee4ffd0369bb75..122ddc98cf6214f747a262d77106a6e55dbb5eaf 100644 --- a/src/js/states/SlaveState.js +++ b/src/js/states/SlaveState.js @@ -64,6 +64,8 @@ App.Entity.SlaveActionCountersState = class SlaveActionCountersState extends App this.timesBred = 0; /** How many of your children has they borne. */ this.PCChildrenBeared = 0; + /** In how many random events has been actor */ + this.events = 0; } }; diff --git a/src/js/utilsSlaves.js b/src/js/utilsSlaves.js index f8e5e65886bc43e860cf4912973664ae429558e3..2a7d32f07ba42368eb255383312102d3d507bdc4 100644 --- a/src/js/utilsSlaves.js +++ b/src/js/utilsSlaves.js @@ -20,7 +20,7 @@ globalThis.servantsLength = function() { globalThis.getRieEligibleSlaves = function() { return V.slaves.filter(s => s.fuckdoll === 0 && (assignmentVisible(s) || [Job.MASTERSUITE, Job.CONCUBINE, Job.QUARTER].includes(s.assignment)) && - !V.RIESkip.includes(s.ID) + !V.eventControl.RIESkip.includes(s.ID) ); }; @@ -164,13 +164,14 @@ globalThis.slaveSortMinor = function(slaves) { * getBestSlaves({part:"dick", smallest:true, filter:(slave)=>slave.dick > 0});//defaults to top 3 * getBestSlaves({part:slave=>slave.intelligence+slave.intelligenceImplant}); * @param {getBestSlavesParams} params + * @param {FC.SlaveState[]} [slaveArray] * @returns {FC.SlaveState[]} sorted from best to worst */ -globalThis.getBestSlaves = function({part, count = 3, largest = true, filter = (() => true)}) { +globalThis.getBestSlaves = function({part, count = 3, largest = true, filter = (() => true)}, slaveArray = V.slaves) { const partCB = _.isFunction(part) ? part : (slave) => slave[part]; const sortMethod = largest ? (left, right) => right.value - left.value : (left, right) => left.value - right.value; - return V.slaves.filter(slave => filter(slave)) + return slaveArray.filter(slave => filter(slave)) .map(slave => ({slave, value: partCB(slave)})) .sort(sortMethod) .slice(0, count)