import { getJSONfromString } from "@/src/helpers/stringHelpers"; import { RequestHandler } from "express"; import { getAccountIdForRequest } from "@/src/services/loginService"; import { ExportSyndicates, ISyndicateSacrifice } from "warframe-public-export-plus"; import { handleStoreItemAcquisition } from "@/src/services/purchaseService"; import { addMiscItems, combineInventoryChanges, getInventory, updateCurrency } from "@/src/services/inventoryService"; import { IInventoryChanges } from "@/src/types/purchaseTypes"; import { toStoreItem } from "@/src/services/itemDataService"; import { logger } from "@/src/utils/logger"; export const syndicateSacrificeController: RequestHandler = async (request, response) => { const accountId = await getAccountIdForRequest(request); const inventory = await getInventory(accountId); const data = getJSONfromString(String(request.body)); let syndicate = inventory.Affiliations.find(x => x.Tag == data.AffiliationTag); if (!syndicate) { syndicate = inventory.Affiliations[inventory.Affiliations.push({ Tag: data.AffiliationTag, Standing: 0 }) - 1]; } const res: ISyndicateSacrificeResponse = { AffiliationTag: data.AffiliationTag, InventoryChanges: {}, Level: 0, // the new level after the sacrifice LevelIncrease: 0, // the amount of levels gained from the sacrifice NewEpisodeReward: false }; const manifest = ExportSyndicates[data.AffiliationTag]; const isNightwave = manifest.dailyChallenges !== undefined; const titles = manifest.titles; const oldLevel = syndicate.Title ?? 0; const currentStanding = syndicate.Standing ?? 0; let newLevel = oldLevel; interface _HandleItem { sacrifice?: ISyndicateSacrifice; reward?: { type: string; count?: number; // default 1 } } const needProcess: _HandleItem[] = []; if (!syndicate.Initiated) { needProcess.push({ sacrifice: manifest.initiationSacrifice, reward: manifest.initiationReward ? { type: manifest.initiationReward } : undefined, }); syndicate.Initiated = true; } if (titles == undefined) { // ummm then just trust what the client says? newLevel = res.Level = data.SacrificeLevel; res.LevelIncrease = data.SacrificeLevel - oldLevel; } else { titles.filter(x => x.level > oldLevel && x.minStanding <= currentStanding).forEach(x => { if (x.level > newLevel) newLevel = x.level; const item: _HandleItem = {}; if (x.sacrifice) { item.sacrifice = x.sacrifice; } if (x.storeItemReward) { item.reward = { type: x.storeItemReward, count: 1 }; } else if (x.reward) { item.reward = { type: toStoreItem(x.reward.ItemType), count: x.reward.ItemCount }; } if (item.sacrifice || item.reward) { needProcess.push(item); } }) res.Level = newLevel; res.LevelIncrease = newLevel - oldLevel; } for (const item of needProcess) { if (item.sacrifice) { const changes = updateCurrency(inventory, item.sacrifice.credits, false); const miscItemChanges = item.sacrifice.items.map(x => ({ ItemType: x.ItemType, ItemCount: x.ItemCount * -1 })); addMiscItems(inventory, miscItemChanges); if (res.InventoryChanges.MiscItems === undefined) { res.InventoryChanges.MiscItems = []; } res.InventoryChanges.MiscItems.push(...miscItemChanges); combineInventoryChanges(res.InventoryChanges, changes); } if (item.reward) { const rewardChanges = await handleStoreItemAcquisition(item.reward.type, inventory, item.reward.count ?? 1); if (isNightwave && Object.keys(rewardChanges.InventoryChanges).length == 0) { logger.debug(`syndicate sacrifice reward did not seem to get added, giving 50 creds instead`); const syndicateCredsItemType = manifest.titles![0].reward!.ItemType; rewardChanges.InventoryChanges.MiscItems = [{ ItemType: syndicateCredsItemType, ItemCount: 50 }]; addMiscItems(inventory, rewardChanges.InventoryChanges.MiscItems); } combineInventoryChanges(res.InventoryChanges, rewardChanges.InventoryChanges); } } if (isNightwave) { res.NewEpisodeReward = needProcess.length > 0; } else { manifest.favours.filter(x => x.rankUpReward && x.requiredLevel <= newLevel).forEach(x => { syndicate.FreeFavorsEarned ??= []; if (!syndicate.FreeFavorsEarned.includes(x.requiredLevel)) { syndicate.FreeFavorsEarned.push(x.requiredLevel); } }) } syndicate.Title = newLevel; await inventory.save(); response.json(res); }; interface ISyndicateSacrificeRequest { AffiliationTag: string; SacrificeLevel: number; AllowMultiple: boolean; } interface ISyndicateSacrificeResponse { AffiliationTag: string; Level: number; LevelIncrease: number; InventoryChanges: IInventoryChanges; NewEpisodeReward: boolean; }