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 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 class="flex-container flexFlowColumn flexNoGap wi-enter-footer-text ">
|
||||
<label class="checkbox flex-container">
|
||||
|
@ -3958,6 +3970,12 @@
|
|||
Non-recursable
|
||||
</span>
|
||||
</label>
|
||||
<label class="checkbox flex-container alignitemscenter">
|
||||
<input type="checkbox" name="character_exclusion" />
|
||||
<span data-i18n="Character Exclusion">
|
||||
Character Exclusion
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
|
|
|
@ -449,6 +449,86 @@ function getWorldEntry(name, data, entry) {
|
|||
.prop("selected", true)
|
||||
.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
|
||||
const keySecondaryInput = template.find('textarea[name="keysecondary"]');
|
||||
keySecondaryInput.data("uid", entry.uid);
|
||||
|
@ -689,6 +769,7 @@ function getWorldEntry(name, data, entry) {
|
|||
});
|
||||
disableInput.prop("checked", entry.disable).trigger("input");
|
||||
|
||||
// exclude recursion
|
||||
const excludeRecursionInput = template.find('input[name="exclude_recursion"]');
|
||||
excludeRecursionInput.data("uid", entry.uid);
|
||||
excludeRecursionInput.on("input", function () {
|
||||
|
@ -1020,6 +1101,16 @@ async function checkWorldInfo(chat, maxContext) {
|
|||
let activatedNow = new Set();
|
||||
|
||||
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)) {
|
||||
continue;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue