Compare commits

..

No commits in common. "8104e2fc27f793382f7b8dba0fe470ff69c83dc5" and "2a7767ef4a96447ef8a4f02c2803708e9f5065fe" have entirely different histories.

7 changed files with 48 additions and 104 deletions

View File

@ -1,20 +1,11 @@
import type { RequestHandler } from "express"; import type { RequestHandler } from "express";
import { getAccountIdForRequest } from "../../services/loginService.ts"; import { updateShipFeature } from "../../services/personalRoomsService.ts";
import { getInventory } from "../../services/inventoryService.ts"; import type { IUnlockShipFeatureRequest } from "../../types/requestTypes.ts";
import { getJSONfromString } from "../../helpers/stringHelpers.ts"; import { parseString } from "../../helpers/general.ts";
import { unlockShipFeature } from "../../services/personalRoomsService.ts";
export const unlockShipFeatureController: RequestHandler = async (req, res) => { export const unlockShipFeatureController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = parseString(req.query.accountId);
const inventory = await getInventory(accountId, "MiscItems accountOwnerId"); const shipFeatureRequest = JSON.parse((req.body as string).toString()) as IUnlockShipFeatureRequest;
const request = getJSONfromString<IUnlockShipFeatureRequest>(String(req.body)); await updateShipFeature(accountId, shipFeatureRequest.Feature);
await unlockShipFeature(inventory, request.Feature);
await inventory.save();
res.send([]); res.send([]);
}; };
interface IUnlockShipFeatureRequest {
Feature: string;
KeyChain: string;
ChainStage: number;
}

View File

@ -388,7 +388,7 @@ export const addItem = async (
}; };
} else if (ExportResources[typeName].productCategory == "CrewShips") { } else if (ExportResources[typeName].productCategory == "CrewShips") {
return { return {
...(await addCrewShip(inventory, typeName)), ...addCrewShip(inventory, typeName),
// fix to unlock railjack modding, item bellow supposed to be obtained from archwing quest // fix to unlock railjack modding, item bellow supposed to be obtained from archwing quest
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
...(!inventory.CrewShipHarnesses?.length ...(!inventory.CrewShipHarnesses?.length
@ -1543,31 +1543,17 @@ export const addCrewShipSalvagedWeaponSkin = (
return inventoryChanges; return inventoryChanges;
}; };
const addCrewShip = async ( const addCrewShip = (
inventory: TInventoryDatabaseDocument, inventory: TInventoryDatabaseDocument,
typeName: string, typeName: string,
inventoryChanges: IInventoryChanges = {} inventoryChanges: IInventoryChanges = {}
): Promise<IInventoryChanges> => { ): IInventoryChanges => {
if (inventory.CrewShips.length != 0) { if (inventory.CrewShips.length != 0) {
logger.warn("refusing to add CrewShip because account already has one"); logger.warn("refusing to add CrewShip because account already has one");
} else { } else {
const index = inventory.CrewShips.push({ ItemType: typeName }) - 1; const index = inventory.CrewShips.push({ ItemType: typeName }) - 1;
inventoryChanges.CrewShips ??= []; inventoryChanges.CrewShips ??= [];
inventoryChanges.CrewShips.push(inventory.CrewShips[index].toJSON<IEquipmentClient>()); inventoryChanges.CrewShips.push(inventory.CrewShips[index].toJSON<IEquipmentClient>());
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; return inventoryChanges;
}; };

View File

@ -243,7 +243,7 @@ export const addMissionInventoryUpdates = async (
} }
} }
} }
if (inventoryUpdates.RewardInfo.jobId) { if (inventoryUpdates.MissionStatus == "GS_SUCCESS" && inventoryUpdates.RewardInfo.jobId) {
// e.g. for Profit-Taker Phase 1: // e.g. for Profit-Taker Phase 1:
// JobTier: -6, // JobTier: -6,
// jobId: '/Lotus/Types/Gameplay/Venus/Jobs/Heists/HeistProfitTakerBountyOne_-6_SolarisUnitedHub1_663a71c80000000000000025_EudicoHeists', // jobId: '/Lotus/Types/Gameplay/Venus/Jobs/Heists/HeistProfitTakerBountyOne_-6_SolarisUnitedHub1_663a71c80000000000000025_EudicoHeists',
@ -251,10 +251,7 @@ export const addMissionInventoryUpdates = async (
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
const [bounty, tier, hub, id, tag] = inventoryUpdates.RewardInfo.jobId.split("_"); const [bounty, tier, hub, id, tag] = inventoryUpdates.RewardInfo.jobId.split("_");
if ( if (tag == "EudicoHeists") {
(tag == "EudicoHeists" && inventoryUpdates.MissionStatus == "GS_SUCCESS") ||
(tag == "NokkoColony" && inventoryUpdates.RewardInfo.JobStage == 4)
) {
inventory.CompletedJobChains ??= []; inventory.CompletedJobChains ??= [];
let chain = inventory.CompletedJobChains.find(x => x.LocationTag == tag); let chain = inventory.CompletedJobChains.find(x => x.LocationTag == tag);
if (!chain) { if (!chain) {
@ -1129,8 +1126,7 @@ export const addMissionRewards = async (
RegularCredits: creditDrops, RegularCredits: creditDrops,
VoidTearParticipantsCurrWave: voidTearWave, VoidTearParticipantsCurrWave: voidTearWave,
StrippedItems: strippedItems, StrippedItems: strippedItems,
AffiliationChanges: AffiliationMods, AffiliationChanges: AffiliationMods
InvasionProgress: invasionProgress
}: IMissionInventoryUpdateRequest, }: IMissionInventoryUpdateRequest,
firstCompletion: boolean firstCompletion: boolean
): Promise<AddMissionRewardsReturnType> => { ): Promise<AddMissionRewardsReturnType> => {
@ -1180,19 +1176,6 @@ export const addMissionRewards = async (
//inventory change is what the client has not rewarded itself, also the client needs to know the credit changes for display //inventory change is what the client has not rewarded itself, also the client needs to know the credit changes for display
if (invasionProgress) {
for (const clientProgress of invasionProgress) {
const dbProgress = inventory.QualifyingInvasions.find(x => x.invasionId.equals(clientProgress._id.$oid));
if (dbProgress) {
const run =
(clientProgress.AttackerScore > clientProgress.DefenderScore
? dbProgress.AttackerScore
: dbProgress.DefenderScore) - 1;
missionCompletionCredits += 1000 * Math.min(run, 10);
}
}
}
if (rewardInfo.goalId) { if (rewardInfo.goalId) {
const goal = getWorldState().Goals.find(x => x._id.$oid == rewardInfo.goalId); const goal = getWorldState().Goals.find(x => x._id.$oid == rewardInfo.goalId);
if (goal) { if (goal) {
@ -1517,7 +1500,7 @@ export const addMissionRewards = async (
syndicateEntry = Goals.find(m => m._id.$oid === syndicateMissionId); syndicateEntry = Goals.find(m => m._id.$oid === syndicateMissionId);
if (syndicateEntry) syndicateEntry.Tag = syndicateEntry.JobAffiliationTag!; if (syndicateEntry) syndicateEntry.Tag = syndicateEntry.JobAffiliationTag!;
} }
if (syndicateEntry && syndicateEntry.Jobs && !jobType.startsWith("/Lotus/Types/Gameplay/NokkoColony/Jobs")) { if (syndicateEntry && syndicateEntry.Jobs) {
let currentJob = syndicateEntry.Jobs[rewardInfo.JobTier!]; let currentJob = syndicateEntry.Jobs[rewardInfo.JobTier!];
if ( if (
[ [
@ -2025,17 +2008,6 @@ function getRandomMissionDrops(
xpAmounts: [1000] xpAmounts: [1000]
}; };
RewardInfo.Q = false; // Just in case RewardInfo.Q = false; // Just in case
} else if (jobType.startsWith("/Lotus/Types/Gameplay/NokkoColony/Jobs/NokkoJob")) {
job = {
rewards: jobType.replace(
"/Lotus/Types/Gameplay/NokkoColony/Jobs/NokkoJob",
"Lotus/Types/Game/MissionDecks/NokkoColonyRewards/NokkoColonyRewards"
),
masteryReq: 0,
minEnemyLevel: 30,
maxEnemyLevel: 40,
xpAmounts: [0, 0, 0, 0, 0]
};
} else { } else {
const tierMap = { const tierMap = {
Two: "B", Two: "B",
@ -2079,18 +2051,14 @@ function getRandomMissionDrops(
} else if (totalStage == 5 && curentStage == 4) { } else if (totalStage == 5 && curentStage == 4) {
tableIndex = 2; tableIndex = 2;
} }
if (jobType.startsWith("/Lotus/Types/Gameplay/NokkoColony/Jobs/NokkoJob")) {
if (RewardInfo.JobStage === job.xpAmounts.length - 1) rotations = [0, 1, 2];
} else {
rotations = [tableIndex]; rotations = [tableIndex];
}
} else { } else {
rotations = [0]; rotations = [0];
} }
if ( if (
RewardInfo.Q && RewardInfo.Q &&
(RewardInfo.JobStage === job.xpAmounts.length - 1 || jobType.endsWith("VaultBounty")) && (RewardInfo.JobStage === job.xpAmounts.length - 1 || jobType.endsWith("VaultBounty")) &&
!jobType.startsWith("/Lotus/Types/Gameplay/NokkoColony/Jobs/NokkoJob") &&
!isEndlessJob !isEndlessJob
) { ) {
rotations.push(ExportRewards[job.rewards].length - 1); rotations.push(ExportRewards[job.rewards].length - 1);
@ -2181,7 +2149,6 @@ function getRandomMissionDrops(
logger.warn(`RewardSeed mismatch:`, { client: RewardInfo.rewardSeed, database: inventory.RewardSeed }); logger.warn(`RewardSeed mismatch:`, { client: RewardInfo.rewardSeed, database: inventory.RewardSeed });
} }
} }
if (rotations.length > 1) {
const rng = new SRng(BigInt(RewardInfo.rewardSeed ?? generateRewardSeed()) ^ 0xffffffffffffffffn); const rng = new SRng(BigInt(RewardInfo.rewardSeed ?? generateRewardSeed()) ^ 0xffffffffffffffffn);
rewardManifests.forEach(name => { rewardManifests.forEach(name => {
const table = ExportRewards[name]; const table = ExportRewards[name];
@ -2198,7 +2165,6 @@ function getRandomMissionDrops(
} }
} }
}); });
}
// Railjack Abandoned Cache Rewards, Rotation A (Mandatory Objectives) // Railjack Abandoned Cache Rewards, Rotation A (Mandatory Objectives)
if (RewardInfo.POICompletions) { if (RewardInfo.POICompletions) {

View File

@ -1,9 +1,7 @@
import { PersonalRooms } from "../models/personalRoomsModel.ts"; import { PersonalRooms } from "../models/personalRoomsModel.ts";
import { addItem } from "./inventoryService.ts"; import { addItem, getInventory } from "./inventoryService.ts";
import type { IGardeningDatabase, TPersonalRoomsDatabaseDocument } from "../types/personalRoomsTypes.ts"; import type { IGardeningDatabase, TPersonalRoomsDatabaseDocument } from "../types/personalRoomsTypes.ts";
import { getRandomElement } from "./rngService.ts"; import { getRandomElement } from "./rngService.ts";
import type { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel.ts";
import { logger } from "../utils/logger.ts";
export const getPersonalRooms = async ( export const getPersonalRooms = async (
accountId: string, accountId: string,
@ -17,17 +15,19 @@ export const getPersonalRooms = async (
return personalRooms; return personalRooms;
}; };
export const unlockShipFeature = async (inventory: TInventoryDatabaseDocument, shipFeature: string): Promise<void> => { export const updateShipFeature = async (accountId: string, shipFeature: string): Promise<void> => {
const personalRooms = await getPersonalRooms(inventory.accountOwnerId.toString()); const personalRooms = await getPersonalRooms(accountId);
if (personalRooms.Ship.Features.includes(shipFeature)) { if (personalRooms.Ship.Features.includes(shipFeature)) {
logger.warn(`ship feature ${shipFeature} already unlocked`); throw new Error(`ship feature ${shipFeature} already unlocked`);
} else { }
personalRooms.Ship.Features.push(shipFeature); personalRooms.Ship.Features.push(shipFeature);
await personalRooms.save(); await personalRooms.save();
}
const miscItem = inventory.MiscItems.find(x => x.ItemType === shipFeature); const inventory = await getInventory(accountId);
if (miscItem && miscItem.ItemCount > 0) await addItem(inventory, shipFeature, miscItem.ItemCount * -1); await addItem(inventory, shipFeature, -1);
await inventory.save();
}; };
export const createGarden = (): IGardeningDatabase => { export const createGarden = (): IGardeningDatabase => {

View File

@ -120,7 +120,7 @@ export const completeQuest = async (
inventory: TInventoryDatabaseDocument, inventory: TInventoryDatabaseDocument,
questKey: string, questKey: string,
sendMessages: boolean = false sendMessages: boolean = false
): Promise<void | IQuestKeyClient> => { ): Promise<void> => {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
const chainStages = ExportKeys[questKey]?.chainStages; const chainStages = ExportKeys[questKey]?.chainStages;
@ -176,8 +176,6 @@ export const completeQuest = async (
existingQuestKey.CompletionDate = new Date(); existingQuestKey.CompletionDate = new Date();
await handleQuestCompletion(inventory, questKey, undefined, run > 0); await handleQuestCompletion(inventory, questKey, undefined, run > 0);
} }
return existingQuestKey.toJSON<IQuestKeyClient>();
}; };
const getQuestCompletionItems = (questKey: string): ITypeCount[] | undefined => { const getQuestCompletionItems = (questKey: string): ITypeCount[] | undefined => {

View File

@ -9,8 +9,7 @@ import type {
TEquipmentKey, TEquipmentKey,
ICrewMemberClient, ICrewMemberClient,
IKubrowPetPrintClient, IKubrowPetPrintClient,
IUpgradeClient, IUpgradeClient
IQuestKeyClient
} from "./inventoryTypes/inventoryTypes.ts"; } from "./inventoryTypes/inventoryTypes.ts";
export enum PurchaseSource { export enum PurchaseSource {
@ -84,7 +83,6 @@ export type IInventoryChanges = {
CrewMembers?: ICrewMemberClient[]; CrewMembers?: ICrewMemberClient[];
KubrowPetPrints?: IKubrowPetPrintClient[]; KubrowPetPrints?: IKubrowPetPrintClient[];
Upgrades?: IUpgradeClient[]; // TOVERIFY Upgrades?: IUpgradeClient[]; // TOVERIFY
QuestKeys?: IQuestKeyClient[];
} & Record< } & Record<
Exclude< Exclude<
string, string,

View File

@ -234,6 +234,11 @@ export interface IUpgradeOperation {
PolarizeValue: ArtifactPolarity; PolarizeValue: ArtifactPolarity;
PolarityRemap: IPolarity[]; PolarityRemap: IPolarity[];
} }
export interface IUnlockShipFeatureRequest {
Feature: string;
KeyChain: string;
ChainStage: number;
}
export interface IVoidTearParticipantInfo { export interface IVoidTearParticipantInfo {
AccountId: string; AccountId: string;