Fix v14 Vevaphon: debounce createItem hook + try/catch guard on Ebb enforcement deletes

This commit is contained in:
2026-04-15 11:14:45 +01:00
parent 9fb7867069
commit 4a5561a82f
2 changed files with 20 additions and 5 deletions
+9 -3
View File
@@ -5037,13 +5037,19 @@ export class MothershipActor extends Actor {
};
await this.update(updateData);
const validIds = restrictedIds.filter(id => this.items.get(id) !== undefined);
let removed = 0;
if (validIds.length) {
await this.deleteEmbeddedDocuments("Item", validIds);
try {
await this.deleteEmbeddedDocuments("Item", validIds);
removed = validIds.length;
} catch (err) {
// Concurrent enforcement calls may have already deleted these items — safe to ignore
}
}
if (notify && validIds.length) {
if (notify && removed) {
ui.notifications.warn(`${this.name} is not an Ebb user. Restricted Ebb skills and abilities were removed.`);
}
return { removed: validIds.length };
return { removed };
}
const currentMax = Math.max(0, Number(this.system?.sla?.flux?.max ?? 0) || 0);
+11 -2
View File
@@ -144,11 +144,20 @@ Hooks.once('init', async function () {
await SLADrugSystem.handleEffectDeleted(effect, options);
});
Hooks.on("createItem", async (item) => {
// Debounce map: actorId → pending timeout handle.
// Prevents enforceSlaEbbEligibility from being called once per item when the
// character generator creates many items in rapid succession (each createItem
// hook call would otherwise race to delete the same Ebb items concurrently).
const _pendingEbbEnforcement = new Map();
Hooks.on("createItem", (item) => {
const actor = item.parent;
if (!actor || actor.type !== "character" || typeof actor.enforceSlaEbbEligibility !== "function") return;
if (actor.isSlaEbbUser?.()) return;
await actor.enforceSlaEbbEligibility({ notify: true, refillFlux: false });
if (_pendingEbbEnforcement.has(actor.id)) clearTimeout(_pendingEbbEnforcement.get(actor.id));
_pendingEbbEnforcement.set(actor.id, setTimeout(async () => {
_pendingEbbEnforcement.delete(actor.id);
await actor.enforceSlaEbbEligibility({ notify: true, refillFlux: false });
}, 300));
});
Hooks.on("updateActor", async (actor, changes, options) => {