Fix off-by-one in timed effects. Add protected status

This commit is contained in:
Cohee
2024-06-24 11:51:04 +00:00
parent e7ab43527a
commit 4b58a822db

View File

@@ -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);
} }
} }