forked from OpenWF/SpaceNinjaServer
feat: claim all recipes (#2700)
Closes #2699 tried to make it a cleaner diff, but this is the best I could do Reviewed-on: OpenWF/SpaceNinjaServer#2700 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
parent
15578b04d2
commit
30398021b3
@ -4,8 +4,9 @@
|
|||||||
import type { RequestHandler } from "express";
|
import type { RequestHandler } from "express";
|
||||||
import { logger } from "../../utils/logger.ts";
|
import { logger } from "../../utils/logger.ts";
|
||||||
import { getRecipe } from "../../services/itemDataService.ts";
|
import { getRecipe } from "../../services/itemDataService.ts";
|
||||||
import type { IOid, IOidWithLegacySupport } from "../../types/commonTypes.ts";
|
import type { IOidWithLegacySupport } from "../../types/commonTypes.ts";
|
||||||
import { getJSONfromString } from "../../helpers/stringHelpers.ts";
|
import { getJSONfromString } from "../../helpers/stringHelpers.ts";
|
||||||
|
import type { TAccountDocument } from "../../services/loginService.ts";
|
||||||
import { getAccountForRequest } from "../../services/loginService.ts";
|
import { getAccountForRequest } from "../../services/loginService.ts";
|
||||||
import {
|
import {
|
||||||
getInventory,
|
getInventory,
|
||||||
@ -21,240 +22,254 @@ import {
|
|||||||
import type { IInventoryChanges } from "../../types/purchaseTypes.ts";
|
import type { IInventoryChanges } from "../../types/purchaseTypes.ts";
|
||||||
import type { IPendingRecipeDatabase } from "../../types/inventoryTypes/inventoryTypes.ts";
|
import type { IPendingRecipeDatabase } from "../../types/inventoryTypes/inventoryTypes.ts";
|
||||||
import { InventorySlot } from "../../types/inventoryTypes/inventoryTypes.ts";
|
import { InventorySlot } from "../../types/inventoryTypes/inventoryTypes.ts";
|
||||||
import { toOid2 } from "../../helpers/inventoryHelpers.ts";
|
import { fromOid, toOid2 } from "../../helpers/inventoryHelpers.ts";
|
||||||
import type { TInventoryDatabaseDocument } from "../../models/inventoryModels/inventoryModel.ts";
|
import type { TInventoryDatabaseDocument } from "../../models/inventoryModels/inventoryModel.ts";
|
||||||
import type { IRecipe } from "warframe-public-export-plus";
|
import type { IRecipe } from "warframe-public-export-plus";
|
||||||
import type { IEquipmentClient } from "../../types/equipmentTypes.ts";
|
import type { IEquipmentClient } from "../../types/equipmentTypes.ts";
|
||||||
import { EquipmentFeatures, Status } from "../../types/equipmentTypes.ts";
|
import { EquipmentFeatures, Status } from "../../types/equipmentTypes.ts";
|
||||||
|
|
||||||
interface IClaimCompletedRecipeRequest {
|
interface IClaimCompletedRecipeRequest {
|
||||||
RecipeIds: IOid[];
|
RecipeIds: IOidWithLegacySupport[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IClaimCompletedRecipeResponse {
|
||||||
|
InventoryChanges: IInventoryChanges;
|
||||||
|
BrandedSuits?: IOidWithLegacySupport[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const claimCompletedRecipeController: RequestHandler = async (req, res) => {
|
export const claimCompletedRecipeController: RequestHandler = async (req, res) => {
|
||||||
const claimCompletedRecipeRequest = getJSONfromString<IClaimCompletedRecipeRequest>(String(req.body));
|
const claimCompletedRecipeRequest = getJSONfromString<IClaimCompletedRecipeRequest>(String(req.body));
|
||||||
const account = await getAccountForRequest(req);
|
const account = await getAccountForRequest(req);
|
||||||
const inventory = await getInventory(account._id.toString());
|
const inventory = await getInventory(account._id.toString());
|
||||||
const pendingRecipe = inventory.PendingRecipes.id(claimCompletedRecipeRequest.RecipeIds[0].$oid);
|
const resp: IClaimCompletedRecipeResponse = {
|
||||||
if (!pendingRecipe) {
|
InventoryChanges: {}
|
||||||
throw new Error(`no pending recipe found with id ${claimCompletedRecipeRequest.RecipeIds[0].$oid}`);
|
};
|
||||||
}
|
for (const recipeId of claimCompletedRecipeRequest.RecipeIds) {
|
||||||
|
const pendingRecipe = inventory.PendingRecipes.id(fromOid(recipeId));
|
||||||
//check recipe is indeed ready to be completed
|
if (!pendingRecipe) {
|
||||||
// if (pendingRecipe.CompletionDate > new Date()) {
|
throw new Error(`no pending recipe found with id ${fromOid(recipeId)}`);
|
||||||
// throw new Error(`recipe ${pendingRecipe._id} is not ready to be completed`);
|
|
||||||
// }
|
|
||||||
|
|
||||||
inventory.PendingRecipes.pull(pendingRecipe._id);
|
|
||||||
|
|
||||||
const recipe = getRecipe(pendingRecipe.ItemType);
|
|
||||||
if (!recipe) {
|
|
||||||
throw new Error(`no completed item found for recipe ${pendingRecipe._id.toString()}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req.query.cancel) {
|
|
||||||
const inventoryChanges: IInventoryChanges = {};
|
|
||||||
await refundRecipeIngredients(inventory, inventoryChanges, recipe, pendingRecipe);
|
|
||||||
await inventory.save();
|
|
||||||
res.json(inventoryChanges); // Not a bug: In the specific case of cancelling a recipe, InventoryChanges are expected to be the root.
|
|
||||||
} else {
|
|
||||||
logger.debug("Claiming Recipe", { recipe, pendingRecipe });
|
|
||||||
|
|
||||||
let BrandedSuits: undefined | IOidWithLegacySupport[];
|
|
||||||
if (recipe.secretIngredientAction == "SIA_SPECTRE_LOADOUT_COPY") {
|
|
||||||
inventory.PendingSpectreLoadouts ??= [];
|
|
||||||
inventory.SpectreLoadouts ??= [];
|
|
||||||
|
|
||||||
const pendingLoadoutIndex = inventory.PendingSpectreLoadouts.findIndex(
|
|
||||||
x => x.ItemType == recipe.resultType
|
|
||||||
);
|
|
||||||
if (pendingLoadoutIndex != -1) {
|
|
||||||
const loadoutIndex = inventory.SpectreLoadouts.findIndex(x => x.ItemType == recipe.resultType);
|
|
||||||
if (loadoutIndex != -1) {
|
|
||||||
inventory.SpectreLoadouts.splice(loadoutIndex, 1);
|
|
||||||
}
|
|
||||||
logger.debug(
|
|
||||||
"moving spectre loadout from pending to active",
|
|
||||||
inventory.toJSON().PendingSpectreLoadouts![pendingLoadoutIndex]
|
|
||||||
);
|
|
||||||
inventory.SpectreLoadouts.push(inventory.PendingSpectreLoadouts[pendingLoadoutIndex]);
|
|
||||||
inventory.PendingSpectreLoadouts.splice(pendingLoadoutIndex, 1);
|
|
||||||
}
|
|
||||||
} else if (recipe.secretIngredientAction == "SIA_UNBRAND") {
|
|
||||||
inventory.BrandedSuits!.splice(
|
|
||||||
inventory.BrandedSuits!.findIndex(x => x.equals(pendingRecipe.SuitToUnbrand)),
|
|
||||||
1
|
|
||||||
);
|
|
||||||
BrandedSuits = [toOid2(pendingRecipe.SuitToUnbrand!, account.BuildLabel)];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let InventoryChanges: IInventoryChanges = {};
|
//check recipe is indeed ready to be completed
|
||||||
if (recipe.consumeOnUse) {
|
// if (pendingRecipe.CompletionDate > new Date()) {
|
||||||
addRecipes(inventory, [
|
// throw new Error(`recipe ${pendingRecipe._id} is not ready to be completed`);
|
||||||
|
// }
|
||||||
|
|
||||||
|
inventory.PendingRecipes.pull(pendingRecipe._id);
|
||||||
|
|
||||||
|
const recipe = getRecipe(pendingRecipe.ItemType);
|
||||||
|
if (!recipe) {
|
||||||
|
throw new Error(`no completed item found for recipe ${pendingRecipe._id.toString()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.query.cancel) {
|
||||||
|
const inventoryChanges: IInventoryChanges = {};
|
||||||
|
await refundRecipeIngredients(inventory, inventoryChanges, recipe, pendingRecipe);
|
||||||
|
await inventory.save();
|
||||||
|
res.json(inventoryChanges); // Not a bug: In the specific case of cancelling a recipe, InventoryChanges are expected to be the root.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await claimCompletedRecipe(account, inventory, recipe, pendingRecipe, resp, req.query.rush);
|
||||||
|
}
|
||||||
|
await inventory.save();
|
||||||
|
res.json(resp);
|
||||||
|
};
|
||||||
|
|
||||||
|
const claimCompletedRecipe = async (
|
||||||
|
account: TAccountDocument,
|
||||||
|
inventory: TInventoryDatabaseDocument,
|
||||||
|
recipe: IRecipe,
|
||||||
|
pendingRecipe: IPendingRecipeDatabase,
|
||||||
|
resp: IClaimCompletedRecipeResponse,
|
||||||
|
rush: any
|
||||||
|
): Promise<void> => {
|
||||||
|
logger.debug("Claiming Recipe", { recipe, pendingRecipe });
|
||||||
|
|
||||||
|
if (recipe.secretIngredientAction == "SIA_SPECTRE_LOADOUT_COPY") {
|
||||||
|
inventory.PendingSpectreLoadouts ??= [];
|
||||||
|
inventory.SpectreLoadouts ??= [];
|
||||||
|
|
||||||
|
const pendingLoadoutIndex = inventory.PendingSpectreLoadouts.findIndex(x => x.ItemType == recipe.resultType);
|
||||||
|
if (pendingLoadoutIndex != -1) {
|
||||||
|
const loadoutIndex = inventory.SpectreLoadouts.findIndex(x => x.ItemType == recipe.resultType);
|
||||||
|
if (loadoutIndex != -1) {
|
||||||
|
inventory.SpectreLoadouts.splice(loadoutIndex, 1);
|
||||||
|
}
|
||||||
|
logger.debug(
|
||||||
|
"moving spectre loadout from pending to active",
|
||||||
|
inventory.toJSON().PendingSpectreLoadouts![pendingLoadoutIndex]
|
||||||
|
);
|
||||||
|
inventory.SpectreLoadouts.push(inventory.PendingSpectreLoadouts[pendingLoadoutIndex]);
|
||||||
|
inventory.PendingSpectreLoadouts.splice(pendingLoadoutIndex, 1);
|
||||||
|
}
|
||||||
|
} else if (recipe.secretIngredientAction == "SIA_UNBRAND") {
|
||||||
|
inventory.BrandedSuits!.splice(
|
||||||
|
inventory.BrandedSuits!.findIndex(x => x.equals(pendingRecipe.SuitToUnbrand)),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
resp.BrandedSuits = [toOid2(pendingRecipe.SuitToUnbrand!, account.BuildLabel)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recipe.consumeOnUse) {
|
||||||
|
addRecipes(inventory, [
|
||||||
|
{
|
||||||
|
ItemType: pendingRecipe.ItemType,
|
||||||
|
ItemCount: -1
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rush) {
|
||||||
|
const end = Math.trunc(pendingRecipe.CompletionDate.getTime() / 1000);
|
||||||
|
const start = end - recipe.buildTime;
|
||||||
|
const secondsElapsed = Math.trunc(Date.now() / 1000) - start;
|
||||||
|
const progress = secondsElapsed / recipe.buildTime;
|
||||||
|
logger.debug(`rushing recipe at ${Math.trunc(progress * 100)}% completion`);
|
||||||
|
const cost =
|
||||||
|
progress > 0.5 ? Math.round(recipe.skipBuildTimePrice * (1 - (progress - 0.5))) : recipe.skipBuildTimePrice;
|
||||||
|
combineInventoryChanges(resp.InventoryChanges, updateCurrency(inventory, cost, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recipe.secretIngredientAction == "SIA_CREATE_KUBROW") {
|
||||||
|
const pet = inventory.KubrowPets.id(pendingRecipe.KubrowPet!)!;
|
||||||
|
if (pet.Details!.HatchDate!.getTime() > Date.now()) {
|
||||||
|
pet.Details!.HatchDate = new Date();
|
||||||
|
}
|
||||||
|
let canSetActive = true;
|
||||||
|
for (const pet of inventory.KubrowPets) {
|
||||||
|
if (pet.Details!.Status == Status.StatusAvailable) {
|
||||||
|
canSetActive = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pet.Details!.Status = canSetActive ? Status.StatusAvailable : Status.StatusStasis;
|
||||||
|
} else if (recipe.secretIngredientAction == "SIA_DISTILL_PRINT") {
|
||||||
|
const pet = inventory.KubrowPets.id(pendingRecipe.KubrowPet!)!;
|
||||||
|
addKubrowPetPrint(inventory, pet, resp.InventoryChanges);
|
||||||
|
} else if (recipe.secretIngredientAction != "SIA_UNBRAND") {
|
||||||
|
if (recipe.resultType == "/Lotus/Powersuits/Excalibur/ExcaliburUmbra") {
|
||||||
|
// Quite the special case here...
|
||||||
|
// We don't just get Umbra, but also Skiajati and Umbra Mods. Both items are max rank, potatoed, and with the mods are pre-installed.
|
||||||
|
// Source: https://wiki.warframe.com/w/The_Sacrifice, https://wiki.warframe.com/w/Excalibur/Umbra, https://wiki.warframe.com/w/Skiajati
|
||||||
|
|
||||||
|
const umbraModA = (
|
||||||
|
await addItem(
|
||||||
|
inventory,
|
||||||
|
"/Lotus/Upgrades/Mods/Sets/Umbra/WarframeUmbraModA",
|
||||||
|
1,
|
||||||
|
false,
|
||||||
|
undefined,
|
||||||
|
`{"lvl":5}`
|
||||||
|
)
|
||||||
|
).Upgrades![0];
|
||||||
|
const umbraModB = (
|
||||||
|
await addItem(
|
||||||
|
inventory,
|
||||||
|
"/Lotus/Upgrades/Mods/Sets/Umbra/WarframeUmbraModB",
|
||||||
|
1,
|
||||||
|
false,
|
||||||
|
undefined,
|
||||||
|
`{"lvl":5}`
|
||||||
|
)
|
||||||
|
).Upgrades![0];
|
||||||
|
const umbraModC = (
|
||||||
|
await addItem(
|
||||||
|
inventory,
|
||||||
|
"/Lotus/Upgrades/Mods/Sets/Umbra/WarframeUmbraModC",
|
||||||
|
1,
|
||||||
|
false,
|
||||||
|
undefined,
|
||||||
|
`{"lvl":5}`
|
||||||
|
)
|
||||||
|
).Upgrades![0];
|
||||||
|
const sacrificeModA = (
|
||||||
|
await addItem(
|
||||||
|
inventory,
|
||||||
|
"/Lotus/Upgrades/Mods/Sets/Sacrifice/MeleeSacrificeModA",
|
||||||
|
1,
|
||||||
|
false,
|
||||||
|
undefined,
|
||||||
|
`{"lvl":5}`
|
||||||
|
)
|
||||||
|
).Upgrades![0];
|
||||||
|
const sacrificeModB = (
|
||||||
|
await addItem(
|
||||||
|
inventory,
|
||||||
|
"/Lotus/Upgrades/Mods/Sets/Sacrifice/MeleeSacrificeModB",
|
||||||
|
1,
|
||||||
|
false,
|
||||||
|
undefined,
|
||||||
|
`{"lvl":5}`
|
||||||
|
)
|
||||||
|
).Upgrades![0];
|
||||||
|
resp.InventoryChanges.Upgrades ??= [];
|
||||||
|
resp.InventoryChanges.Upgrades.push(umbraModA, umbraModB, umbraModC, sacrificeModA, sacrificeModB);
|
||||||
|
|
||||||
|
await addPowerSuit(
|
||||||
|
inventory,
|
||||||
|
"/Lotus/Powersuits/Excalibur/ExcaliburUmbra",
|
||||||
{
|
{
|
||||||
ItemType: pendingRecipe.ItemType,
|
Configs: [
|
||||||
ItemCount: -1
|
{
|
||||||
}
|
Upgrades: [
|
||||||
]);
|
"",
|
||||||
}
|
"",
|
||||||
if (req.query.rush) {
|
"",
|
||||||
const end = Math.trunc(pendingRecipe.CompletionDate.getTime() / 1000);
|
"",
|
||||||
const start = end - recipe.buildTime;
|
"",
|
||||||
const secondsElapsed = Math.trunc(Date.now() / 1000) - start;
|
umbraModA.ItemId.$oid,
|
||||||
const progress = secondsElapsed / recipe.buildTime;
|
umbraModB.ItemId.$oid,
|
||||||
logger.debug(`rushing recipe at ${Math.trunc(progress * 100)}% completion`);
|
umbraModC.ItemId.$oid
|
||||||
const cost =
|
]
|
||||||
progress > 0.5
|
}
|
||||||
? Math.round(recipe.skipBuildTimePrice * (1 - (progress - 0.5)))
|
],
|
||||||
: recipe.skipBuildTimePrice;
|
XP: 900_000,
|
||||||
InventoryChanges = {
|
Features: EquipmentFeatures.DOUBLE_CAPACITY
|
||||||
...InventoryChanges,
|
},
|
||||||
...updateCurrency(inventory, cost, true)
|
resp.InventoryChanges
|
||||||
};
|
);
|
||||||
}
|
inventory.XPInfo.push({
|
||||||
|
ItemType: "/Lotus/Powersuits/Excalibur/ExcaliburUmbra",
|
||||||
|
XP: 900_000
|
||||||
|
});
|
||||||
|
|
||||||
if (recipe.secretIngredientAction == "SIA_CREATE_KUBROW") {
|
addEquipment(
|
||||||
const pet = inventory.KubrowPets.id(pendingRecipe.KubrowPet!)!;
|
inventory,
|
||||||
if (pet.Details!.HatchDate!.getTime() > Date.now()) {
|
"Melee",
|
||||||
pet.Details!.HatchDate = new Date();
|
"/Lotus/Weapons/Tenno/Melee/Swords/UmbraKatana/UmbraKatana",
|
||||||
}
|
{
|
||||||
let canSetActive = true;
|
Configs: [
|
||||||
for (const pet of inventory.KubrowPets) {
|
{ Upgrades: ["", "", "", "", "", "", sacrificeModA.ItemId.$oid, sacrificeModB.ItemId.$oid] }
|
||||||
if (pet.Details!.Status == Status.StatusAvailable) {
|
],
|
||||||
canSetActive = false;
|
XP: 450_000,
|
||||||
break;
|
Features: EquipmentFeatures.DOUBLE_CAPACITY
|
||||||
}
|
},
|
||||||
}
|
resp.InventoryChanges
|
||||||
pet.Details!.Status = canSetActive ? Status.StatusAvailable : Status.StatusStasis;
|
);
|
||||||
} else if (recipe.secretIngredientAction == "SIA_DISTILL_PRINT") {
|
inventory.XPInfo.push({
|
||||||
const pet = inventory.KubrowPets.id(pendingRecipe.KubrowPet!)!;
|
ItemType: "/Lotus/Weapons/Tenno/Melee/Swords/UmbraKatana/UmbraKatana",
|
||||||
addKubrowPetPrint(inventory, pet, InventoryChanges);
|
XP: 450_000
|
||||||
} else if (recipe.secretIngredientAction != "SIA_UNBRAND") {
|
});
|
||||||
if (recipe.resultType == "/Lotus/Powersuits/Excalibur/ExcaliburUmbra") {
|
} else {
|
||||||
// Quite the special case here...
|
combineInventoryChanges(
|
||||||
// We don't just get Umbra, but also Skiajati and Umbra Mods. Both items are max rank, potatoed, and with the mods are pre-installed.
|
resp.InventoryChanges,
|
||||||
// Source: https://wiki.warframe.com/w/The_Sacrifice, https://wiki.warframe.com/w/Excalibur/Umbra, https://wiki.warframe.com/w/Skiajati
|
await addItem(
|
||||||
|
|
||||||
const umbraModA = (
|
|
||||||
await addItem(
|
|
||||||
inventory,
|
|
||||||
"/Lotus/Upgrades/Mods/Sets/Umbra/WarframeUmbraModA",
|
|
||||||
1,
|
|
||||||
false,
|
|
||||||
undefined,
|
|
||||||
`{"lvl":5}`
|
|
||||||
)
|
|
||||||
).Upgrades![0];
|
|
||||||
const umbraModB = (
|
|
||||||
await addItem(
|
|
||||||
inventory,
|
|
||||||
"/Lotus/Upgrades/Mods/Sets/Umbra/WarframeUmbraModB",
|
|
||||||
1,
|
|
||||||
false,
|
|
||||||
undefined,
|
|
||||||
`{"lvl":5}`
|
|
||||||
)
|
|
||||||
).Upgrades![0];
|
|
||||||
const umbraModC = (
|
|
||||||
await addItem(
|
|
||||||
inventory,
|
|
||||||
"/Lotus/Upgrades/Mods/Sets/Umbra/WarframeUmbraModC",
|
|
||||||
1,
|
|
||||||
false,
|
|
||||||
undefined,
|
|
||||||
`{"lvl":5}`
|
|
||||||
)
|
|
||||||
).Upgrades![0];
|
|
||||||
const sacrificeModA = (
|
|
||||||
await addItem(
|
|
||||||
inventory,
|
|
||||||
"/Lotus/Upgrades/Mods/Sets/Sacrifice/MeleeSacrificeModA",
|
|
||||||
1,
|
|
||||||
false,
|
|
||||||
undefined,
|
|
||||||
`{"lvl":5}`
|
|
||||||
)
|
|
||||||
).Upgrades![0];
|
|
||||||
const sacrificeModB = (
|
|
||||||
await addItem(
|
|
||||||
inventory,
|
|
||||||
"/Lotus/Upgrades/Mods/Sets/Sacrifice/MeleeSacrificeModB",
|
|
||||||
1,
|
|
||||||
false,
|
|
||||||
undefined,
|
|
||||||
`{"lvl":5}`
|
|
||||||
)
|
|
||||||
).Upgrades![0];
|
|
||||||
InventoryChanges.Upgrades ??= [];
|
|
||||||
InventoryChanges.Upgrades.push(umbraModA, umbraModB, umbraModC, sacrificeModA, sacrificeModB);
|
|
||||||
|
|
||||||
await addPowerSuit(
|
|
||||||
inventory,
|
inventory,
|
||||||
"/Lotus/Powersuits/Excalibur/ExcaliburUmbra",
|
recipe.resultType,
|
||||||
{
|
recipe.num,
|
||||||
Configs: [
|
false,
|
||||||
{
|
undefined,
|
||||||
Upgrades: [
|
pendingRecipe.TargetFingerprint
|
||||||
"",
|
)
|
||||||
"",
|
);
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
umbraModA.ItemId.$oid,
|
|
||||||
umbraModB.ItemId.$oid,
|
|
||||||
umbraModC.ItemId.$oid
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
XP: 900_000,
|
|
||||||
Features: EquipmentFeatures.DOUBLE_CAPACITY
|
|
||||||
},
|
|
||||||
InventoryChanges
|
|
||||||
);
|
|
||||||
inventory.XPInfo.push({
|
|
||||||
ItemType: "/Lotus/Powersuits/Excalibur/ExcaliburUmbra",
|
|
||||||
XP: 900_000
|
|
||||||
});
|
|
||||||
|
|
||||||
addEquipment(
|
|
||||||
inventory,
|
|
||||||
"Melee",
|
|
||||||
"/Lotus/Weapons/Tenno/Melee/Swords/UmbraKatana/UmbraKatana",
|
|
||||||
{
|
|
||||||
Configs: [
|
|
||||||
{ Upgrades: ["", "", "", "", "", "", sacrificeModA.ItemId.$oid, sacrificeModB.ItemId.$oid] }
|
|
||||||
],
|
|
||||||
XP: 450_000,
|
|
||||||
Features: EquipmentFeatures.DOUBLE_CAPACITY
|
|
||||||
},
|
|
||||||
InventoryChanges
|
|
||||||
);
|
|
||||||
inventory.XPInfo.push({
|
|
||||||
ItemType: "/Lotus/Weapons/Tenno/Melee/Swords/UmbraKatana/UmbraKatana",
|
|
||||||
XP: 450_000
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
InventoryChanges = {
|
|
||||||
...InventoryChanges,
|
|
||||||
...(await addItem(
|
|
||||||
inventory,
|
|
||||||
recipe.resultType,
|
|
||||||
recipe.num,
|
|
||||||
false,
|
|
||||||
undefined,
|
|
||||||
pendingRecipe.TargetFingerprint
|
|
||||||
))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (
|
}
|
||||||
inventory.claimingBlueprintRefundsIngredients &&
|
if (
|
||||||
recipe.secretIngredientAction != "SIA_CREATE_KUBROW" // Can't refund the egg
|
inventory.claimingBlueprintRefundsIngredients &&
|
||||||
) {
|
recipe.secretIngredientAction != "SIA_CREATE_KUBROW" // Can't refund the egg
|
||||||
await refundRecipeIngredients(inventory, InventoryChanges, recipe, pendingRecipe);
|
) {
|
||||||
}
|
await refundRecipeIngredients(inventory, resp.InventoryChanges, recipe, pendingRecipe);
|
||||||
await inventory.save();
|
|
||||||
res.json({ InventoryChanges, BrandedSuits });
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user