mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Fix off-by-one in timed effects. Add protected status
This commit is contained in:
@@ -105,6 +105,7 @@ const MAX_SCAN_DEPTH = 1000;
|
|||||||
* @property {number} hash Hash of the entry that triggered the effect
|
* @property {number} hash Hash of the entry that triggered the effect
|
||||||
* @property {number} start The chat index where the effect starts
|
* @property {number} start The chat index where the effect starts
|
||||||
* @property {number} end The chat index where the effect ends
|
* @property {number} end The chat index where the effect ends
|
||||||
|
* @property {boolean} protected The protected effect can't be removed if the chat does not advance
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -362,11 +363,6 @@ class WorldInfoTimedEffects {
|
|||||||
*/
|
*/
|
||||||
#entries = [];
|
#entries = [];
|
||||||
|
|
||||||
/**
|
|
||||||
* Set of entries to ignore chat advancement requirement for.
|
|
||||||
*/
|
|
||||||
#entryIgnoreAdvancement = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buffer for active timed effects.
|
* Buffer for active timed effects.
|
||||||
* @type {Record<TimedEffectType, WIScanEntry[]>}
|
* @type {Record<TimedEffectType, WIScanEntry[]>}
|
||||||
@@ -392,12 +388,11 @@ class WorldInfoTimedEffects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const key = this.#getEntryKey(entry);
|
const key = this.#getEntryKey(entry);
|
||||||
const effect = this.#getEntryTimedEffect(entry, 'cooldown');
|
const effect = this.#getEntryTimedEffect('cooldown', entry, true);
|
||||||
chat_metadata.timedWorldInfo.cooldown[key] = effect;
|
chat_metadata.timedWorldInfo.cooldown[key] = effect;
|
||||||
console.log(`Adding cooldown entry ${key} on ended sticky: start=${effect.start}, end=${effect.end}`);
|
console.log(`Adding cooldown entry ${key} on ended sticky: start=${effect.start}, end=${effect.end}, protected=${effect.protected}`);
|
||||||
// Set the cooldown immediately for this evaluation
|
// Set the cooldown immediately for this evaluation
|
||||||
this.#buffer['cooldown'].push(entry);
|
this.#buffer.cooldown.push(entry);
|
||||||
this.#entryIgnoreAdvancement.push(entry);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -470,27 +465,20 @@ class WorldInfoTimedEffects {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a timed effect for a WI entry.
|
* Gets a timed effect for a WI entry.
|
||||||
* @param {WIScanEntry} entry WI entry
|
|
||||||
* @param {TimedEffectType} type Type of timed effect
|
* @param {TimedEffectType} type Type of timed effect
|
||||||
|
* @param {WIScanEntry} entry WI entry
|
||||||
|
* @param {boolean} isProtected If the effect should be protected
|
||||||
* @returns {WITimedEffect} Timed effect for the entry
|
* @returns {WITimedEffect} Timed effect for the entry
|
||||||
*/
|
*/
|
||||||
#getEntryTimedEffect(entry, type) {
|
#getEntryTimedEffect(type, entry, isProtected) {
|
||||||
return {
|
return {
|
||||||
hash: this.#getEntryHash(entry),
|
hash: this.#getEntryHash(entry),
|
||||||
start: this.#chat.length,
|
start: this.#chat.length,
|
||||||
end: this.#chat.length + Number(entry[type]),
|
end: this.#chat.length + Number(entry[type]),
|
||||||
|
protected: !!isProtected,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets if the entry should be ignored for chat advancement requirement.
|
|
||||||
* @param {WIScanEntry} entry WI entry
|
|
||||||
* @returns {boolean} True if the entry should be ignored
|
|
||||||
*/
|
|
||||||
#isChatAdvancementIgnored(entry) {
|
|
||||||
return entry && this.#entryIgnoreAdvancement.some(x => this.#getEntryHash(x) === this.#getEntryHash(entry));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes entries for a given type of timed effect.
|
* Processes entries for a given type of timed effect.
|
||||||
* @param {TimedEffectType} type Identifier for the type of timed effect
|
* @param {TimedEffectType} type Identifier for the type of timed effect
|
||||||
@@ -504,7 +492,7 @@ class WorldInfoTimedEffects {
|
|||||||
console.log(`Processing ${type} entry ${key}`, value);
|
console.log(`Processing ${type} entry ${key}`, value);
|
||||||
const entry = this.#entries.find(x => String(this.#getEntryHash(x)) === String(value.hash));
|
const entry = this.#entries.find(x => String(this.#getEntryHash(x)) === String(value.hash));
|
||||||
|
|
||||||
if (this.#chat.length <= Number(value.start) && !this.#isChatAdvancementIgnored(entry)) {
|
if (this.#chat.length <= Number(value.start) && !value.protected) {
|
||||||
console.log(`Removing ${type} entry ${key} from timedWorldInfo: chat not advanced`, value);
|
console.log(`Removing ${type} entry ${key} from timedWorldInfo: chat not advanced`, value);
|
||||||
delete chat_metadata.timedWorldInfo[type][key];
|
delete chat_metadata.timedWorldInfo[type][key];
|
||||||
continue;
|
continue;
|
||||||
@@ -512,7 +500,7 @@ class WorldInfoTimedEffects {
|
|||||||
|
|
||||||
// Missing entries (they could be from another character's lorebook)
|
// Missing entries (they could be from another character's lorebook)
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
if (this.#chat.length > Number(value.end)) {
|
if (this.#chat.length >= Number(value.end)) {
|
||||||
console.log(`Removing ${type} entry from timedWorldInfo: entry not found and interval passed`, entry);
|
console.log(`Removing ${type} entry from timedWorldInfo: entry not found and interval passed`, entry);
|
||||||
delete chat_metadata.timedWorldInfo[type][key];
|
delete chat_metadata.timedWorldInfo[type][key];
|
||||||
}
|
}
|
||||||
@@ -526,7 +514,7 @@ class WorldInfoTimedEffects {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.#chat.length > Number(value.end)) {
|
if (this.#chat.length >= Number(value.end)) {
|
||||||
console.log(`Removing ${type} entry from timedWorldInfo: ${type} interval passed`, entry);
|
console.log(`Removing ${type} entry from timedWorldInfo: ${type} interval passed`, entry);
|
||||||
delete chat_metadata.timedWorldInfo[type][key];
|
delete chat_metadata.timedWorldInfo[type][key];
|
||||||
if (typeof onEnded === 'function') {
|
if (typeof onEnded === 'function') {
|
||||||
@@ -577,10 +565,10 @@ class WorldInfoTimedEffects {
|
|||||||
const key = this.#getEntryKey(entry);
|
const key = this.#getEntryKey(entry);
|
||||||
|
|
||||||
if (!chat_metadata.timedWorldInfo[type][key]) {
|
if (!chat_metadata.timedWorldInfo[type][key]) {
|
||||||
const effect = this.#getEntryTimedEffect(entry, type);
|
const effect = this.#getEntryTimedEffect(type, entry, false);
|
||||||
chat_metadata.timedWorldInfo[type][key] = effect;
|
chat_metadata.timedWorldInfo[type][key] = effect;
|
||||||
|
|
||||||
console.log(`Adding ${type} entry ${key}: start=${effect.start}, end=${effect.end}`);
|
console.log(`Adding ${type} entry ${key}: start=${effect.start}, end=${effect.end}, protected=${effect.protected}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -610,9 +598,9 @@ class WorldInfoTimedEffects {
|
|||||||
delete chat_metadata.timedWorldInfo[type][key];
|
delete chat_metadata.timedWorldInfo[type][key];
|
||||||
|
|
||||||
if (newState) {
|
if (newState) {
|
||||||
const effect = this.#getEntryTimedEffect(entry, type);
|
const effect = this.#getEntryTimedEffect(type, entry, false);
|
||||||
chat_metadata.timedWorldInfo[type][key] = effect;
|
chat_metadata.timedWorldInfo[type][key] = effect;
|
||||||
console.log(`Adding ${type} entry ${key}: start=${effect.start}, end=${effect.end}`);
|
console.log(`Adding ${type} entry ${key}: start=${effect.start}, end=${effect.end}, protected=${effect.protected}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,7 +634,6 @@ class WorldInfoTimedEffects {
|
|||||||
for (const buffer of Object.values(this.#buffer)) {
|
for (const buffer of Object.values(this.#buffer)) {
|
||||||
buffer.splice(0, buffer.length);
|
buffer.splice(0, buffer.length);
|
||||||
}
|
}
|
||||||
this.#entryIgnoreAdvancement.splice(0, this.#entryIgnoreAdvancement.length);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user