Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • PantyNabber/fc-pregmod
  • pregmodfan/fc-pregmod
  • Alice.Grant/fc-pregmod
  • powerfful/fc-pregmod
  • elstumpo/fc-pregmod
  • Y/fc-pregmod
  • floer/fc-pregmod
  • oidocrop/fc-pregmod
  • hawk5005/fc-pregmod
  • nn/fc-pregmod
  • latios298/fc-pregmod
  • brpregmodfan/fc-pregmod
  • SomeoneTookMyUserName/fc-pregmod
  • 000-250-006/fc-pregmod
  • rewrica/fc-pregmod
  • Stuffedgame/fc-pregmod
  • wisepants314/fc-pregmod
  • fcanon/fc-pregmod
  • randomanon1/pregmod-mod-cyberfurry
  • teddy.buckland/fc-pregmod
  • farsinian_591b7a2d8b49d/fc-pregmod
  • FCShotadev/fc-pregmod
  • uselessartifact/fc-pregmod
  • irina_90/fc-pregmod
  • thaumx/fc-pregmod
  • MouseOfLight/fc-pregmod
  • empresssela/fc-pregmod
  • MasterAaran/fc-pregmod
  • ishy/fc-pregmod
  • psychofox/fc-pregmod
  • shadomancer/fc-pregmod
  • tycrakgg/fc-pregmod
  • azktaawc/fc-pregmod
  • andonno07/fc-pregmod
  • Onithyr/fc-pregmod
  • redneck987.jl/fc-pregmod
  • Farseeker/fc-pregmod
  • milliarc/fc-pregmod
  • BeefimusMaximus/fc-pregmod
  • magicknight79/fc-pregmod
  • hexall90/fc-pregmod
  • cantworkforever/fc-pregmod
  • jc052005/fc-pregmod
  • klorpa/fc-pregmod
  • doku/fc-pregmod
  • samhradh/fc-pregmod
  • scientist/fc-pregmod
  • albania420/fc-pregmod
  • Editoranon/fc-pregmod
  • Anony/fc-pregmod
  • deimios666/fc-pregmod
  • IvoHoe/fc-pregmod
  • bitty/fc-pregmod
  • RealAnon1800/fc-pregmod
  • brankirk/fc-pregmod
  • Amygdalan/fc-pregmod
  • DankWolf/fc-pregmod
  • Supot1951/fc-pregmod
  • bcy603/fc-pregmod
  • pwfxjpuv/fc-pregmod
  • ThreadAnon/fc-pregmod
  • Anon1800/fc-pregmod
  • Echoart/fc-pregmod
  • Dingotush/fc-pregmod
  • anonman/fc-pregmod
  • Arkerthan/fc-pregmod
  • svornost/fc-pregmod
  • wierdwierdos/fc-pregmod
  • wetwareAnon/fc-pregmod
  • QuartzHat/fc-pregmod
  • IchthysdeKilt/fc-pregmod
  • AnonAnonFC/fc-pregmod
  • Alexsis/fc-pregmod
  • LoyalTreeWP/fc-pregmod
  • aerialace/fc-pregmod
  • NurseryAnon/fc-pregmod
  • drakeashordcataclysm/fc-pregmod
  • AshVaris/fc-pregmod
  • purely0nothing/fc-pregmod
  • alex2011/fc-pregmod
  • Lindontree/fc-pregmod
  • FCaa/fc-pregmod
  • TR-8R/fc-pregmod
  • Jones/fc-pregmod
  • brr99/fc-pregmod
  • WriteAnon101/fc-pregmod
  • Drosil/fc-pregmod
  • Bob1221/fc-pregmod
  • vas/fc-pregmod
  • gitgud.user.937/fc-pregmod
  • D-K/fc-pregmod
  • AnonDev/fc-pregmod
  • madman23456/fc-pregmod
  • InarusLynx/fc-pregmod
  • Sonofrevvan/fc-pregmod
  • Randoisrando/fc-pregmod
  • cheez94/fc-pregmod
  • dldldl/fc-pregmod
  • alice321/fc-pregmod
  • Alexei91/fc-pregmod
  • darkcy/fc-pregmod
  • MapleMAD/fc-pregmod
  • pillarofsalt/fc-pregmod
  • vultureangels/fc-pregmod
  • kernel/fc-pregmod
  • nooneman/fc-pregmod
  • deepmurk/fc-pregmod
  • uglybead/fc-pregmod
  • lemongrab/fc-pregmod
  • temperence-chan/fc-pregmod
  • hcommenter/fc-pregmod
  • SpedeMemerson/fc-pregmod
  • qwijqwsf/fc-pregmod
  • BuDClow/fc-pregmod
  • HiveBro/fc-pregmod
  • shoku/fc-pregmod
  • ezsh/fc-pregmod
  • Blank/fc-pregmod
  • randoralcissian/fc-pregmod
  • benito92/fc-pregmod
  • balakart/fc-pregmod
  • wedonotsaw/fc-pregmod
  • Cayleth/fc-pregmod
  • Khip/fc-pregmod
  • Zfair/fc-pregmod
  • promethium/fc-pregmod
  • scyne/fc-pregmod
  • ZZC/fc-pregmod
  • SilverJanine/fc-pregmod
  • joxosix654email-9.co/fc-pregmod
  • Littlefootlittleguy/fc-pregmod
  • FelipeBA/fc-pregmod
  • bigtiddygothbf/fc-pregmod
  • Qotsafan/fc-pregmod
  • Zachpocalypse/fc-pregmod
  • milkanon66/fc-pregmod
  • GreGGoZZ/fc-pregmod
  • drsnarf86/fc-pregmod
  • valen102938/fc-pregmod
  • pregspammer/fc-pregmod
  • ponderin94/fc-pregmod
  • nook/fc-pregmod
  • carnifex34/fc-pregmod-mod-carni
  • SyntheticHigh/fc-pregmod
  • bob112211/fc-pregmod
  • amomynous0/fc-pregmod
  • oxone/fc-pregmod
  • MaxEuwe/fc-pregmod
  • nekoanon/fc-pregmod
  • preglocke/fc-pregmod
  • valen10293847/fc-pregmod
  • 2hu4u/fc-pregmod
  • mayibrad/fc-pregmod
  • Screm/fc-pregmod
  • Ansopedi/fc-pregmod
  • mrchaosbones/fc-pregmod
  • putrid/fc-pregmod
  • Kinnerman/fc-pregmod
  • gungrave1155/fc-pregmod
  • prndev/fc-pregmod
  • weresmilodon/fc-pregmod
  • auxxigobin/fc-pregmod
  • alice-chan/fc-pregmod
  • wigglie/fc-pregmod
  • jrliltfgb/fc-pregmod
  • Lord.alek.shade/fc-pregmod
  • truetailthesquire/fc-pregmod
  • lowercasedonkey/fc-pregmod
  • alice-chan9/fc-pregmod
  • eroglyphics/fc-pregmod
  • taliyent/fc-pregmod
  • zenzombie90/fc-pregmod
  • kjarik/fc-pregmod
  • wriggler/fc-pregmod
  • midnightblue/fc-pregmod
  • faraen/fc-pregmod
  • sigurd.cole/fc-pregmod
  • FCbuganon/fc-pregmod
  • kidkinster/fc-pregmod
  • Kar_Dragon/fc-pregmod
  • Zhafier/fc-pregmod
  • crcaretti/fc-pregmod
  • anond/fc-pregmod
  • tempmania/fc-pregmod
  • Dhanze/fc-pregmod
  • EstaUnCachucha/fc-pregmod
  • oniAnon/fc-pregmod
  • plebian/fc-pregmod
  • maxd569/fc-pregmod
  • Levarn/fc-pregmod
  • pumpkinspice/fc-pregmod
  • GammaXai/fc-pregmod
  • DanBackslide/fc-pregmod
  • i107760/fc-pregmod
  • Absimiliard/fc-pregmod
  • AmbrosiaCheesecake/fc-pregmod
  • fuguer/fc-pregmod
  • Azurel/fc-pregmod
  • Fake_Dev/fc-pregmod
  • ddongsanda/fc-pregmod
  • Combine456/fc-pregmod
  • UnwrappedGodiva/fc-pregmod
  • toyRuberDucky/fc-pregmod
  • zmobie/fc-pregmod
  • chuongk/fc-pregmod
  • BigWalnuts/fc-pregmod
  • Birdstrike/fc-pregmod
  • r3d/fc-pregmod
  • mawspa/fc-pregmod
  • sushila/fc-pregmod
  • DeathShip/fc-pregmod
  • eggrollsandwich/fc-pregmod
  • krayken/fc-pregmod
  • Reman/fc-pregmod
  • dwiafgts/fc-pregmod
  • jort93/fc-pregmod
  • teruterubouzu/fc-pregmod
  • flut/fc-pregmod
  • john-normal/fc-pregmod
  • Jonathan2405/fc-pregmod
  • Tyrgalon/fc-pregmod
  • NovX/fc-pregmod
  • Star1/fc-pregmod
  • Transhumanist01/fc-pregmod
  • m1017242/fc-pregmod
  • Rizal98798/fc-pregmod
  • jamezu369/fc-pregmod
  • thisisawittyname/fc-pregmod
  • KnightBoulegard/fc-pregmod
  • jblack/fc-pregmod
  • Souldrainr/fc-pregmod
  • torbjornhub/fc-pregmod
  • turnop/fc-pregmod
  • breadedpigeon/fc-pregmod
  • fire.maker/fc-pregmod
  • Inahaze/fc-pregmod
  • Waerjak/fc-pregmod
  • Trashman1138/fc-pregmod
  • supanintendo/fc-pregmod
  • _no0neman/fc-pregmod
  • Weslo/fc-pregmod
  • qw89/fc-pregmod
  • EvilDruid/fc-pregmod
  • dt25/fc-pregmod
  • Raou/fc-pregmod
  • DDouFu/fc-pregmod
  • Mauno/fc-pregmod
  • PandemoniumPenguin/fc-pregmod
  • AngelPuppet/fc-pregmod
  • DasUser79/fc-pregmod
  • Keaeag3s/fc-pregmod
  • HazeHazeHaze/fc-pregmod
  • hpotato/fc-pregmod
  • owouchthatbloodyhurt/fc-pregmod
  • v7Silent/fc-pregmod
  • nickylass/fc-pregmod
  • ThePrimer/fc-pregmod
  • PineCone/fc-pregmod
  • bruhmomentum17/fc-pregmod
  • CheatDude/fc-pregmod
  • synnove/fc-pregmod
  • en_bees/fc-pregmod
  • seronis/fc-pregmod
  • Nepidinepnep/fc-pregmod
  • Titanninja/fc-pregmod
  • Elohiem/fc-pregmod
  • cocoajazz/fc-pregmod
  • tfwncagf/fc-pregmod
  • ChunkyMonke/fc-pregmod
  • Dracoman671/fc-pregmod
  • jgl/fc-pregmod
  • Inev/fc-pregmod
  • jbige/fc-pregmod
  • MonsterMate/fc-pregmod
  • Konstantin6961/fc-pregmod
  • darth_ashi/fc-pregmod
  • shinx/fc-pregmod
  • Anu/fc-pregmod
  • Greytide/fc-pregmod
  • Bonafidemetal/fc-pregmod
  • Peje/fc-pregmod
  • Hexfy98/fc-pregmod
  • TooSlow/fc-pregmod
  • SoGu/fc-pregmod
  • CloudyCoffee/fc-pregmod
  • Welptard/fc-pregmod
  • Ploc/fc-pregmod-ploc
  • rain-/fc-pregmod
  • Pecanus/fc-pregmod
  • Jhortrax/fc-pregmod
  • valleytwo/fc-pregmod
  • QCmd/fc-pregmod
  • kung-wada/fc-pregmod
  • LolGaye/fc-pregmod
  • Exspiravit1/fc-pregmod
  • jadeddog/fc-pregmod
  • buster-scruggs/fs-antebellum-revivalism
  • policia123/fc-pregmod
  • evrgentesee/fc-pregmod
  • rko127/fc-pregmod
  • ExcalGrip12/fc-pregmod
  • BlackAion/fc-pregmod
  • Boss2020/fc-pregmod
  • Lawled/fc-pregmod
  • shiro/fc-pregmod
  • Skavenkeri/fc-pregmod
  • PooPooDooDooHead/fc-pregmod
  • Dugee/fc-pregmod
  • Portal124/fc-pregmod-vore
  • Fekenol/fc-pregmod
  • elGuapo/fc-pregmod
  • KelioSteel/fc-pregmod
  • sldlddk/fc-pregmod
  • lumepanter/fc-pregmod
  • ryuhana/fc-pregmod
  • Nene1009yb/fc-pregmod
  • DontAskDontTell/fc-pregmod-extra-events
  • Dulgi/fc-pregmod
  • Jate/fc-pregmod
  • percy365/fc-pregmod
  • franklygeorge/fc-pregmod
  • Dragneel117/fc-pregmod
  • vl96/fc-pregmod
  • Gorlom/fc-economicmod
  • NotAlive/fc-pregmod
  • Heretek/fc-pregmod
  • joeshmo828282/fc-pregmod
  • deswes/fc-pregmod
  • Nanana21/fc-pregmod
  • Gbr6/fc-pregmod
  • RandomNecro/fc-pregmod
  • Trinidad/fc-pregmod
  • anonymousey/fc-pregmod
  • macaronideath/fc-pregmod
  • fcbleh/fc-pregmod
  • jk3000/fc-pregmod
  • Akane/fc-pregmod
  • TheBoi/fc-pregmod
  • Sheenariel/fc-pregmod
  • Metapod/multi-custom
  • Banyanael/fc-pregmod
  • frogge/fc-pregmod
  • idkkk12385/fc-pregmod
  • Mirarara/fc-pregmod
  • DeaDa/fc-pregmod-thedeal
  • CobraCommander/fc-pregmod
  • bicobus/fc-pregmod
  • CardcaptorRLH85/fc-pregmod
  • temp-ui-start/fc-pregmod
  • PresidentConvert/fc-pregmod
  • delizious/fc-pregmod
  • Ducati/fc-pregmod
  • DerangedLoner/fc-pregmod-development-fork
  • ProjectVictory/fc-pregmod
  • forecastle/fc-pregmod
  • Apathy/fc-pregmod
  • indf/fc-pregmod-dev
  • GavAndAlt/fc-pregmod
  • hagamablabla/fc-pregmod
  • Alaco/fc-pregmod
  • DCoded/fc-pregmod
  • LittlePlague/fc-pregmod
  • MissOnahole/fc-pregmod
  • ishy2317/fc-pregmod
  • nielkazama/fc-pregmod
  • Phobos/fc-pregmod
  • kraster/fc-pregmod
  • JasWS/fc-pregmod
  • FelixJS/fc-pregmod
  • NCherfaoui/fc-pregmod
  • MidnightMoose/fc-pregmod
  • jjjjjj/fc-pregmod
  • Cl0ver/fc-pregmod
  • Pythoniqus/fc-pregmod
  • JohnMolotov/fc-pregmod
  • anonymouspregmodder/fc-pregmod-anonymouspregmodder
  • Fanatey/fc-pregmod
  • Mizako/fc-pregmod
  • Nithhogg/fc-pregmod
  • Bluecoffee/fc-pregmod
380 results
Show changes
Showing
with 304 additions and 62 deletions
App.Art.GenAI.UI.QueueOverlay = function() {
// Internal State
let toggleVisible = true;
let generating = false;
// Setup containers
const container = document.createElement("div");
container.classList.add("ai-queue-overlay");
document.body.append(container);
const mainQueueSpan = document.createElement("span");
const backlogSpan = document.createElement("span");
// Export functionality
return {init: init, toggle: toggle};
function init() {
// Setup content
const spinnerSpan = document.createElement("span");
spinnerSpan.classList.add("spinner");
container.append(spinnerSpan);
container.append("(Queue: ", mainQueueSpan, " / Backlog: ", backlogSpan, ") ");
const button = document.createElement("button");
button.append("\uf410");
button.onclick = () => App.Art.GenAI.sdQueue.interrupt();
container.append(button);
// Callback
App.Art.GenAI.sdQueue.registerStatusChangeCallback(queueChangeCallback);
}
/**
* @param {ArtQueueState} status
*/
function queueChangeCallback(status) {
mainQueueSpan.textContent = String(status.mainQueueCount);
backlogSpan.textContent = String(status.backlogCount);
generating = status.active;
updateVisible();
}
/**
* @param {boolean} visible
*/
function toggle(visible) {
toggleVisible = visible;
updateVisible();
}
function updateVisible() {
const visible = V.aiQueueOverlay === 1 && toggleVisible && generating;
if (visible) {
container.classList.remove("hidden");
} else {
container.classList.add("hidden");
}
}
}();
......@@ -129,6 +129,11 @@ App.Art.GenAI.reactiveImageDB = (function() {
};
/** @type {string} */
const base64Image = await App.Art.GenAI.reactiveCache.fetchImageForSlave(slave, options.isEventImage);
if (!base64Image) {
return "";
}
return getImageData(base64Image);
}
......@@ -176,18 +181,28 @@ App.Art.GenAI.reactiveImageDB = (function() {
App.Art.GenAI.CustomPromptPart // player probably cares
];
let count = 0;
for (const DealBreaker of dealBreakers) {
const p1 = new DealBreaker(s1);
const p2 = new DealBreaker(s2);
// immediate disqualification
if (p1.positive() !== p2.positive()) {
return {
canReuse: false
};
// immediate disqualification
if (!s2.custom.aiAutoRegenExclude) {
return {
canReuse: false
};
} else {
count += 1;
}
}
}
// Count will only ever be larger 0 if slave.custom.aiAutoRegenExclude is active
if (count > 0) {
return {canReuse: true, difference: count * 10};
}
let differenceScore = 0;
// // Calculate and sum the "difference score" for each of these
......@@ -251,8 +266,8 @@ App.Art.GenAI.reactiveImageDB = (function() {
/**
* Fuzzily compares to see if all the slaves in an array are close enough to be used again
*
* @param {FC.SlaveState[]} slaveArr1
* @param {FC.SlaveState[]} slaveArr2
* @param {FC.SlaveState[]} slaveArr1 old slaves save in db
* @param {FC.SlaveState[]} slaveArr2 current slaves
*
* @returns {{canReuse: boolean, averageDifference: number}} Comparison results
*/
......@@ -301,7 +316,7 @@ App.Art.GenAI.reactiveImageDB = (function() {
const fuzzyResults = entries.map((entry) => {
return {
entry,
...fuzzyCompareSlavesArr(slaveStates, entry.slaveStates)
...fuzzyCompareSlavesArr(entry.slaveStates, slaveStates)
};
}).filter((record) => record.canReuse)
.reduce(( /** @type {ClosestEventRecord} */prevRecord, currentRecord) => {
......@@ -332,7 +347,7 @@ App.Art.GenAI.reactiveImageDB = (function() {
* @param {Partial<App.Art.GenAI.GetImageOptions>} [options] Misc options.
* Defaults: action='overview', size=App.Art.ArtSizes.SMALL, forceRegenerate: false, isEventImage: false
*
* @returns {FC.PromiseWithProgress<App.Art.GenAI.EventStore.Entry>} Promise object that resolves with the retrieved image data
* @returns {FC.PromiseWithProgress<App.Art.GenAI.EventStore.Entry | undefined>} Promise object that resolves with the retrieved image data
*/
function getImage(slaves, options = {}) {
const progressFns = [];
......@@ -370,9 +385,12 @@ App.Art.GenAI.reactiveImageDB = (function() {
const eventEntries = await db.getAllFromIndex(EVENT_STORE.path, EVENT_STORE.indicies.bySlaveIdsActions, IDBKeyRange.only([event.slaveIds, event.action]));
const {matches, averageDifference} = findClosestEvents(slaves, eventEntries, effectiveOptions);
const shouldUseCache = (averageDifference <= SIGNIFICANTLY_DIFFERENT_THRESHOLD) && !effectiveOptions.forceRegenerate;
const isExactMatch = averageDifference === 0;
const chosenEvent = matches[Math.floor(Math.random() * matches.length)];
// Use cache if an existing image is similar enough or all slaves are excluded from auto image gen
const shouldUseCache = (
averageDifference <= SIGNIFICANTLY_DIFFERENT_THRESHOLD ||
(slaves.reduce((acc, s) => acc && !!s.custom.aiAutoRegenExclude, true))
) && !effectiveOptions.forceRegenerate;
// Use the cached value
if (matches?.length > 0 && shouldUseCache) {
......@@ -380,7 +398,8 @@ App.Art.GenAI.reactiveImageDB = (function() {
return matches[Math.floor(Math.random() * matches.length)];
}
const base64Image = await generateNewImage(slaves, effectiveOptions);
const isExactMatch = averageDifference === 0;
const chosenEvent = matches[Math.floor(Math.random() * matches.length)];
/** @type {App.Art.GenAI.EventStore.Entry} */
// @ts-expect-error
......@@ -393,7 +412,12 @@ App.Art.GenAI.reactiveImageDB = (function() {
};
}
const base64Image = await generateNewImage(slaves, effectiveOptions);
if (event.action === 'overview') {
if (!base64Image) {
return undefined;
}
fullEvent.data = {
images: {
lowRes: base64Image
......
......@@ -111,6 +111,13 @@ async function fetchWithTimeout(url, timeout, options) {
* @property {[function(string): void]} rejects
*/
/**
* @typedef {object} ArtQueueState
* @property {boolean} active
* @property {number} mainQueueCount
* @property {number} backlogCount
*/
App.Art.GenAI.StableDiffusionClientQueue = class {
constructor() {
// Images for this current screen
......@@ -124,6 +131,11 @@ App.Art.GenAI.StableDiffusionClientQueue = class {
this.workingOnID = null;
/** @type {string|null} */
this.workingOnBody = null;
/**
* @type {Array<function(ArtQueueState): void>}
* @private
*/
this._statusChangeCallbacks = [];
}
resetWorkingOnProperties() {
......@@ -131,6 +143,15 @@ App.Art.GenAI.StableDiffusionClientQueue = class {
this.workingOnID = null;
}
/**
* First value is main queue, second backlog queue
*
* @param {function(ArtQueueState): void} callback
*/
registerStatusChangeCallback(callback) {
this._statusChangeCallbacks.push(callback);
}
/**
* Updates the queue counts if on the ai image settings page
*/
......@@ -148,6 +169,14 @@ App.Art.GenAI.StableDiffusionClientQueue = class {
queue.empty().append(count.toString());
}
});
const state = {
active: this.workingOnID !== null,
mainQueueCount: this.queue.length,
backlogCount: this.backlogQueue.length
};
for (const callback of this._statusChangeCallbacks) {
callback(state);
}
}
openWebSocket(top, options) {
......
......@@ -137,10 +137,8 @@ App.Art.GenAI.PromptHelpers = (() => {
/**
* Returns a string that allows the selected AI User Interface to use the LoRA model.
* Returns an empty string if App.Art.GenAI.sdClient.hasLora(loraKey) returns false.
* @see App.Art.GenAI.sdClient.hasLora
* @param {string} loraKey The LoRA key as defined in App.Art.GenAI.UI.Options.recommendedLoRAs.
* @see App.Art.GenAI.UI.Options.recommendedLoRAs
* Returns an empty string if {@link App.Art.GenAI.sdClient.hasLora}(loraKey) returns false.
* @param {string} loraKey The LoRA key as defined in {@link App.Art.GenAI.UI.Options.recommendedLoRAs}.
* @param {number} [strength=0.5] What strength the LoRA should have [default=0.5].
* @param {string} [postString=""] If provided this is added to the end of the string [default=""].
* @param {string} [preString=""] If provided this is added to the beginning of the string [default=""].
......
......@@ -976,6 +976,9 @@ App.Art.GenAI.UI.Options.aiGenerationSettings = () => {
}
}
options.addOption("Generation Queue Overlay", "aiQueueOverlay")
.addValue("Enabled", 1).on().addValue("Disabled", 0).off();
el.append(options.render());
return el;
};
......
......@@ -239,7 +239,7 @@ App.Art.GenAI.ComfyUIWorkflow = class {
promptWorkflow[30].inputs.positive = ["8", 0];
}
if (V.aiDynamicCfgEnabled) {
promptWorkflow[30].inputs.model[0] = "10";
promptWorkflow[30].inputs.model = ["10", 0];
}
}
......
This diff is collapsed.
......@@ -242,6 +242,12 @@ App.Budget.table = function(budgetType) {
...generateRowCategory("Subsidies and Barriers", "subsidiesAndBarriers")
]);
if (V.scenarios.contraceptivesBan) {
addToggle(generateRowGroup("Abortions", "ABORTIONS"), [
...generateRowCategory("Abortions", "abortions")
]);
}
// EDICTS
addToggle(generateRowGroup("Edicts", "EDICTS"), [
...generateRowCategory("Edicts", "edicts")
......
......@@ -84,14 +84,14 @@ App.UI.Cheat.cheatEditActor = function(actor) {
tabBar.addTab("Family", "family", App.Intro.editFamily(actor, true));
}
if (slave || citizen) {
tabBar.addTab("Body Mods", "body-mods", App.UI.bodyModification(actor, true));
tabBar.addTab("Body Mods", "body-mods", App.UI.bodyModification(slave ?? citizen, true));
}
if (player){
tabBar.addTab("Salon", "salon", App.UI.playerSalon(actor, true));
tabBar.addTab("Salon", "salon", App.UI.playerSalon(player, true));
} else if (!infant && !tankSlave) {
tabBar.addTab("Salon", "salon", App.UI.salon(actor, true));
}
if (V.seeExtreme) {
tabBar.addTab("Extreme", "extreme", extreme());
}
......@@ -282,9 +282,9 @@ App.UI.Cheat.cheatEditActor = function(actor) {
}
if (slave) {
const origin = App.StartingGirls.playerOrigin(actor).preview;
const origin = App.StartingGirls.playerOrigin(slave).preview;
options.addOption("Origin story", "origin", actor)
.customButton("Customize", () => App.StartingGirls.playerOrigin(actor).apply(), "")
.customButton("Customize", () => App.StartingGirls.playerOrigin(slave).apply(), "")
.showTextBox()
.addComment(origin === "" ? "No origin available" : pronounsForSlaveProp(actor, origin));
}
......@@ -1277,7 +1277,6 @@ App.UI.Cheat.cheatEditActor = function(actor) {
option.showTextBox();
options.addOption("Births", "birthsTotal", actor.counter).showTextBox().addComment(`Absolute total number of births, not just in current game.`);
options.addOption("Number of babies", "pregType", actor).showTextBox();
if (V.seeHyperPreg && V.seeExtreme && actor.broodmother === 1) {
options.addOption("Babies produced per week", "broodmotherFetuses", actor).showTextBox();
}
......@@ -1309,14 +1308,9 @@ App.UI.Cheat.cheatEditActor = function(actor) {
]);
}
}
App.Interact.ActorEdit.fetusFatherSelector(actor, options, cheat);
App.Interact.ActorEdit.fetusCount(actor, options);
if (actor.preg > 0) {
option = options.addOption("Father of child", "pregSource", actor);
if (canBreed(V.PC, actor)) {
option.addValueList([["Your child", -1], ["Not yours", 0]]);
}
option.showTextBox().addComment("Use slave's ID");
}
options.addOption("Breeding mark", "breedingMark", actor)
.addValue("No", 0).off()
.addValue("Yes", 1).on();
......@@ -2297,3 +2291,112 @@ App.UI.Cheat.cheatEditActor = function(actor) {
}
}
};
// TODO: move code shared by starting player editor, starting girls editor, and/or the cheat actor editor to here
App.Interact.ActorEdit = {};
/**
* @param {FC.HumanState} actor
* @param {InstanceType<App.UI.OptionsGroup>} options
*/
App.Interact.ActorEdit.fetusCount = (actor, options) => {
if (actor.preg > 0) {
options.addOption("Number of babies in their womb", "a", {a: actor.pregType})
.showTextBox()
.addGlobalCallback((count) => {
let change = count - actor.pregType;
actor.pregType = count;
if (change > 0) {
WombImpregnate(actor, change, actor.pregSource, 0);
} else if (change < 0) {
while (change < 0) {
change++;
WombRemoveFetus(actor, actor.womb.length -1);
}
}
}).addComment(`Setting this number to less than it already is will remove fetuses.`);
}
};
/**
* @param {FC.HumanState} actor
* @param {InstanceType<App.UI.OptionsGroup>} options
* @param {boolean} [cheat]
*/
App.Interact.ActorEdit.fetusFatherSelector = (actor, options, cheat=(V.cheatMode === 1)) => {
let option;
if (actor.preg > 0) {
// pregSource
option = options.addOption(`Set the father of their future children to`, "a", {a: actor.pregSource});
if (canBreed(V.PC, actor)) {
option.addValue(`Yourself`, V.PC.ID);
}
if (canBreed(actor, actor)) {
option.addValue(`Themself`, actor.ID);
}
option.addValueList([
["An unknown source", 0],
["Another arcology's owner", -4],
["A citizen", -2],
["An unknown rapist", -10],
]);
if (isPCCareerInCategory("servant")) {
option.addValue("Your former master", -3);
}
if (isPCCareerInCategory("escort")) {
option.addValue("One of your clients", -5);
}
getSlaves().forEach((s) => {
if (s.ID !== actor.ID && canBreed(s, actor)) {
option.addValue(SlaveFullName(s), s.ID);
}
});
option.pulldown();
option.addGlobalCallback(
/** @param {FC.HumanID} fatherID */
(fatherID) => {
actor.pregSource = fatherID;
}
);
if (cheat) {
option.showTextBox();
}
// existing children
option = options.addOption(`Set the father of their existing child${actor.womb.length > 1 ? "ren" : ""} to`, "a", {a: -10532052305});
option.addValue(`Don't change`, -10532052305);
if (canBreed(V.PC, actor)) {
option.addValue(`Yourself`, V.PC.ID);
}
if (canBreed(actor, actor)) {
option.addValue(`Themself`, actor.ID);
}
option.addValueList([
["An unknown source", 0],
["Another arcology's owner", -4],
["A citizen", -2],
["An unknown rapist", -10],
]);
if (isPCCareerInCategory("servant")) {
option.addValue("Your former master", -3);
}
if (isPCCareerInCategory("escort")) {
option.addValue("One of your clients", -5);
}
getSlaves().forEach((s) => {
if (s.ID !== actor.ID && canBreed(s, actor)) {
option.addValue(SlaveFullName(s), s.ID);
}
});
option.pulldown();
option.addGlobalCallback(
/** @param {FC.HumanID} fatherID */
(fatherID) => {
WombForceFatherID(actor, fatherID);
}
);
if (cheat) {
option.showTextBox();
}
}
};
/**
* @deprecated we are working on moving this to App.UI.Cheat.cheatEditActor
* @see App.UI.Cheat.cheatEditActor
* @deprecated we are working on moving this to {@link App.UI.Cheat.cheatEditActor}
* TODO: @franklygeorge finish moving this
* @param {FC.SlaveState} slave
*/
App.UI.SlaveInteract.cheatEditSlave = function(slave) {
......
/** @file holds functions that help manage data. */
/**
* @deprecated use `App.Utils.assignMissingDefaults(obj, props)` instead
* @see App.Utils.assignMissingDefaults
* @deprecated use {@link App.Utils.assignMissingDefaults}(obj, props) instead
* TODO:@franklygeorge replace this with `App.Utils.assignMissingDefaults`
* Adds properties from `props` to `obj` if they don't already exist
* @template {object} T
......@@ -52,8 +51,7 @@ App.Utils.assignMissingDefaults = (obj, ...defaultObjs) => {
};
/**
* @deprecated use `App.Utils.overwriteWithDefaults(obj, props)` instead
* @see App.Utils.overwriteWithDefaults
* @deprecated use {@link App.Utils.overwriteWithDefaults}(obj, props) instead
* TODO:@franklygeorge replace this with `App.Utils.overwriteWithDefaults(obj, props)`
* Adds properties from `props` to `obj`, overwriting the existing values
* @param {object} obj
......
......@@ -10,8 +10,7 @@
* With the exception of the underdash the naming scheme is the same as the rest of FC's files.
*
* Each patch file should have a single call to `App.Patch.register()` with a `App.Patch.Utils.PatchRecord` object as the only argument.
* @see App.Patch.register
* @see App.Patch.Utils.PatchRecord
* See {@link App.Patch.register} and {@link App.Patch.Utils.PatchRecord}
*
* Each function defined by `App.Patch.Utils.PatchRecord` is optional, only use the ones you need.
* The definitions of each function and what it is used for can be found below starting on the line with `====== Functions and their use ======`.
......@@ -21,9 +20,8 @@
* There can only be one patch for each `releaseID`.
* `descriptionOfChanges` should be a string that describes what was changed to cause this patch to be needed.
*
* There are some helpful functions located in `/src/data/dataUtils.js` and under `App.Utils`.
* You should use `App.Patch.log()` to report what you are doing in each patch function.
* @see App.Patch.Log
* There are some helpful functions located in `/src/data/dataUtils.js` and under {@link App.Utils}.
* You should use {@link App.Patch.log}() to report what you are doing in each patch function.
*
* ====== Patch functions and their use ======
*
......
App.Patch.register({
releaseID: 1280,
descriptionOfChanges: "Adds controllers for fertKnown and pregKnown as well as the showcase policy",
pre: (div) => {
V.menstruationKnown = 0;
V.pregnancyKnown = 0;
V.boughtItem.toys.chastity = 1;
V.policies.contraceptivesBan = 0;
V.scenarios = {};
V.scenarios.contraceptivesBan = 0;
},
});
......@@ -505,6 +505,24 @@ App.Verify.I.arcologies = () => {
}
};
/**
* @type {App.Verify.Utils.FunctionGameVariables}
*/
App.Verify.I.mods = () => {
App.Mods.SecExp.Obj.Init();
};
/**
* @type {App.Verify.Utils.FunctionGameVariables}
*/
App.Verify.I.pit = () => {
if (V.pit) {
if (getSlave(V.pit.slaveFightingBodyguard) === undefined) {
V.pit.slaveFightingBodyguard = null;
}
}
};
/**
* @type {App.Verify.Utils.FunctionGameVariables}
*/
......
......@@ -193,6 +193,7 @@ App.Verify.I.humanPregnancy = (actor, location) => {
actor.preg = 0; // no contraceptives for prepubescent humans
}
actor.fertPeak = Math.clamp(+actor.fertPeak, -10, 10) ?? 0;
actor.fertLate = Math.clamp(+actor.fertLate, -10, 10) ?? 0;
// @ts-expect-error Type 'number' is not assignable to type ...
actor.broodmother = Math.clamp(+actor.broodmother, 0, 3) ?? 0;
actor.broodmotherFetuses = Math.max(+actor.broodmotherFetuses, 0) ?? 0;
......
......@@ -98,6 +98,8 @@ App.Verify.instructions = {
facilityNursery: App.Verify.I.facilityNursery,
futureSocieties: App.Verify.I.futureSocieties,
arcologies: App.Verify.I.arcologies,
mods: App.Verify.I.mods,
pit: App.Verify.I.pit,
jobIDMap: App.Verify.I.jobIDMap,
},
slaveState: {
......
......@@ -247,6 +247,12 @@ globalThis.endWeek = (function() {
}
if (isHorny(V.PC)) {
V.PC.need *= 2;
} else if (V.menstruation && isFertile(V.PC, true)) {
if (V.PC.fertPeak === 0) {
V.PC.need *= 1.10;
} else if (V.PC.fertPeak === 2) {
V.PC.need *= 0.75;
}
}
if (V.PC.balls > 0 && V.PC.pubertyXY === 1 && V.PC.physicalAge <= (V.PC.pubertyAgeXY + 1) && (V.PC.physicalAge > V.PC.pubertyAgeXY) && V.PC.physicalAge < 18) {
V.PC.need *= 1.25;
......
......@@ -35,19 +35,13 @@ App.Events.SEDeath = class SEDeath extends App.Events.BaseEvent {
const deceased = getSlave(id);
if (deceased) {
App.UI.DOM.appendNewElement("p", node, death(deceased, deathType));
node.append(sectionBreak());
node.append(App.UI.sectionBreak());
removeSlave(deceased, {dead: true});
}
}
V.slaveDeath = new Map();
function sectionBreak() {
const hr = document.createElement("hr");
hr.style.margin = "0";
return hr;
}
/**
*
* @param {FC.SlaveState} slave
......
......@@ -21,7 +21,7 @@ App.Events.SEExpiration = class SEExpiration extends App.Events.BaseEvent {
const slave = getSlave(id);
if (slave) {
App.UI.DOM.appendNewElement("div", node, expire(slave));
node.append(sectionBreak());
node.append(App.UI.sectionBreak());
}
}
const oldHandler = App.Utils.PassageSwitchHandler.get();
......@@ -34,12 +34,6 @@ App.Events.SEExpiration = class SEExpiration extends App.Events.BaseEvent {
oldHandler();
});
function sectionBreak() {
const hr = document.createElement("hr");
hr.style.margin = "0";
return hr;
}
/**
*
* @param {FC.SlaveState} slave
......
......@@ -19,15 +19,9 @@ App.Events.SERetire = class SERetire extends App.Events.BaseEvent {
const slave = getSlave(id);
if (slave) {
App.UI.DOM.appendNewElement("div", node, App.Events.retire(slave));
node.append(sectionBreak());
node.append(App.UI.sectionBreak());
}
}
function sectionBreak() {
const hr = document.createElement("hr");
hr.style.margin = "0";
return hr;
}
}
};
......