diff --git a/src/controllers/api/updateQuestController.ts b/src/controllers/api/updateQuestController.ts index 0ca4d857..5bae315a 100644 --- a/src/controllers/api/updateQuestController.ts +++ b/src/controllers/api/updateQuestController.ts @@ -5,6 +5,7 @@ import type { IUpdateQuestRequest } from "../../services/questService.ts"; import { updateQuestKey } from "../../services/questService.ts"; import { getInventory } from "../../services/inventoryService.ts"; import type { IInventoryChanges } from "../../types/purchaseTypes.ts"; +import { sendWsBroadcastTo } from "../../services/wsService.ts"; export const updateQuestController: RequestHandler = async (req, res) => { const accountId = parseString(req.query.accountId); @@ -29,4 +30,5 @@ export const updateQuestController: RequestHandler = async (req, res) => { await inventory.save(); res.send(updateQuestResponse); + sendWsBroadcastTo(accountId, { update_inventory: true }); }; diff --git a/src/controllers/custom/manageQuestsController.ts b/src/controllers/custom/manageQuestsController.ts index 25c80cd0..efd1ec63 100644 --- a/src/controllers/custom/manageQuestsController.ts +++ b/src/controllers/custom/manageQuestsController.ts @@ -115,7 +115,7 @@ export const manageQuestsController: RequestHandler = async (req, res) => { if (stage > 0) { await giveKeyChainStageTriggered(inventory, { KeyChain: questKey.ItemType, - ChainStage: stage - 1 + ChainStage: stage }); } } diff --git a/src/services/itemDataService.ts b/src/services/itemDataService.ts index 0b33a1a1..8cf18d03 100644 --- a/src/services/itemDataService.ts +++ b/src/services/itemDataService.ts @@ -210,7 +210,7 @@ export const getKeyChainItems = ({ KeyChain, ChainStage }: IKeyChainRequest): st throw new Error(`KeyChain ${KeyChain} does not contain chain stages`); } - const keyChainStage = chainStages[ChainStage]; + const keyChainStage = chainStages[ChainStage - 1]; // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!keyChainStage) { throw new Error(`KeyChainStage ${ChainStage} not found`); diff --git a/src/services/questService.ts b/src/services/questService.ts index 02bf81b7..cc9449fd 100644 --- a/src/services/questService.ts +++ b/src/services/questService.ts @@ -68,25 +68,31 @@ export const updateQuestStage = ( throw new Error(`Progress should always exist when giving keychain triggered items or messages`); } - const questStage = quest.Progress[ChainStage]; + ChainStage -= 1; // They are 1-indexed in the client, but we need 0-indexing - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - if (!questStage) { - const questStageIndex = - quest.Progress.push({ - c: questStageUpdate.c ?? 0, - i: questStageUpdate.i ?? false, - m: questStageUpdate.m ?? false, - b: questStageUpdate.b ?? [] - }) - 1; - if (questStageIndex !== ChainStage) { - throw new Error(`Quest stage index mismatch: ${questStageIndex} !== ${ChainStage}`); - } - return; + if (ChainStage == quest.Progress.length) { + logger.debug(`pushing to quest progress in updateQuestStage`); + quest.Progress.push({ + c: 0, + i: false, + m: false, + b: [] + }); + } else if (ChainStage >= quest.Progress.length) { + throw new Error( + `Quest stage index mismatch: stage is ${ChainStage} but array size is ${quest.Progress.length}` + ); } + // Note that the client may use index 0 as well, e.g. for rising tide's initial inbox message. 'm' is not tracked for it. + if (ChainStage >= 0) { + const questStage = quest.Progress[ChainStage]; // guaranteed in-bounds now - for (const [key, value] of Object.entries(questStageUpdate) as [keyof IQuestStage, number | boolean | any[]][]) { - (questStage[key] as any) = value; + for (const [key, value] of Object.entries(questStageUpdate) as [ + keyof IQuestStage, + number | boolean | any[] + ][]) { + (questStage[key] as any) = value; + } } }; @@ -157,7 +163,7 @@ export const completeQuest = async (inventory: TInventoryDatabaseDocument, quest existingQuestKey.Progress.push(...missingProgress); } - for (let i = 0; i < chainStageTotal; i++) { + for (let i = 1; i < chainStageTotal; i++) { const stage = existingQuestKey.Progress[i]; if (stage.c <= run) { stage.c = run; @@ -302,7 +308,7 @@ export const giveKeyChainItem = async ( ): Promise => { let inventoryChanges: IInventoryChanges = {}; - if (!questKey.Progress?.[keyChainInfo.ChainStage]?.i) { + if (!questKey.Progress?.[keyChainInfo.ChainStage - 1]?.i) { inventoryChanges = await addKeyChainItems(inventory, keyChainInfo); if (isEmptyObject(inventoryChanges)) { @@ -329,16 +335,18 @@ export const giveKeyChainMessage = async ( keyChainInfo: IKeyChainRequest, questKey: IQuestKeyDatabase ): Promise => { - const keyChainMessage = getKeyChainMessage(keyChainInfo); + if (!questKey.Progress?.[keyChainInfo.ChainStage - 1]?.m) { + const keyChainMessage = getKeyChainMessage(keyChainInfo); - if ((questKey.Progress?.[0]?.c ?? 0) > 0) { - keyChainMessage.att = []; - keyChainMessage.countedAtt = []; + if ((questKey.Progress?.[0]?.c ?? 0) > 0) { + keyChainMessage.att = []; + keyChainMessage.countedAtt = []; + } + + await createMessage(inventory.accountOwnerId, [keyChainMessage]); + + updateQuestStage(inventory, keyChainInfo, { m: true }); } - - await createMessage(inventory.accountOwnerId, [keyChainMessage]); - - updateQuestStage(inventory, keyChainInfo, { m: true }); }; export const giveKeyChainMissionReward = async ( @@ -391,11 +399,11 @@ export const giveKeyChainStageTriggered = async ( const questKey = inventory.QuestKeys.find(qk => qk.ItemType === keyChainInfo.KeyChain); if (chainStages && questKey) { - if (chainStages[keyChainInfo.ChainStage].itemsToGiveWhenTriggered.length > 0) { + if (chainStages[keyChainInfo.ChainStage - 1].itemsToGiveWhenTriggered.length > 0) { await giveKeyChainItem(inventory, keyChainInfo, questKey); } - if (chainStages[keyChainInfo.ChainStage].messageToSendWhenTriggered) { + if (chainStages[keyChainInfo.ChainStage - 1].messageToSendWhenTriggered) { await giveKeyChainMessage(inventory, keyChainInfo, questKey); } }