diff --git a/devTools/types/FC/RA.d.ts b/devTools/types/FC/RA.d.ts index 38b1bf69b2e63a1a06d4f3b13274054e2c0f15d4..2fe9e2ab523acd4ab854c2b89cc07703e6fa9398 100644 --- a/devTools/types/FC/RA.d.ts +++ b/devTools/types/FC/RA.d.ts @@ -182,6 +182,10 @@ declare namespace FC { labelTagsClear: boolean; choosesOwnClothes: 0 | 1; pronoun: number; + posePrompt: string; + positivePrompt: string; + negativePrompt: string; + overridePrompts: boolean; } interface Rule { diff --git a/src/js/DefaultRules.js b/src/js/DefaultRules.js index 1d531d749c144c914969e9aa59ed44e9373eabc8..c348111e4ae52d4ada65d4b47671ee696f030e1d 100644 --- a/src/js/DefaultRules.js +++ b/src/js/DefaultRules.js @@ -81,6 +81,7 @@ globalThis.DefaultRules = function(slave) { ProcessPorn(slave, rule); ProcessLabel(slave, rule); ProcessOther(slave, rule); + ProcessPrompts(slave, rule); return r; @@ -3228,6 +3229,91 @@ globalThis.DefaultRules = function(slave) { } } + /** + * @param {App.Entity.SlaveState} slave + * @param {FC.RA.RuleSetters} rule + */ + function ProcessPrompts(slave, rule) { + /** + * @param {string[]} newPrompts + * @param {string[]} oldPrompts + */ + function promptsEqual(newPrompts, oldPrompts) { + if (!rule.overridePrompts) { // if using append + no new prompts + return oldPrompts.includesAll(newPrompts); + } + return newPrompts.slice(0).sort().toString() === oldPrompts.slice(0).sort().toString(); + } + + /** + * @param {string} promptField "positive","negative" + */ + function myFunc(promptField) { + let newPrompts; + let oldPrompts; + let override; + + if (rule.overridePrompts) { + override = 'overwritten'; + } else { + override = 'added'; + } + + if (promptField === "positive") { + newPrompts = rule.positivePrompt.split(/ *, */g); + oldPrompts = slave.custom.aiPrompts.positive.split(/ *, */g); + } else { + newPrompts = rule.negativePrompt.split(/ *, */g); + oldPrompts = slave.custom.aiPrompts.negative.split(/ *, */g); + } + if (promptsEqual(newPrompts, oldPrompts)) { + return; + } + if (!rule.overridePrompts){ + if (oldPrompts.includesAny(newPrompts)) { // if appending and old prompts have overlap with new prompts + oldPrompts = oldPrompts.filter(value => !newPrompts.includes(value)); + } + newPrompts = newPrompts.concat(oldPrompts); + } + if (promptField === "positive") { + slave.custom.aiPrompts.positive = newPrompts.toString(); + // toString is used partially as a lazy solution and as a way to differentiate prompts added by rules assistant + message(`${slave.slaveName} has had positive prompts ${override}`, sourceRecord.positivePrompt); + } else { + slave.custom.aiPrompts.negative = newPrompts.toString(); + // toString is used partially as a lazy solution and as a way to differentiate prompts added by rules assistant + message(`${slave.slaveName} has had negative prompts ${override}`, sourceRecord.negativePrompt); + } + } + + // custom prompts setup + if (slave.custom.aiPrompts == null) { + slave.custom.aiPrompts = new App.Entity.SlaveCustomAIPrompts(); + // if the player has yet to set custom values for the slave a null type error is passed + slave.custom.aiPrompts.pose = ''; + slave.custom.aiPrompts.positive = ''; + slave.custom.aiPrompts.negative = ''; + } + + // custom pose prompt + if (rule.posePrompt != null && rule.posePrompt !== '') { + if (slave.custom.aiPrompts.pose !== rule.posePrompt) { + slave.custom.aiPrompts.pose = rule.posePrompt; + message(`${slave.slaveName} has had ${his} posture set.`, sourceRecord.posePrompt); + } + } + + // custom positive prompts + if (rule.positivePrompt != null && rule.positivePrompt !== '') { + myFunc("positive"); + } + + // custom negative prompts + if (rule.negativePrompt != null && rule.negativePrompt !== '') { + myFunc("negative"); + } + } + /** * @param {string} text * @param {string|string[]} [origin] diff --git a/src/js/rulesAssistant.js b/src/js/rulesAssistant.js index 3b1a393314fc6efd9bf7a110b30f2af0c2c6b370..c9535287a4d0edfdebb87fb4d68d9754398b80cb 100644 --- a/src/js/rulesAssistant.js +++ b/src/js/rulesAssistant.js @@ -299,6 +299,10 @@ App.RA.newRule = function() { inflationType: null, labelTagsClear: null, pronoun: null, + posePrompt: null, + positivePrompt: null, + negativePrompt: null, + overridePrompts: null, }; } diff --git a/src/js/rulesAssistantOptions.js b/src/js/rulesAssistantOptions.js index 6ee116f948f9113cffdb91dd6f8c344894875cf5..0aa138934c36a56ad14e62f50777df7ae3d12324 100644 --- a/src/js/rulesAssistantOptions.js +++ b/src/js/rulesAssistantOptions.js @@ -1584,6 +1584,12 @@ App.RA.options = (function() { if (V.diversePronouns === 1) { this.appendChild(new PronounList()); } + if (V.imageChoice === 6) { // If using AI generated images + this.appendChild(new OverridePosePrompt()); + this.appendChild(new OverridePromptSwitch()); + this.appendChild(new AddCustomPosPrompt()); + this.appendChild(new AddCustomNegPrompt()); + } } } @@ -4125,6 +4131,38 @@ App.RA.options = (function() { } } + class OverridePosePrompt extends StringEditor { + constructor() { + super("Override pose prompt", [], true, false); + this.setValue(current_rule.set.posePrompt); + this.onchange = (value) => current_rule.set.posePrompt = value; + } + } + + class AddCustomPosPrompt extends StringEditor { + constructor() { + super("Add custom positive prompt(s) to slave", [], true, false); + this.setValue(current_rule.set.positivePrompt); + this.onchange = (value) => current_rule.set.positivePrompt = value; + } + } + + class AddCustomNegPrompt extends StringEditor { + constructor() { + super("Add custom negative prompt(s) to slave", [], true, false); + this.setValue(current_rule.set.negativePrompt); + this.onchange = (value) => current_rule.set.negativePrompt = value; + } + } + + class OverridePromptSwitch extends BooleanSwitch { + constructor() { + super("Rules Assistant prompts override (Applies to both)", [false, true]); + this.setValue(current_rule.set.overridePrompts); + this.onchange = (value) => current_rule.set.overridePrompts = value; + } + } + class SkinColorList extends ListSelector { constructor() { const items = [