From 98a46e51de4230c8952bf4af4a2360b1f81cf010 Mon Sep 17 00:00:00 2001 From: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Date: Tue, 21 Oct 2025 23:50:05 -0700 Subject: [PATCH] feat: complete Rising Tide with buying railjack (#2922) Closes #2754 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2922 Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com> Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> --- .../api/unlockShipFeatureController.ts | 21 +++++++++++++----- src/services/inventoryService.ts | 20 ++++++++++++++--- src/services/personalRoomsService.ts | 22 +++++++++---------- src/services/questService.ts | 4 +++- src/types/purchaseTypes.ts | 4 +++- src/types/requestTypes.ts | 5 ----- 6 files changed, 49 insertions(+), 27 deletions(-) diff --git a/src/controllers/api/unlockShipFeatureController.ts b/src/controllers/api/unlockShipFeatureController.ts index fb047d8d..e24a9c2c 100644 --- a/src/controllers/api/unlockShipFeatureController.ts +++ b/src/controllers/api/unlockShipFeatureController.ts @@ -1,11 +1,20 @@ import type { RequestHandler } from "express"; -import { updateShipFeature } from "../../services/personalRoomsService.ts"; -import type { IUnlockShipFeatureRequest } from "../../types/requestTypes.ts"; -import { parseString } from "../../helpers/general.ts"; +import { getAccountIdForRequest } from "../../services/loginService.ts"; +import { getInventory } from "../../services/inventoryService.ts"; +import { getJSONfromString } from "../../helpers/stringHelpers.ts"; +import { unlockShipFeature } from "../../services/personalRoomsService.ts"; export const unlockShipFeatureController: RequestHandler = async (req, res) => { - const accountId = parseString(req.query.accountId); - const shipFeatureRequest = JSON.parse((req.body as string).toString()) as IUnlockShipFeatureRequest; - await updateShipFeature(accountId, shipFeatureRequest.Feature); + const accountId = await getAccountIdForRequest(req); + const inventory = await getInventory(accountId, "MiscItems accountOwnerId"); + const request = getJSONfromString(String(req.body)); + + await unlockShipFeature(inventory, request.Feature); + await inventory.save(); res.send([]); }; +interface IUnlockShipFeatureRequest { + Feature: string; + KeyChain: string; + ChainStage: number; +} diff --git a/src/services/inventoryService.ts b/src/services/inventoryService.ts index 7fc7be4e..17cdf370 100644 --- a/src/services/inventoryService.ts +++ b/src/services/inventoryService.ts @@ -388,7 +388,7 @@ export const addItem = async ( }; } else if (ExportResources[typeName].productCategory == "CrewShips") { return { - ...addCrewShip(inventory, typeName), + ...(await addCrewShip(inventory, typeName)), // fix to unlock railjack modding, item bellow supposed to be obtained from archwing quest // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition ...(!inventory.CrewShipHarnesses?.length @@ -1543,17 +1543,31 @@ export const addCrewShipSalvagedWeaponSkin = ( return inventoryChanges; }; -const addCrewShip = ( +const addCrewShip = async ( inventory: TInventoryDatabaseDocument, typeName: string, inventoryChanges: IInventoryChanges = {} -): IInventoryChanges => { +): Promise => { if (inventory.CrewShips.length != 0) { logger.warn("refusing to add CrewShip because account already has one"); } else { const index = inventory.CrewShips.push({ ItemType: typeName }) - 1; inventoryChanges.CrewShips ??= []; inventoryChanges.CrewShips.push(inventory.CrewShips[index].toJSON()); + const railjackQuest = inventory.QuestKeys.find( + qk => qk.ItemType === "/Lotus/Types/Keys/RailJackBuildQuest/RailjackBuildQuestKeyChain" + ); + if (!railjackQuest || !railjackQuest.Completed) { + const questChanges = await completeQuest( + inventory, + "/Lotus/Types/Keys/RailJackBuildQuest/RailjackBuildQuestKeyChain", + false + ); + if (questChanges) { + inventoryChanges.QuestKeys ??= []; + inventoryChanges.QuestKeys.push(questChanges); + } + } } return inventoryChanges; }; diff --git a/src/services/personalRoomsService.ts b/src/services/personalRoomsService.ts index 56c32af9..3aa8d780 100644 --- a/src/services/personalRoomsService.ts +++ b/src/services/personalRoomsService.ts @@ -1,7 +1,9 @@ import { PersonalRooms } from "../models/personalRoomsModel.ts"; -import { addItem, getInventory } from "./inventoryService.ts"; +import { addItem } from "./inventoryService.ts"; import type { IGardeningDatabase, TPersonalRoomsDatabaseDocument } from "../types/personalRoomsTypes.ts"; import { getRandomElement } from "./rngService.ts"; +import type { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel.ts"; +import { logger } from "../utils/logger.ts"; export const getPersonalRooms = async ( accountId: string, @@ -15,19 +17,17 @@ export const getPersonalRooms = async ( return personalRooms; }; -export const updateShipFeature = async (accountId: string, shipFeature: string): Promise => { - const personalRooms = await getPersonalRooms(accountId); +export const unlockShipFeature = async (inventory: TInventoryDatabaseDocument, shipFeature: string): Promise => { + const personalRooms = await getPersonalRooms(inventory.accountOwnerId.toString()); if (personalRooms.Ship.Features.includes(shipFeature)) { - throw new Error(`ship feature ${shipFeature} already unlocked`); + logger.warn(`ship feature ${shipFeature} already unlocked`); + } else { + personalRooms.Ship.Features.push(shipFeature); + await personalRooms.save(); } - - personalRooms.Ship.Features.push(shipFeature); - await personalRooms.save(); - - const inventory = await getInventory(accountId); - await addItem(inventory, shipFeature, -1); - await inventory.save(); + const miscItem = inventory.MiscItems.find(x => x.ItemType === shipFeature); + if (miscItem && miscItem.ItemCount > 0) await addItem(inventory, shipFeature, miscItem.ItemCount * -1); }; export const createGarden = (): IGardeningDatabase => { diff --git a/src/services/questService.ts b/src/services/questService.ts index eea76b6a..8a7a532e 100644 --- a/src/services/questService.ts +++ b/src/services/questService.ts @@ -120,7 +120,7 @@ export const completeQuest = async ( inventory: TInventoryDatabaseDocument, questKey: string, sendMessages: boolean = false -): Promise => { +): Promise => { // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition const chainStages = ExportKeys[questKey]?.chainStages; @@ -176,6 +176,8 @@ export const completeQuest = async ( existingQuestKey.CompletionDate = new Date(); await handleQuestCompletion(inventory, questKey, undefined, run > 0); } + + return existingQuestKey.toJSON(); }; const getQuestCompletionItems = (questKey: string): ITypeCount[] | undefined => { diff --git a/src/types/purchaseTypes.ts b/src/types/purchaseTypes.ts index e6d5ba1e..4b1542c2 100644 --- a/src/types/purchaseTypes.ts +++ b/src/types/purchaseTypes.ts @@ -9,7 +9,8 @@ import type { TEquipmentKey, ICrewMemberClient, IKubrowPetPrintClient, - IUpgradeClient + IUpgradeClient, + IQuestKeyClient } from "./inventoryTypes/inventoryTypes.ts"; export enum PurchaseSource { @@ -83,6 +84,7 @@ export type IInventoryChanges = { CrewMembers?: ICrewMemberClient[]; KubrowPetPrints?: IKubrowPetPrintClient[]; Upgrades?: IUpgradeClient[]; // TOVERIFY + QuestKeys?: IQuestKeyClient[]; } & Record< Exclude< string, diff --git a/src/types/requestTypes.ts b/src/types/requestTypes.ts index d762edd8..ed82d296 100644 --- a/src/types/requestTypes.ts +++ b/src/types/requestTypes.ts @@ -234,11 +234,6 @@ export interface IUpgradeOperation { PolarizeValue: ArtifactPolarity; PolarityRemap: IPolarity[]; } -export interface IUnlockShipFeatureRequest { - Feature: string; - KeyChain: string; - ChainStage: number; -} export interface IVoidTearParticipantInfo { AccountId: string;