diff --git a/config.json.example b/config.json.example index 660da015..2bdc035a 100644 --- a/config.json.example +++ b/config.json.example @@ -13,8 +13,6 @@ "skipAllDialogue": true, "unlockAllScans": true, "unlockAllMissions": true, - "unlockAllQuests": true, - "completeAllQuests": true, "infiniteCredits": true, "infinitePlatinum": true, "infiniteEndo": true, diff --git a/src/controllers/api/inventoryController.ts b/src/controllers/api/inventoryController.ts index d614b147..df7cebcf 100644 --- a/src/controllers/api/inventoryController.ts +++ b/src/controllers/api/inventoryController.ts @@ -9,7 +9,6 @@ import { IPolarity, ArtifactPolarity, EquipmentFeatures } from "@/src/types/inve import { ExportCustoms, ExportFlavour, - ExportKeys, ExportRegions, ExportResources, ExportVirtuals @@ -102,42 +101,6 @@ export const getInventoryResponse = async ( addString(inventoryResponse.NodeIntrosCompleted, "TeshinHardModeUnlocked"); } - if (config.unlockAllQuests) { - for (const [k, v] of Object.entries(ExportKeys)) { - if ("chainStages" in v) { - if (!inventoryResponse.QuestKeys.find(quest => quest.ItemType == k)) { - inventoryResponse.QuestKeys.push({ ItemType: k }); - } - } - } - } - if (config.completeAllQuests) { - for (const quest of inventoryResponse.QuestKeys) { - quest.unlock = true; - quest.Completed = true; - - let numStages = 1; - if (quest.ItemType in ExportKeys && "chainStages" in ExportKeys[quest.ItemType]) { - numStages = ExportKeys[quest.ItemType].chainStages!.length; - } - quest.Progress = []; - for (let i = 0; i != numStages; ++i) { - quest.Progress.push({ - c: 0, - i: false, - m: false, - b: [] - }); - } - } - - inventoryResponse.ArchwingEnabled = true; - inventoryResponse.ActiveQuest = ""; //TODO: might need to reconsider this if this does not work long term. - - // Skip "Watch The Maker" - addString(inventoryResponse.NodeIntrosCompleted, "/Lotus/Levels/Cinematics/NewWarIntro/NewWarStageTwo.level"); - } - if (config.unlockAllShipDecorations) { inventoryResponse.ShipDecorations = []; for (const [uniqueName, item] of Object.entries(ExportResources)) { @@ -261,7 +224,7 @@ export const getInventoryResponse = async ( return inventoryResponse; }; -const addString = (arr: string[], str: string): void => { +export const addString = (arr: string[], str: string): void => { if (!arr.find(x => x == str)) { arr.push(str); } diff --git a/src/controllers/custom/manageQuestsController.ts b/src/controllers/custom/manageQuestsController.ts new file mode 100644 index 00000000..504b4951 --- /dev/null +++ b/src/controllers/custom/manageQuestsController.ts @@ -0,0 +1,80 @@ +import { addString } from "@/src/controllers/api/inventoryController"; +import { getInventory } from "@/src/services/inventoryService"; +import { getAccountIdForRequest } from "@/src/services/loginService"; +import { addQuestKey, IUpdateQuestRequest, updateQuestKey } from "@/src/services/questService"; +import { IQuestStage } from "@/src/types/inventoryTypes/inventoryTypes"; +import { logger } from "@/src/utils/logger"; +import { RequestHandler } from "express"; +import { ExportKeys } from "warframe-public-export-plus"; + +export const manageQuestsController: RequestHandler = async (req, res) => { + const accountId = await getAccountIdForRequest(req); + const operation = req.query.operation as + | "unlockAll" + | "completeAll" + | "ResetAll" + | "completeAllUnlocked" + | "updateKey"; + const questKeyUpdate = req.body as IUpdateQuestRequest["QuestKeys"]; + + const allQuestKeys: string[] = []; + for (const [k, v] of Object.entries(ExportKeys)) { + if ("chainStages" in v) { + allQuestKeys.push(k); + } + } + const inventory = await getInventory(accountId, "QuestKeys NodeIntrosCompleted"); + + switch (operation) { + case "updateKey": { + //TODO: if this is intended to be used, one needs to add a updateQuestKeyMultiple, the game does never intend to do it, so it errors for multiple keys. + updateQuestKey(inventory, questKeyUpdate); + break; + } + case "unlockAll": { + for (const questKey of allQuestKeys) { + addQuestKey(inventory, { ItemType: questKey, Completed: false, unlock: true, Progress: [] }); + } + break; + } + case "completeAll": { + logger.info("completing all quests.."); + for (const questKey of allQuestKeys) { + const chainStageTotal = ExportKeys[questKey].chainStages?.length ?? 0; + const Progress = Array(chainStageTotal).fill({ c: 0, i: true, m: true, b: [] } satisfies IQuestStage); + const inventoryQuestKey = inventory.QuestKeys.find(qk => qk.ItemType === questKey); + if (inventoryQuestKey) { + inventoryQuestKey.Completed = true; + inventoryQuestKey.Progress = Progress; + continue; + } + addQuestKey(inventory, { ItemType: questKey, Completed: true, unlock: true, Progress: Progress }); + } + inventory.ArchwingEnabled = true; + inventory.ActiveQuest = ""; + + // Skip "Watch The Maker" + addString(inventory.NodeIntrosCompleted, "/Lotus/Levels/Cinematics/NewWarIntro/NewWarStageTwo.level"); + break; + } + case "ResetAll": { + logger.info("resetting all quests.."); + for (const questKey of inventory.QuestKeys) { + questKey.Completed = false; + questKey.Progress = []; + } + break; + } + case "completeAllUnlocked": { + logger.info("completing all unlocked quests.."); + for (const questKey of inventory.QuestKeys) { + //if (!questKey.unlock) { continue; } + questKey.Completed = true; + } + break; + } + } + + await inventory.save(); + res.status(200).end(); +}; diff --git a/src/routes/custom.ts b/src/routes/custom.ts index ad2ea069..a69afc1c 100644 --- a/src/routes/custom.ts +++ b/src/routes/custom.ts @@ -16,6 +16,7 @@ import { importController } from "@/src/controllers/custom/importController"; import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController"; import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController"; +import { manageQuestsController } from "@/src/controllers/custom/manageQuestsController"; const customRouter = express.Router(); @@ -32,6 +33,7 @@ customRouter.post("/addCurrency", addCurrencyController); customRouter.post("/addItems", addItemsController); customRouter.post("/addXp", addXpController); customRouter.post("/import", importController); +customRouter.post("/manageQuests", manageQuestsController); customRouter.get("/config", getConfigDataController); customRouter.post("/config", updateConfigDataController); diff --git a/src/services/configService.ts b/src/services/configService.ts index 89d81e8d..2312727b 100644 --- a/src/services/configService.ts +++ b/src/services/configService.ts @@ -39,8 +39,6 @@ interface IConfig { skipAllDialogue?: boolean; unlockAllScans?: boolean; unlockAllMissions?: boolean; - unlockAllQuests?: boolean; - completeAllQuests?: boolean; infiniteCredits?: boolean; infinitePlatinum?: boolean; infiniteEndo?: boolean; diff --git a/src/services/questService.ts b/src/services/questService.ts index e53126c5..75316763 100644 --- a/src/services/questService.ts +++ b/src/services/questService.ts @@ -62,3 +62,11 @@ export const updateQuestStage = ( Object.assign(questStage, questStageUpdate); }; + +export const addQuestKey = (inventory: TInventoryDatabaseDocument, questKey: IQuestKeyDatabase): void => { + if (inventory.QuestKeys.some(q => q.ItemType === questKey.ItemType)) { + logger.error(`quest key ${questKey.ItemType} already exists`); + return; + } + inventory.QuestKeys.push(questKey); +}; diff --git a/static/webui/index.html b/static/webui/index.html index 5273ba50..6af03e3c 100644 --- a/static/webui/index.html +++ b/static/webui/index.html @@ -410,6 +410,27 @@ +