Add character specific locks for WI and LB (#1170)
* World Info: Add character locking for entries With the addition of depth, world info has become more important than ever. However, there is a conflict that can occur when using multiple world info or lorebooks on a character. Add the ability to lock entries to a specific character (or characters) if needed. This allows for adequate separation especially when there are character cards each with their separate lorebooks that build off of a core lorebook. Signed-off-by: kingbri <bdashore3@proton.me> * World Info: Add entry-specific character exclusions This is the opposite of locking an entry to a specific character. Exclusions allows the entry to get included for everyone except the specified characters in the list. Signed-off-by: kingbri <bdashore3@proton.me> --------- Signed-off-by: kingbri <bdashore3@proton.me>
This commit is contained in:
parent
d9b2b9f753
commit
5421925d6c
|
@ -3930,6 +3930,18 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex-container flexFlowColumn flexNoGap wide100p">
|
||||||
|
<label for="characterFilter" class="range-block-title justifyLeft">
|
||||||
|
<small data-i18n="Filter to Character(s)">Filter to Character(s)</small>
|
||||||
|
</label>
|
||||||
|
<div class="range-block-range">
|
||||||
|
<select name="characterFilter" multiple>
|
||||||
|
<option value="">
|
||||||
|
<span data-i18n="-- Characters not found --">-- Characters not found --</span>
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div name="WIEntryBottomControls" class="flex-container flex1 justifySpaceBetween world_entry_form_horizontal">
|
<div name="WIEntryBottomControls" class="flex-container flex1 justifySpaceBetween world_entry_form_horizontal">
|
||||||
<div class="flex-container flexFlowColumn flexNoGap wi-enter-footer-text ">
|
<div class="flex-container flexFlowColumn flexNoGap wi-enter-footer-text ">
|
||||||
<label class="checkbox flex-container">
|
<label class="checkbox flex-container">
|
||||||
|
@ -3958,6 +3970,12 @@
|
||||||
Non-recursable
|
Non-recursable
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
<label class="checkbox flex-container alignitemscenter">
|
||||||
|
<input type="checkbox" name="character_exclusion" />
|
||||||
|
<span data-i18n="Character Exclusion">
|
||||||
|
Character Exclusion
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|
|
@ -449,6 +449,86 @@ function getWorldEntry(name, data, entry) {
|
||||||
.prop("selected", true)
|
.prop("selected", true)
|
||||||
.trigger("input");
|
.trigger("input");
|
||||||
|
|
||||||
|
// Character filter
|
||||||
|
const characterFilterLabel = template.find(`label[for="characterFilter"] > small`);
|
||||||
|
characterFilterLabel.text(!!(entry.characterFilter?.isExclude) ? "Exclude Character(s)" : "Filter to Character(s)");
|
||||||
|
|
||||||
|
// exclude characters checkbox
|
||||||
|
const characterExclusionInput = template.find(`input[name="character_exclusion"]`);
|
||||||
|
characterExclusionInput.data("uid", entry.uid);
|
||||||
|
characterExclusionInput.on("input", function () {
|
||||||
|
const uid = $(this).data("uid");
|
||||||
|
const value = $(this).prop("checked");
|
||||||
|
characterFilterLabel.text(value ? "Exclude Character(s)" : "Filter to Character(s)");
|
||||||
|
if (data.entries[uid].characterFilter) {
|
||||||
|
if (!value && data.entries[uid].characterFilter.names.length === 0) {
|
||||||
|
delete data.entries[uid].characterFilter;
|
||||||
|
} else {
|
||||||
|
data.entries[uid].characterFilter.isExclude = value
|
||||||
|
}
|
||||||
|
} else if (value) {
|
||||||
|
Object.assign(
|
||||||
|
data.entries[uid],
|
||||||
|
{
|
||||||
|
characterFilter: {
|
||||||
|
isExclude: true,
|
||||||
|
names: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
setOriginalDataValue(data, uid, "character_filter", data.entries[uid].characterFilter);
|
||||||
|
saveWorldInfo(name, data);
|
||||||
|
});
|
||||||
|
characterExclusionInput.prop("checked", entry.characterFilter?.isExclude ?? false).trigger("input");
|
||||||
|
|
||||||
|
const characterFilter = template.find(`select[name="characterFilter"]`);
|
||||||
|
characterFilter.data("uid", entry.uid)
|
||||||
|
const deviceInfo = getDeviceInfo();
|
||||||
|
if (deviceInfo && deviceInfo.device.type === 'desktop') {
|
||||||
|
$(characterFilter).select2({
|
||||||
|
width: '100%',
|
||||||
|
placeholder: 'All characters will pull from this entry.',
|
||||||
|
allowClear: true,
|
||||||
|
closeOnSelect: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const characters = getContext().characters;
|
||||||
|
characters.forEach((character) => {
|
||||||
|
const option = document.createElement('option');
|
||||||
|
const name = character.avatar.replace(/\.[^/.]+$/, "") ?? character.name
|
||||||
|
option.innerText = name
|
||||||
|
option.selected = entry.characterFilter?.names.includes(name)
|
||||||
|
characterFilter.append(option)
|
||||||
|
});
|
||||||
|
|
||||||
|
characterFilter.on('mousedown change', async function (e) {
|
||||||
|
// If there's no world names, don't do anything
|
||||||
|
if (world_names.length === 0) {
|
||||||
|
e.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uid = $(this).data("uid");
|
||||||
|
const value = $(this).val();
|
||||||
|
if ((!value || value?.length === 0) && !data.entries[uid].characterFilter?.isExclude) {
|
||||||
|
delete data.entries[uid].characterFilter;
|
||||||
|
} else {
|
||||||
|
Object.assign(
|
||||||
|
data.entries[uid],
|
||||||
|
{
|
||||||
|
characterFilter: {
|
||||||
|
isExclude: data.entries[uid].characterFilter?.isExclude ?? false,
|
||||||
|
names: value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
setOriginalDataValue(data, uid, "character_filter", data.entries[uid].characterFilter);
|
||||||
|
saveWorldInfo(name, data);
|
||||||
|
});
|
||||||
|
|
||||||
// keysecondary
|
// keysecondary
|
||||||
const keySecondaryInput = template.find('textarea[name="keysecondary"]');
|
const keySecondaryInput = template.find('textarea[name="keysecondary"]');
|
||||||
keySecondaryInput.data("uid", entry.uid);
|
keySecondaryInput.data("uid", entry.uid);
|
||||||
|
@ -689,6 +769,7 @@ function getWorldEntry(name, data, entry) {
|
||||||
});
|
});
|
||||||
disableInput.prop("checked", entry.disable).trigger("input");
|
disableInput.prop("checked", entry.disable).trigger("input");
|
||||||
|
|
||||||
|
// exclude recursion
|
||||||
const excludeRecursionInput = template.find('input[name="exclude_recursion"]');
|
const excludeRecursionInput = template.find('input[name="exclude_recursion"]');
|
||||||
excludeRecursionInput.data("uid", entry.uid);
|
excludeRecursionInput.data("uid", entry.uid);
|
||||||
excludeRecursionInput.on("input", function () {
|
excludeRecursionInput.on("input", function () {
|
||||||
|
@ -1020,6 +1101,16 @@ async function checkWorldInfo(chat, maxContext) {
|
||||||
let activatedNow = new Set();
|
let activatedNow = new Set();
|
||||||
|
|
||||||
for (let entry of sortedEntries) {
|
for (let entry of sortedEntries) {
|
||||||
|
// Check if this entry applies to the character or if it's excluded
|
||||||
|
if (entry.characterFilter && entry.characterFilter?.names.length > 0) {
|
||||||
|
const nameIncluded = entry.characterFilter.names.includes(getCharaFilename());
|
||||||
|
const filtered = entry.characterFilter.isExclude ? nameIncluded : !nameIncluded
|
||||||
|
|
||||||
|
if (filtered) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (failedProbabilityChecks.has(entry)) {
|
if (failedProbabilityChecks.has(entry)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue