Merge branch 'main' of https://github.com/spaceninjaserver/SpaceNinjaServer
This commit is contained in:
commit
8c46a5391b
8
package-lock.json
generated
8
package-lock.json
generated
@ -12,7 +12,7 @@
|
||||
"copyfiles": "^2.4.1",
|
||||
"express": "^5",
|
||||
"mongoose": "^8.9.2",
|
||||
"warframe-public-export-plus": "^0.5.18",
|
||||
"warframe-public-export-plus": "^0.5.19",
|
||||
"warframe-riven-info": "^0.1.2",
|
||||
"winston": "^3.17.0",
|
||||
"winston-daily-rotate-file": "^5.0.0"
|
||||
@ -3778,9 +3778,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/warframe-public-export-plus": {
|
||||
"version": "0.5.18",
|
||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.18.tgz",
|
||||
"integrity": "sha512-wUaW5Ua5tXHOYkKJxbealdCcTnRLUN7UCkvYOJEwlB/H14EBzDaqxg4engGqzbq4H8fmttyp3EUo4vazSaxZWg=="
|
||||
"version": "0.5.19",
|
||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.19.tgz",
|
||||
"integrity": "sha512-ERCPAe4ojJXts6tyNPBvNsFcgAwJuV3M04iDfXhudJfpJrg0qseDO4AExjSyFo+WUvKoWROMCy9dCRzxIbNATw=="
|
||||
},
|
||||
"node_modules/warframe-riven-info": {
|
||||
"version": "0.1.2",
|
||||
|
@ -16,7 +16,7 @@
|
||||
"copyfiles": "^2.4.1",
|
||||
"express": "^5",
|
||||
"mongoose": "^8.9.2",
|
||||
"warframe-public-export-plus": "^0.5.18",
|
||||
"warframe-public-export-plus": "^0.5.19",
|
||||
"warframe-riven-info": "^0.1.2",
|
||||
"winston": "^3.17.0",
|
||||
"winston-daily-rotate-file": "^5.0.0"
|
||||
|
16
src/app.ts
16
src/app.ts
@ -1,16 +1,15 @@
|
||||
import express from "express";
|
||||
|
||||
import bodyParser from "body-parser";
|
||||
import { unknownEndpointHandler } from "@/src/middleware/middleware";
|
||||
import { requestLogger } from "@/src/middleware/morgenMiddleware";
|
||||
import { errorHandler } from "@/src/middleware/errorHandler";
|
||||
|
||||
import { apiRouter } from "@/src/routes/api";
|
||||
//import { testRouter } from "@/src/routes/test";
|
||||
import { cacheRouter } from "@/src/routes/cache";
|
||||
import bodyParser from "body-parser";
|
||||
|
||||
import { steamPacksController } from "@/src/controllers/misc/steamPacksController";
|
||||
import { customRouter } from "@/src/routes/custom";
|
||||
import { dynamicController } from "@/src/routes/dynamic";
|
||||
import { payRouter } from "@/src/routes/pay";
|
||||
import { statsRouter } from "@/src/routes/stats";
|
||||
import { webuiRouter } from "@/src/routes/webui";
|
||||
|
||||
@ -20,21 +19,16 @@ app.use(bodyParser.raw());
|
||||
app.use(express.json());
|
||||
app.use(bodyParser.text());
|
||||
app.use(requestLogger);
|
||||
//app.use(requestLogger);
|
||||
|
||||
app.use("/api", apiRouter);
|
||||
//app.use("/test", testRouter);
|
||||
app.use("/", cacheRouter);
|
||||
app.use("/custom", customRouter);
|
||||
app.use("/:id/dynamic", dynamicController);
|
||||
|
||||
app.post("/pay/steamPacks.php", steamPacksController);
|
||||
app.use("/pay", payRouter);
|
||||
app.use("/stats", statsRouter);
|
||||
|
||||
app.use("/", webuiRouter);
|
||||
|
||||
app.use(unknownEndpointHandler);
|
||||
|
||||
//app.use(errorHandler)
|
||||
app.use(errorHandler);
|
||||
|
||||
export { app };
|
||||
|
@ -30,13 +30,11 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
|
||||
recipe => recipe._id?.toString() === claimCompletedRecipeRequest.RecipeIds[0].$oid
|
||||
);
|
||||
if (!pendingRecipe) {
|
||||
logger.error(`no pending recipe found with id ${claimCompletedRecipeRequest.RecipeIds[0].$oid}`);
|
||||
throw new Error(`no pending recipe found with id ${claimCompletedRecipeRequest.RecipeIds[0].$oid}`);
|
||||
}
|
||||
|
||||
//check recipe is indeed ready to be completed
|
||||
// if (pendingRecipe.CompletionDate > new Date()) {
|
||||
// logger.error(`recipe ${pendingRecipe._id} is not ready to be completed`);
|
||||
// throw new Error(`recipe ${pendingRecipe._id} is not ready to be completed`);
|
||||
// }
|
||||
|
||||
@ -45,7 +43,6 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
|
||||
|
||||
const recipe = getRecipe(pendingRecipe.ItemType);
|
||||
if (!recipe) {
|
||||
logger.error(`no completed item found for recipe ${pendingRecipe._id.toString()}`);
|
||||
throw new Error(`no completed item found for recipe ${pendingRecipe._id.toString()}`);
|
||||
}
|
||||
|
||||
@ -83,11 +80,12 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
|
||||
...(await updateCurrencyByAccountId(recipe.skipBuildTimePrice, true, accountId))
|
||||
};
|
||||
}
|
||||
res.json({
|
||||
InventoryChanges: {
|
||||
...InventoryChanges,
|
||||
...(await addItem(accountId, recipe.resultType, recipe.num)).InventoryChanges
|
||||
}
|
||||
});
|
||||
const inventory = await getInventory(accountId);
|
||||
InventoryChanges = {
|
||||
...InventoryChanges,
|
||||
...(await addItem(inventory, recipe.resultType, recipe.num)).InventoryChanges
|
||||
};
|
||||
await inventory.save();
|
||||
res.json({ InventoryChanges });
|
||||
}
|
||||
};
|
||||
|
@ -3,14 +3,8 @@ import { config } from "@/src/services/configService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
|
||||
export const getCreditsController: RequestHandler = async (req, res) => {
|
||||
let accountId;
|
||||
try {
|
||||
accountId = await getAccountIdForRequest(req);
|
||||
} catch (e) {
|
||||
res.status(400).send("Log-in expired");
|
||||
return;
|
||||
}
|
||||
export const creditsController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
|
@ -4,6 +4,7 @@ import { getInventory, addMiscItems, addEquipment } from "@/src/services/invento
|
||||
import { IMiscItem, TFocusPolarity, TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { ExportFocusUpgrades } from "warframe-public-export-plus";
|
||||
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||
|
||||
export const focusController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
@ -102,8 +103,10 @@ export const focusController: RequestHandler = async (req, res) => {
|
||||
"/Lotus/Weapons/Sentients/OperatorAmplifiers/SentTrainingAmplifier/SentAmpTrainingChassis",
|
||||
"/Lotus/Weapons/Sentients/OperatorAmplifiers/SentTrainingAmplifier/SentAmpTrainingBarrel"
|
||||
];
|
||||
const result = await addEquipment("OperatorAmps", request.StartingWeaponType, accountId, parts);
|
||||
res.json(result);
|
||||
const inventory = await getInventory(accountId);
|
||||
const inventoryChanges = addEquipment(inventory, "OperatorAmps", request.StartingWeaponType, parts);
|
||||
await inventory.save();
|
||||
res.json((inventoryChanges.OperatorAmps as IEquipmentClient[])[0]);
|
||||
break;
|
||||
}
|
||||
case FocusOperation.UnbindUpgrade: {
|
||||
|
@ -5,7 +5,6 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getPersonalRooms } from "@/src/services/personalRoomsService";
|
||||
import { getShip } from "@/src/services/shipService";
|
||||
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { toOid } from "@/src/helpers/inventoryHelpers";
|
||||
import { IGetShipResponse } from "@/src/types/shipTypes";
|
||||
import { IPersonalRooms } from "@/src/types/personalRoomsTypes";
|
||||
@ -44,8 +43,7 @@ export const getLoadout = async (accountId: string) => {
|
||||
const loadout = await Loadout.findOne({ loadoutOwnerId: accountId });
|
||||
|
||||
if (!loadout) {
|
||||
logger.error(`loadout not found for account ${accountId}`);
|
||||
throw new Error("loadout not found");
|
||||
throw new Error(`loadout not found for account ${accountId}`);
|
||||
}
|
||||
|
||||
return loadout;
|
||||
|
@ -2,7 +2,7 @@ import { RequestHandler } from "express";
|
||||
import { getGuildForRequestEx } from "@/src/services/guildService";
|
||||
import { ExportDojoRecipes } from "warframe-public-export-plus";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inventoryService";
|
||||
import { addMiscItems, addRecipes, getInventory, updateCurrency } from "@/src/services/inventoryService";
|
||||
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
||||
|
||||
@ -11,11 +11,12 @@ export const guildTechController: RequestHandler = async (req, res) => {
|
||||
const inventory = await getInventory(accountId);
|
||||
const guild = await getGuildForRequestEx(req, inventory);
|
||||
const data = JSON.parse(String(req.body)) as TGuildTechRequest;
|
||||
if (data.Action == "Sync") {
|
||||
const action = data.Action.split(",")[0];
|
||||
if (action == "Sync") {
|
||||
res.json({
|
||||
TechProjects: guild.toJSON().TechProjects
|
||||
});
|
||||
} else if (data.Action == "Start") {
|
||||
} else if (action == "Start") {
|
||||
const recipe = ExportDojoRecipes.research[data.RecipeType!];
|
||||
guild.TechProjects ??= [];
|
||||
if (!guild.TechProjects.find(x => x.ItemType == data.RecipeType)) {
|
||||
@ -31,7 +32,7 @@ export const guildTechController: RequestHandler = async (req, res) => {
|
||||
}
|
||||
await guild.save();
|
||||
res.end();
|
||||
} else if (data.Action == "Contribute") {
|
||||
} else if (action == "Contribute") {
|
||||
const contributions = data as IGuildTechContributeFields;
|
||||
const techProject = guild.TechProjects!.find(x => x.ItemType == contributions.RecipeType)!;
|
||||
if (contributions.RegularCredits > techProject.ReqCredits) {
|
||||
@ -70,6 +71,30 @@ export const guildTechController: RequestHandler = async (req, res) => {
|
||||
res.json({
|
||||
InventoryChanges: inventoryChanges
|
||||
});
|
||||
} else if (action == "Buy") {
|
||||
const purchase = data as IGuildTechBuyFields;
|
||||
const quantity = parseInt(data.Action.split(",")[1]);
|
||||
const inventory = await getInventory(accountId);
|
||||
const recipeChanges = [
|
||||
{
|
||||
ItemType: purchase.RecipeType,
|
||||
ItemCount: quantity
|
||||
}
|
||||
];
|
||||
addRecipes(inventory, recipeChanges);
|
||||
const currencyChanges = updateCurrency(
|
||||
inventory,
|
||||
ExportDojoRecipes.research[purchase.RecipeType].replicatePrice,
|
||||
false
|
||||
);
|
||||
await inventory.save();
|
||||
// Not a mistake: This response uses `inventoryChanges` instead of `InventoryChanges`.
|
||||
res.json({
|
||||
inventoryChanges: {
|
||||
...currencyChanges,
|
||||
Recipes: recipeChanges
|
||||
}
|
||||
});
|
||||
} else {
|
||||
throw new Error(`unknown guildTech action: ${data.Action}`);
|
||||
}
|
||||
@ -85,6 +110,8 @@ interface IGuildTechStartFields {
|
||||
RecipeType: string;
|
||||
}
|
||||
|
||||
type IGuildTechBuyFields = IGuildTechStartFields;
|
||||
|
||||
interface IGuildTechContributeFields {
|
||||
ResearchId: "";
|
||||
RecipeType: string;
|
||||
|
@ -3,15 +3,12 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { getInventory, addMiscItems, updateCurrency, addRecipes } from "@/src/services/inventoryService";
|
||||
import { IOid } from "@/src/types/commonTypes";
|
||||
import {
|
||||
IConsumedSuit,
|
||||
IInfestedFoundry,
|
||||
IInventoryDatabaseDocument,
|
||||
IMiscItem,
|
||||
ITypeCount
|
||||
} from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { IConsumedSuit, IInfestedFoundry, IMiscItem, ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { ExportMisc, ExportRecipes } from "warframe-public-export-plus";
|
||||
import { getRecipe } from "@/src/services/itemDataService";
|
||||
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
||||
import { toMongoDate } from "@/src/helpers/inventoryHelpers";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
|
||||
export const infestedFoundryController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
@ -44,6 +41,25 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
|
||||
break;
|
||||
}
|
||||
|
||||
case "x": {
|
||||
// shard removal
|
||||
const request = getJSONfromString(String(req.body)) as IShardUninstallRequest;
|
||||
const inventory = await getInventory(accountId);
|
||||
const suit = inventory.Suits.find(suit => suit._id.toString() == request.SuitId.$oid)!;
|
||||
suit.ArchonCrystalUpgrades![request.Slot] = {};
|
||||
const bile = inventory.InfestedFoundry!.Resources!.find(
|
||||
x => x.ItemType == "/Lotus/Types/Items/InfestedFoundry/HelminthBile"
|
||||
)!;
|
||||
bile.Count -= 300;
|
||||
await inventory.save();
|
||||
res.json({
|
||||
InventoryChanges: {
|
||||
InfestedFoundry: inventory.toJSON().InfestedFoundry
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "n": {
|
||||
// name the beast
|
||||
const request = getJSONfromString(String(req.body)) as IHelminthNameRequest;
|
||||
@ -71,21 +87,43 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
|
||||
const miscItemChanges: IMiscItem[] = [];
|
||||
let totalPercentagePointsGained = 0;
|
||||
|
||||
const currentUnixSeconds = Math.trunc(new Date().getTime() / 1000);
|
||||
|
||||
for (const contribution of request.ResourceContributions) {
|
||||
const snack = ExportMisc.helminthSnacks[contribution.ItemType];
|
||||
|
||||
// Note: Currently ignoring loss of apetite
|
||||
totalPercentagePointsGained += snack.gain / 0.01;
|
||||
const resource = inventory.InfestedFoundry.Resources.find(x => x.ItemType == snack.type);
|
||||
if (resource) {
|
||||
resource.Count += Math.trunc(snack.gain * 1000);
|
||||
} else {
|
||||
inventory.InfestedFoundry.Resources.push({
|
||||
ItemType: snack.type,
|
||||
Count: Math.trunc(snack.gain * 1000)
|
||||
});
|
||||
let resource = inventory.InfestedFoundry.Resources.find(x => x.ItemType == snack.type);
|
||||
if (!resource) {
|
||||
resource =
|
||||
inventory.InfestedFoundry.Resources[
|
||||
inventory.InfestedFoundry.Resources.push({ ItemType: snack.type, Count: 0 }) - 1
|
||||
];
|
||||
}
|
||||
|
||||
resource.RecentlyConvertedResources ??= [];
|
||||
let record = resource.RecentlyConvertedResources.find(x => x.ItemType == contribution.ItemType);
|
||||
if (!record) {
|
||||
record =
|
||||
resource.RecentlyConvertedResources[
|
||||
resource.RecentlyConvertedResources.push({ ItemType: contribution.ItemType, Date: 0 }) - 1
|
||||
];
|
||||
}
|
||||
|
||||
const hoursRemaining = (record.Date - currentUnixSeconds) / 3600;
|
||||
const apetiteFactor = apetiteModel(hoursRemaining) / 30;
|
||||
logger.debug(`helminth eating ${contribution.ItemType} (+${(snack.gain * 100).toFixed(0)}%)`, {
|
||||
hoursRemaining,
|
||||
apetiteFactor
|
||||
});
|
||||
if (hoursRemaining >= 18) {
|
||||
record.Date = currentUnixSeconds + 72 * 60 * 60;
|
||||
} else {
|
||||
record.Date = currentUnixSeconds + 24 * 60 * 60;
|
||||
}
|
||||
|
||||
totalPercentagePointsGained += snack.gain * 100 * apetiteFactor; // 30% would be gain=0.3, so percentage points is equal to gain * 100.
|
||||
resource.Count += Math.trunc(snack.gain * 1000 * apetiteFactor); // 30% would be gain=0.3 or Count=300, so Count=gain*1000.
|
||||
|
||||
// tally items for removal
|
||||
const change = miscItemChanges.find(x => x.ItemType == contribution.ItemType);
|
||||
if (change) {
|
||||
@ -95,27 +133,43 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
|
||||
}
|
||||
}
|
||||
|
||||
addInfestedFoundryXP(inventory.InfestedFoundry, 666 * totalPercentagePointsGained);
|
||||
const recipeChanges = addInfestedFoundryXP(inventory.InfestedFoundry, 666 * totalPercentagePointsGained);
|
||||
addRecipes(inventory, recipeChanges);
|
||||
addMiscItems(inventory, miscItemChanges);
|
||||
await inventory.save();
|
||||
|
||||
res.json({
|
||||
InventoryChanges: {
|
||||
Recipes: recipeChanges,
|
||||
InfestedFoundry: {
|
||||
XP: inventory.InfestedFoundry.XP,
|
||||
Resources: inventory.InfestedFoundry.Resources,
|
||||
Slots: inventory.InfestedFoundry.Slots
|
||||
}
|
||||
},
|
||||
MiscItems: miscItemChanges
|
||||
},
|
||||
MiscItems: miscItemChanges
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "o": // offerings update
|
||||
// {"OfferingsIndex":540,"SuitTypes":["/Lotus/Powersuits/PaxDuviricus/PaxDuviricusBaseSuit","/Lotus/Powersuits/Nezha/NezhaBaseSuit","/Lotus/Powersuits/Devourer/DevourerBaseSuit"],"Extra":false}
|
||||
res.status(404).end();
|
||||
case "o": {
|
||||
// offerings update
|
||||
const request = getJSONfromString(String(req.body)) as IHelminthOfferingsUpdate;
|
||||
const inventory = await getInventory(accountId);
|
||||
inventory.InfestedFoundry ??= {};
|
||||
inventory.InfestedFoundry.InvigorationIndex = request.OfferingsIndex;
|
||||
inventory.InfestedFoundry.InvigorationSuitOfferings = request.SuitTypes;
|
||||
if (request.Extra) {
|
||||
inventory.InfestedFoundry.InvigorationsApplied = 0;
|
||||
}
|
||||
await inventory.save();
|
||||
res.json({
|
||||
InventoryChanges: {
|
||||
InfestedFoundry: inventory.toJSON().InfestedFoundry
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "a": {
|
||||
// subsume warframe
|
||||
@ -134,18 +188,21 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
|
||||
if (suit.Configs && suit.Configs[0] && suit.Configs[0].pricol) {
|
||||
consumedSuit.c = suit.Configs[0].pricol;
|
||||
}
|
||||
inventory.InfestedFoundry!.Slots!--;
|
||||
if ((inventory.InfestedFoundry!.XP ?? 0) < 73125_00) {
|
||||
inventory.InfestedFoundry!.Slots!--;
|
||||
}
|
||||
inventory.InfestedFoundry!.ConsumedSuits ??= [];
|
||||
inventory.InfestedFoundry!.ConsumedSuits?.push(consumedSuit);
|
||||
inventory.InfestedFoundry!.LastConsumedSuit = suit;
|
||||
inventory.InfestedFoundry!.AbilityOverrideUnlockCooldown = new Date(
|
||||
new Date().getTime() + 24 * 60 * 60 * 1000
|
||||
);
|
||||
addInfestedFoundryXP(inventory.InfestedFoundry!, 1600_00);
|
||||
const recipeChanges = addInfestedFoundryXP(inventory.InfestedFoundry!, 1600_00);
|
||||
addRecipes(inventory, recipeChanges);
|
||||
await inventory.save();
|
||||
console.log(inventory.toJSON().InfestedFoundry);
|
||||
res.json({
|
||||
InventoryChanges: {
|
||||
Recipes: recipeChanges,
|
||||
RemovedIdItems: [
|
||||
{
|
||||
ItemId: request.SuitId
|
||||
@ -178,6 +235,52 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
|
||||
break;
|
||||
}
|
||||
|
||||
case "u": {
|
||||
const request = getJSONfromString(String(req.body)) as IHelminthInvigorationRequest;
|
||||
const inventory = await getInventory(accountId);
|
||||
const suit = inventory.Suits.find(x => x._id.toString() == request.SuitId.$oid)!;
|
||||
const upgradesExpiry = new Date(new Date().getTime() + 7 * 24 * 60 * 60 * 1000);
|
||||
suit.OffensiveUpgrade = request.OffensiveUpgradeType;
|
||||
suit.DefensiveUpgrade = request.DefensiveUpgradeType;
|
||||
suit.UpgradesExpiry = upgradesExpiry;
|
||||
const recipeChanges = addInfestedFoundryXP(inventory.InfestedFoundry!, 4800_00);
|
||||
addRecipes(inventory, recipeChanges);
|
||||
for (let i = 0; i != request.ResourceTypes.length; ++i) {
|
||||
inventory.InfestedFoundry!.Resources!.find(x => x.ItemType == request.ResourceTypes[i])!.Count -=
|
||||
request.ResourceCosts[i];
|
||||
}
|
||||
inventory.InfestedFoundry!.InvigorationsApplied ??= 0;
|
||||
inventory.InfestedFoundry!.InvigorationsApplied += 1;
|
||||
await inventory.save();
|
||||
res.json({
|
||||
SuitId: request.SuitId,
|
||||
OffensiveUpgrade: request.OffensiveUpgradeType,
|
||||
DefensiveUpgrade: request.DefensiveUpgradeType,
|
||||
UpgradesExpiry: toMongoDate(upgradesExpiry),
|
||||
InventoryChanges: {
|
||||
Recipes: recipeChanges,
|
||||
InfestedFoundry: inventory.toJSON().InfestedFoundry
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "custom_unlockall": {
|
||||
const inventory = await getInventory(accountId);
|
||||
inventory.InfestedFoundry ??= {};
|
||||
inventory.InfestedFoundry.XP ??= 0;
|
||||
if (151875_00 > inventory.InfestedFoundry.XP) {
|
||||
const recipeChanges = addInfestedFoundryXP(
|
||||
inventory.InfestedFoundry,
|
||||
151875_00 - inventory.InfestedFoundry.XP
|
||||
);
|
||||
addRecipes(inventory, recipeChanges);
|
||||
await inventory.save();
|
||||
}
|
||||
res.end();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Error(`unhandled infestedFoundry mode: ${String(req.query.mode)}`);
|
||||
}
|
||||
@ -190,6 +293,11 @@ interface IShardInstallRequest {
|
||||
Color: string;
|
||||
}
|
||||
|
||||
interface IShardUninstallRequest {
|
||||
SuitId: IOid;
|
||||
Slot: number;
|
||||
}
|
||||
|
||||
interface IHelminthNameRequest {
|
||||
newName: string;
|
||||
}
|
||||
@ -216,7 +324,8 @@ const colorToShard: Record<string, string> = {
|
||||
ACC_PURPLE_MYTHIC: "/Lotus/Types/Gameplay/NarmerSorties/ArchonCrystalVioletMythic"
|
||||
};
|
||||
|
||||
const addInfestedFoundryXP = (infestedFoundry: IInfestedFoundry, delta: number): void => {
|
||||
export const addInfestedFoundryXP = (infestedFoundry: IInfestedFoundry, delta: number): ITypeCount[] => {
|
||||
const recipeChanges: ITypeCount[] = [];
|
||||
infestedFoundry.XP ??= 0;
|
||||
const prevXP = infestedFoundry.XP;
|
||||
infestedFoundry.XP += delta;
|
||||
@ -224,14 +333,69 @@ const addInfestedFoundryXP = (infestedFoundry: IInfestedFoundry, delta: number):
|
||||
infestedFoundry.Slots ??= 0;
|
||||
infestedFoundry.Slots += 3;
|
||||
}
|
||||
if (prevXP < 5625_00 && infestedFoundry.XP >= 5625_00) {
|
||||
recipeChanges.push({
|
||||
ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthShieldsBlueprint",
|
||||
ItemCount: 1
|
||||
});
|
||||
}
|
||||
if (prevXP < 10125_00 && infestedFoundry.XP >= 10125_00) {
|
||||
recipeChanges.push({ ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthHackBlueprint", ItemCount: 1 });
|
||||
}
|
||||
if (prevXP < 15750_00 && infestedFoundry.XP >= 15750_00) {
|
||||
infestedFoundry.Slots ??= 0;
|
||||
infestedFoundry.Slots += 10;
|
||||
}
|
||||
if (prevXP < 22500_00 && infestedFoundry.XP >= 22500_00) {
|
||||
recipeChanges.push({
|
||||
ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthAmmoEfficiencyBlueprint",
|
||||
ItemCount: 1
|
||||
});
|
||||
}
|
||||
if (prevXP < 30375_00 && infestedFoundry.XP >= 30375_00) {
|
||||
recipeChanges.push({ ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthStunBlueprint", ItemCount: 1 });
|
||||
}
|
||||
if (prevXP < 39375_00 && infestedFoundry.XP >= 39375_00) {
|
||||
infestedFoundry.Slots ??= 0;
|
||||
infestedFoundry.Slots += 20;
|
||||
}
|
||||
if (prevXP < 60750_00 && infestedFoundry.XP >= 60750_00) {
|
||||
recipeChanges.push({ ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthStatusBlueprint", ItemCount: 1 });
|
||||
}
|
||||
if (prevXP < 73125_00 && infestedFoundry.XP >= 73125_00) {
|
||||
infestedFoundry.Slots = 1;
|
||||
}
|
||||
if (prevXP < 86625_00 && infestedFoundry.XP >= 86625_00) {
|
||||
recipeChanges.push({
|
||||
ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthShieldArmorBlueprint",
|
||||
ItemCount: 1
|
||||
});
|
||||
}
|
||||
if (prevXP < 101250_00 && infestedFoundry.XP >= 101250_00) {
|
||||
recipeChanges.push({
|
||||
ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthProcBlockBlueprint",
|
||||
ItemCount: 1
|
||||
});
|
||||
}
|
||||
if (prevXP < 117000_00 && infestedFoundry.XP >= 117000_00) {
|
||||
recipeChanges.push({
|
||||
ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthEnergyShareBlueprint",
|
||||
ItemCount: 1
|
||||
});
|
||||
}
|
||||
if (prevXP < 133875_00 && infestedFoundry.XP >= 133875_00) {
|
||||
recipeChanges.push({
|
||||
ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthMaxStatusBlueprint",
|
||||
ItemCount: 1
|
||||
});
|
||||
}
|
||||
if (prevXP < 151875_00 && infestedFoundry.XP >= 151875_00) {
|
||||
recipeChanges.push({
|
||||
ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthTreasureBlueprint",
|
||||
ItemCount: 1
|
||||
});
|
||||
}
|
||||
return recipeChanges;
|
||||
};
|
||||
|
||||
interface IHelminthSubsumeRequest {
|
||||
@ -239,7 +403,7 @@ interface IHelminthSubsumeRequest {
|
||||
Recipe: string;
|
||||
}
|
||||
|
||||
export const handleSubsumeCompletion = (inventory: IInventoryDatabaseDocument): ITypeCount[] => {
|
||||
export const handleSubsumeCompletion = (inventory: TInventoryDatabaseDocument): ITypeCount[] => {
|
||||
const [recipeType] = Object.entries(ExportRecipes).find(
|
||||
([_recipeType, recipe]) =>
|
||||
recipe.secretIngredientAction == "SIA_WARFRAME_ABILITY" &&
|
||||
@ -256,3 +420,52 @@ export const handleSubsumeCompletion = (inventory: IInventoryDatabaseDocument):
|
||||
addRecipes(inventory, recipeChanges);
|
||||
return recipeChanges;
|
||||
};
|
||||
|
||||
interface IHelminthOfferingsUpdate {
|
||||
OfferingsIndex: number;
|
||||
SuitTypes: string[];
|
||||
Extra: boolean;
|
||||
}
|
||||
|
||||
interface IHelminthInvigorationRequest {
|
||||
SuitId: IOid;
|
||||
OffensiveUpgradeType: string;
|
||||
DefensiveUpgradeType: string;
|
||||
ResourceTypes: string[];
|
||||
ResourceCosts: number[];
|
||||
}
|
||||
|
||||
// Hours remaining, percentage points gained (out of 30 total)
|
||||
// 0, 30
|
||||
// 5, 25.8
|
||||
// 10, 21.6
|
||||
// 12, 20
|
||||
// 16, 16.6
|
||||
// 17, 15.8
|
||||
// 18, 15
|
||||
// 20, 15
|
||||
// 24, 15
|
||||
// 36, 15
|
||||
// 40, 13.6
|
||||
// 47, 11.3
|
||||
// 48, 11
|
||||
// 50, 10.3
|
||||
// 60, 7
|
||||
// 70, 3.6
|
||||
// 71, 3.3
|
||||
// 72, 3
|
||||
const apetiteModel = (x: number): number => {
|
||||
if (x <= 0) {
|
||||
return 30;
|
||||
}
|
||||
if (x < 18) {
|
||||
return -0.84 * x + 30;
|
||||
}
|
||||
if (x <= 36) {
|
||||
return 15;
|
||||
}
|
||||
if (x < 71.9) {
|
||||
return -0.3327892 * x + 26.94135;
|
||||
}
|
||||
return 3;
|
||||
};
|
||||
|
@ -1,11 +1,10 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getAccountForRequest } from "@/src/services/loginService";
|
||||
import { toInventoryResponse } from "@/src/helpers/inventoryHelpers";
|
||||
import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
|
||||
import { config } from "@/src/services/configService";
|
||||
import allDialogue from "@/static/fixed_responses/allDialogue.json";
|
||||
import { ILoadoutDatabase } from "@/src/types/saveLoadoutTypes";
|
||||
import { IInventoryDatabaseDocument, IShipInventory, equipmentKeys } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { IInventoryResponse, IShipInventory, equipmentKeys } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { IPolarity, ArtifactPolarity } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||
import {
|
||||
ExportCustoms,
|
||||
@ -18,17 +17,9 @@ import {
|
||||
import { handleSubsumeCompletion } from "./infestedFoundryController";
|
||||
|
||||
export const inventoryController: RequestHandler = async (request, response) => {
|
||||
let account;
|
||||
try {
|
||||
account = await getAccountForRequest(request);
|
||||
} catch (e) {
|
||||
response.status(400).send("Log-in expired");
|
||||
return;
|
||||
}
|
||||
const account = await getAccountForRequest(request);
|
||||
|
||||
const inventory = await Inventory.findOne({ accountOwnerId: account._id.toString() })
|
||||
.populate<{ LoadOutPresets: ILoadoutDatabase }>("LoadOutPresets")
|
||||
.populate<{ Ships: IShipInventory }>("Ships");
|
||||
const inventory = await Inventory.findOne({ accountOwnerId: account._id.toString() });
|
||||
|
||||
if (!inventory) {
|
||||
response.status(400).json({ error: "inventory was undefined" });
|
||||
@ -41,20 +32,21 @@ export const inventoryController: RequestHandler = async (request, response) =>
|
||||
account.LastLoginDay = today;
|
||||
await account.save();
|
||||
|
||||
inventory.DailyAffiliation = 16000;
|
||||
inventory.DailyAffiliationPvp = 16000;
|
||||
inventory.DailyAffiliationLibrary = 16000;
|
||||
inventory.DailyAffiliationCetus = 16000;
|
||||
inventory.DailyAffiliationQuills = 16000;
|
||||
inventory.DailyAffiliationSolaris = 16000;
|
||||
inventory.DailyAffiliationVentkids = 16000;
|
||||
inventory.DailyAffiliationVox = 16000;
|
||||
inventory.DailyAffiliationEntrati = 16000;
|
||||
inventory.DailyAffiliationNecraloid = 16000;
|
||||
inventory.DailyAffiliationZariman = 16000;
|
||||
inventory.DailyAffiliationKahl = 16000;
|
||||
inventory.DailyAffiliationCavia = 16000;
|
||||
inventory.DailyAffiliationHex = 16000;
|
||||
inventory.DailyAffiliation = 16000 + inventory.PlayerLevel * 500;
|
||||
inventory.DailyAffiliationPvp = 16000 + inventory.PlayerLevel * 500;
|
||||
inventory.DailyAffiliationLibrary = 16000 + inventory.PlayerLevel * 500;
|
||||
inventory.DailyAffiliationCetus = 16000 + inventory.PlayerLevel * 500;
|
||||
inventory.DailyAffiliationQuills = 16000 + inventory.PlayerLevel * 500;
|
||||
inventory.DailyAffiliationSolaris = 16000 + inventory.PlayerLevel * 500;
|
||||
inventory.DailyAffiliationVentkids = 16000 + inventory.PlayerLevel * 500;
|
||||
inventory.DailyAffiliationVox = 16000 + inventory.PlayerLevel * 500;
|
||||
inventory.DailyAffiliationEntrati = 16000 + inventory.PlayerLevel * 500;
|
||||
inventory.DailyAffiliationNecraloid = 16000 + inventory.PlayerLevel * 500;
|
||||
inventory.DailyAffiliationZariman = 16000 + inventory.PlayerLevel * 500;
|
||||
inventory.DailyAffiliationKahl = 16000 + inventory.PlayerLevel * 500;
|
||||
inventory.DailyAffiliationCavia = 16000 + inventory.PlayerLevel * 500;
|
||||
inventory.DailyAffiliationHex = 16000 + inventory.PlayerLevel * 500;
|
||||
inventory.DailyFocus = 250000 + inventory.PlayerLevel * 5000;
|
||||
await inventory.save();
|
||||
}
|
||||
|
||||
@ -63,14 +55,17 @@ export const inventoryController: RequestHandler = async (request, response) =>
|
||||
inventory.InfestedFoundry.AbilityOverrideUnlockCooldown &&
|
||||
new Date() >= inventory.InfestedFoundry.AbilityOverrideUnlockCooldown
|
||||
) {
|
||||
handleSubsumeCompletion(inventory as unknown as IInventoryDatabaseDocument);
|
||||
handleSubsumeCompletion(inventory);
|
||||
await inventory.save();
|
||||
}
|
||||
|
||||
//TODO: make a function that converts from database representation to client
|
||||
const inventoryJSON = inventory.toJSON();
|
||||
|
||||
const inventoryResponse = toInventoryResponse(inventoryJSON);
|
||||
const inventoryWithLoadOutPresets = await inventory.populate<{ LoadOutPresets: ILoadoutDatabase }>(
|
||||
"LoadOutPresets"
|
||||
);
|
||||
const inventoryWithLoadOutPresetsAndShips = await inventoryWithLoadOutPresets.populate<{ Ships: IShipInventory }>(
|
||||
"Ships"
|
||||
);
|
||||
const inventoryResponse = inventoryWithLoadOutPresetsAndShips.toJSON<IInventoryResponse>();
|
||||
|
||||
if (config.infiniteCredits) {
|
||||
inventoryResponse.RegularCredits = 999999999;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { updateCurrencyByAccountId } from "@/src/services/inventoryService";
|
||||
import { getInventory, updateCurrency } from "@/src/services/inventoryService";
|
||||
import { RequestHandler } from "express";
|
||||
import { updateSlots } from "@/src/services/inventoryService";
|
||||
import { InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
@ -26,8 +26,10 @@ export const inventorySlotsController: RequestHandler = async (req, res) => {
|
||||
|
||||
//TODO: check which slot was purchased because pvpBonus is also possible
|
||||
|
||||
const currencyChanges = await updateCurrencyByAccountId(20, true, accountId);
|
||||
await updateSlots(accountId, InventorySlot.PVE_LOADOUTS, 1, 1);
|
||||
const inventory = await getInventory(accountId);
|
||||
const currencyChanges = updateCurrency(inventory, 20, true);
|
||||
updateSlots(inventory, InventorySlot.PVE_LOADOUTS, 1, 1);
|
||||
await inventory.save();
|
||||
|
||||
//console.log({ InventoryChanges: currencyChanges }, " added loadout changes:");
|
||||
|
||||
|
@ -34,9 +34,10 @@ export const modularWeaponCraftingController: RequestHandler = async (req, res)
|
||||
throw new Error(`unknown modular weapon type: ${data.WeaponType}`);
|
||||
}
|
||||
const category = modularWeaponTypes[data.WeaponType];
|
||||
const inventory = await getInventory(accountId);
|
||||
|
||||
// Give weapon
|
||||
const weapon = await addEquipment(category, data.WeaponType, accountId, data.Parts);
|
||||
const weapon = addEquipment(inventory, category, data.WeaponType, data.Parts);
|
||||
|
||||
// Remove credits & parts
|
||||
const miscItemChanges = [];
|
||||
@ -46,7 +47,6 @@ export const modularWeaponCraftingController: RequestHandler = async (req, res)
|
||||
ItemCount: -1
|
||||
});
|
||||
}
|
||||
const inventory = await getInventory(accountId);
|
||||
const currencyChanges = updateCurrency(
|
||||
inventory,
|
||||
category == "Hoverboards" || category == "MoaPets" ? 5000 : 4000,
|
||||
|
@ -22,7 +22,6 @@ export const startRecipeController: RequestHandler = async (req, res) => {
|
||||
const recipe = getRecipe(recipeName);
|
||||
|
||||
if (!recipe) {
|
||||
logger.error(`unknown recipe ${recipeName}`);
|
||||
throw new Error(`unknown recipe ${recipeName}`);
|
||||
}
|
||||
|
||||
|
@ -8,13 +8,16 @@ import {
|
||||
} from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inventoryService";
|
||||
import { addMiscItems, addRecipes, getInventory, updateCurrency } from "@/src/services/inventoryService";
|
||||
import { getRecipeByResult } from "@/src/services/itemDataService";
|
||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
||||
import { addInfestedFoundryXP } from "./infestedFoundryController";
|
||||
|
||||
export const upgradesController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const payload = JSON.parse(String(req.body)) as IUpgradesRequest;
|
||||
const inventory = await getInventory(accountId);
|
||||
const inventoryChanges: IInventoryChanges = {};
|
||||
for (const operation of payload.Operations) {
|
||||
if (
|
||||
operation.UpgradeRequirement == "/Lotus/Types/Items/MiscItems/ModSlotUnlocker" ||
|
||||
@ -35,6 +38,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
|
||||
const suit = inventory.Suits.find(x => x._id.toString() == payload.ItemId.$oid)!;
|
||||
|
||||
let newAbilityOverride: IAbilityOverride | undefined;
|
||||
let totalPercentagePointsConsumed = 0;
|
||||
if (operation.UpgradeRequirement != "") {
|
||||
newAbilityOverride = {
|
||||
Ability: operation.UpgradeRequirement,
|
||||
@ -43,6 +47,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
|
||||
|
||||
const recipe = getRecipeByResult(operation.UpgradeRequirement)!;
|
||||
for (const ingredient of recipe.ingredients) {
|
||||
totalPercentagePointsConsumed += ingredient.ItemCount / 10;
|
||||
inventory.InfestedFoundry!.Resources!.find(x => x.ItemType == ingredient.ItemType)!.Count -=
|
||||
ingredient.ItemCount;
|
||||
}
|
||||
@ -52,6 +57,12 @@ export const upgradesController: RequestHandler = async (req, res) => {
|
||||
suit.Configs[entry.Slot] ??= {};
|
||||
suit.Configs[entry.Slot].AbilityOverride = newAbilityOverride;
|
||||
}
|
||||
|
||||
const recipeChanges = addInfestedFoundryXP(inventory.InfestedFoundry!, totalPercentagePointsConsumed * 8);
|
||||
addRecipes(inventory, recipeChanges);
|
||||
|
||||
inventoryChanges.Recipes = recipeChanges;
|
||||
inventoryChanges.InfestedFoundry = inventory.toJSON().InfestedFoundry;
|
||||
} else
|
||||
switch (operation.UpgradeRequirement) {
|
||||
case "/Lotus/Types/Items/MiscItems/OrokinReactor":
|
||||
@ -146,7 +157,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
|
||||
}
|
||||
}
|
||||
await inventory.save();
|
||||
res.json({ InventoryChanges: {} });
|
||||
res.json({ InventoryChanges: inventoryChanges });
|
||||
};
|
||||
|
||||
const setSlotPolarity = (item: IEquipmentDatabase, slot: number, polarity: ArtifactPolarity): void => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { ItemType, toAddItemRequest } from "@/src/helpers/customHelpers/addItemHelpers";
|
||||
import { getWeaponType } from "@/src/services/itemDataService";
|
||||
import { addPowerSuit, addEquipment } from "@/src/services/inventoryService";
|
||||
import { addPowerSuit, addEquipment, getInventory } from "@/src/services/inventoryService";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
const addItemController: RequestHandler = async (req, res) => {
|
||||
@ -10,14 +10,18 @@ const addItemController: RequestHandler = async (req, res) => {
|
||||
|
||||
switch (request.type) {
|
||||
case ItemType.Powersuit: {
|
||||
const powersuit = await addPowerSuit(request.InternalName, accountId);
|
||||
res.json(powersuit);
|
||||
const inventory = await getInventory(accountId);
|
||||
const inventoryChanges = addPowerSuit(inventory, request.InternalName);
|
||||
await inventory.save();
|
||||
res.json(inventoryChanges);
|
||||
return;
|
||||
}
|
||||
case ItemType.Weapon: {
|
||||
const inventory = await getInventory(accountId);
|
||||
const weaponType = getWeaponType(request.InternalName);
|
||||
const weapon = await addEquipment(weaponType, request.InternalName, accountId);
|
||||
res.json(weapon);
|
||||
const inventoryChanges = addEquipment(inventory, weaponType, request.InternalName);
|
||||
await inventory.save();
|
||||
res.json(inventoryChanges);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -37,9 +37,20 @@ const getItemListsController: RequestHandler = (req, res) => {
|
||||
}
|
||||
}
|
||||
for (const [uniqueName, item] of Object.entries(ExportResources)) {
|
||||
let name = getString(item.name, lang);
|
||||
if ("dissectionParts" in item) {
|
||||
name = getString("/Lotus/Language/Fish/FishDisplayName", lang).split("|FISH_NAME|").join(name);
|
||||
if (uniqueName.indexOf("Large") != -1) {
|
||||
name = name.split("|FISH_SIZE|").join(getString("/Lotus/Language/Fish/FishSizeLargeAbbrev", lang));
|
||||
} else if (uniqueName.indexOf("Medium") != -1) {
|
||||
name = name.split("|FISH_SIZE|").join(getString("/Lotus/Language/Fish/FishSizeMediumAbbrev", lang));
|
||||
} else {
|
||||
name = name.split("|FISH_SIZE|").join(getString("/Lotus/Language/Fish/FishSizeSmallAbbrev", lang));
|
||||
}
|
||||
}
|
||||
miscitems.push({
|
||||
uniqueName: item.productCategory + ":" + uniqueName,
|
||||
name: getString(item.name, lang)
|
||||
name: name
|
||||
});
|
||||
}
|
||||
for (const [uniqueName, item] of Object.entries(ExportGear)) {
|
||||
|
5
src/controllers/pay/getSkuCatalogController.ts
Normal file
5
src/controllers/pay/getSkuCatalogController.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const getSkuCatalogController: RequestHandler = (_req, res) => {
|
||||
res.sendFile("static/fixed_responses/getSkuCatalog.json", { root: "./" });
|
||||
};
|
@ -1,14 +1,6 @@
|
||||
import { IMongoDate, IOid } from "@/src/types/commonTypes";
|
||||
import { IInventoryResponse } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { Types } from "mongoose";
|
||||
|
||||
//TODO: this needs to be addressed: a schema's toJSON is responsible for changing Oid and Date to their corresponding Response versions __id to "ItemId":{"$oid":"6450f720bc562ebf030222d4"}, and a Date to "date":{"$date":{"$numberLong":"unix timestamp"})
|
||||
export const toInventoryResponse = (inventoryDatabase: { accountOwnerId: Types.ObjectId }): IInventoryResponse => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { accountOwnerId, ...inventoryResponse } = inventoryDatabase;
|
||||
return inventoryResponse as unknown as IInventoryResponse;
|
||||
};
|
||||
|
||||
export const toOid = (objectId: Types.ObjectId): IOid => {
|
||||
return { $oid: objectId.toString() } satisfies IOid;
|
||||
};
|
||||
|
16
src/middleware/errorHandler.ts
Normal file
16
src/middleware/errorHandler.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import { logger } from "../utils/logger";
|
||||
|
||||
export const errorHandler = (err: Error, req: Request, res: Response, _next: NextFunction): void => {
|
||||
if (err.message == "Invalid accountId-nonce pair") {
|
||||
res.status(400).send("Log-in expired");
|
||||
} else if (err.stack) {
|
||||
const stackArr = err.stack.split("\n");
|
||||
stackArr[0] += ` while processing ${req.path} request`;
|
||||
logger.error(stackArr.join("\n"));
|
||||
res.status(500).end();
|
||||
} else {
|
||||
logger.error(`uncaught error while processing ${req.path} request: ${err.message}`);
|
||||
res.status(500).end();
|
||||
}
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
import { Model, Schema, Types, model } from "mongoose";
|
||||
import { Document, Model, Schema, Types, model } from "mongoose";
|
||||
import {
|
||||
IFlavourItem,
|
||||
IRawUpgrade,
|
||||
@ -45,7 +45,8 @@ import {
|
||||
ICrewShipMembers,
|
||||
ICrewShip,
|
||||
ICrewShipPilotWeapon,
|
||||
IShipExterior
|
||||
IShipExterior,
|
||||
IHelminthFoodRecord
|
||||
} from "../../types/inventoryTypes/inventoryTypes";
|
||||
import { IOid } from "../../types/commonTypes";
|
||||
import {
|
||||
@ -233,6 +234,9 @@ const EquipmentSchema = new Schema<IEquipmentDatabase>(
|
||||
UnlockLevel: Number,
|
||||
Expiry: Date,
|
||||
SkillTree: String,
|
||||
OffensiveUpgrade: String,
|
||||
DefensiveUpgrade: String,
|
||||
UpgradesExpiry: Date,
|
||||
ArchonCrystalUpgrades: { type: [ArchonCrystalUpgradeSchema], default: undefined }
|
||||
},
|
||||
{ id: false }
|
||||
@ -467,7 +471,22 @@ const consumedSchuitsSchema = new Schema<IConsumedSuit>(
|
||||
{ _id: false }
|
||||
);
|
||||
|
||||
const helminthResourceSchema = new Schema<IHelminthResource>({ ItemType: String, Count: Number }, { _id: false });
|
||||
const helminthFoodRecordSchema = new Schema<IHelminthFoodRecord>(
|
||||
{
|
||||
ItemType: String,
|
||||
Date: Number
|
||||
},
|
||||
{ _id: false }
|
||||
);
|
||||
|
||||
const helminthResourceSchema = new Schema<IHelminthResource>(
|
||||
{
|
||||
ItemType: String,
|
||||
Count: Number,
|
||||
RecentlyConvertedResources: { type: [helminthFoodRecordSchema], default: undefined }
|
||||
},
|
||||
{ _id: false }
|
||||
);
|
||||
|
||||
const infestedFoundrySchema = new Schema<IInfestedFoundry>(
|
||||
{
|
||||
@ -1061,6 +1080,7 @@ inventorySchema.set("toJSON", {
|
||||
transform(_document, returnedObject) {
|
||||
delete returnedObject._id;
|
||||
delete returnedObject.__v;
|
||||
delete returnedObject.accountOwnerId;
|
||||
|
||||
const inventoryDatabase = returnedObject as IInventoryDatabase;
|
||||
const inventoryResponse = returnedObject as IInventoryResponse;
|
||||
@ -1114,3 +1134,15 @@ type InventoryDocumentProps = {
|
||||
type InventoryModelType = Model<IInventoryDatabase, {}, InventoryDocumentProps>;
|
||||
|
||||
export const Inventory = model<IInventoryDatabase, InventoryModelType>("Inventory", inventorySchema);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
export type TInventoryDatabaseDocument = Document<unknown, {}, IInventoryDatabase> &
|
||||
Omit<
|
||||
IInventoryDatabase & {
|
||||
_id: Types.ObjectId;
|
||||
} & {
|
||||
__v: number;
|
||||
},
|
||||
keyof InventoryDocumentProps
|
||||
> &
|
||||
InventoryDocumentProps;
|
||||
|
@ -5,6 +5,7 @@ import { artifactsController } from "../controllers/api/artifactsController";
|
||||
import { checkDailyMissionBonusController } from "@/src/controllers/api/checkDailyMissionBonusController";
|
||||
import { claimCompletedRecipeController } from "@/src/controllers/api/claimCompletedRecipeController";
|
||||
import { createGuildController } from "@/src/controllers/api/createGuildController";
|
||||
import { creditsController } from "@/src/controllers/api/creditsController";
|
||||
import { deleteSessionController } from "@/src/controllers/api/deleteSessionController";
|
||||
import { dojoController } from "@/src/controllers/api/dojoController";
|
||||
import { dronesController } from "@/src/controllers/api/dronesController";
|
||||
@ -16,7 +17,6 @@ import { focusController } from "@/src/controllers/api/focusController";
|
||||
import { fusionTreasuresController } from "@/src/controllers/api/fusionTreasuresController";
|
||||
import { genericUpdateController } from "@/src/controllers/api/genericUpdateController";
|
||||
import { getAllianceController } from "@/src/controllers/api/getAllianceController";
|
||||
import { getCreditsController } from "@/src/controllers/api/getCreditsController";
|
||||
import { getDailyDealStockLevelsController } from "@/src/controllers/api/getDailyDealStockLevelsController";
|
||||
import { getFriendsController } from "@/src/controllers/api/getFriendsController";
|
||||
import { getGuildController } from "@/src/controllers/api/getGuildController";
|
||||
@ -76,7 +76,7 @@ const apiRouter = express.Router();
|
||||
|
||||
// get
|
||||
apiRouter.get("/checkDailyMissionBonus.php", checkDailyMissionBonusController);
|
||||
apiRouter.get("/credits.php", getCreditsController);
|
||||
apiRouter.get("/credits.php", creditsController);
|
||||
apiRouter.get("/deleteSession.php", deleteSessionController);
|
||||
apiRouter.get("/dojo", dojoController);
|
||||
apiRouter.get("/drones.php", dronesController);
|
||||
|
11
src/routes/pay.ts
Normal file
11
src/routes/pay.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import express from "express";
|
||||
|
||||
import { getSkuCatalogController } from "@/src/controllers/pay/getSkuCatalogController";
|
||||
import { steamPacksController } from "@/src/controllers/pay/steamPacksController";
|
||||
|
||||
const payRouter = express.Router();
|
||||
|
||||
payRouter.get("/getSkuCatalog.php", getSkuCatalogController);
|
||||
payRouter.post("/steamPacks.php", steamPacksController);
|
||||
|
||||
export { payRouter };
|
@ -2,7 +2,7 @@ import { Request } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { Guild } from "@/src/models/guildModel";
|
||||
import { IInventoryDatabaseDocument } from "../types/inventoryTypes/inventoryTypes";
|
||||
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
||||
|
||||
export const getGuildForRequest = async (req: Request) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
@ -10,7 +10,7 @@ export const getGuildForRequest = async (req: Request) => {
|
||||
return await getGuildForRequestEx(req, inventory);
|
||||
};
|
||||
|
||||
export const getGuildForRequestEx = async (req: Request, inventory: IInventoryDatabaseDocument) => {
|
||||
export const getGuildForRequestEx = async (req: Request, inventory: TInventoryDatabaseDocument) => {
|
||||
const guildId = req.query.guildId as string;
|
||||
if (!inventory.GuildId || inventory.GuildId.toString() != guildId) {
|
||||
throw new Error("Account is not in the guild that it has sent a request for");
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
|
||||
import { Inventory, TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
||||
import postTutorialInventory from "@/static/fixed_responses/postTutorialInventory.json";
|
||||
import { config } from "@/src/services/configService";
|
||||
import { Types } from "mongoose";
|
||||
@ -7,7 +7,6 @@ import {
|
||||
IChallengeProgress,
|
||||
IConsumable,
|
||||
IFlavourItem,
|
||||
IInventoryDatabaseDocument,
|
||||
IMiscItem,
|
||||
IMission,
|
||||
IRawUpgrade,
|
||||
@ -80,8 +79,9 @@ export const combineInventoryChanges = (InventoryChanges: IInventoryChanges, del
|
||||
}
|
||||
} else if (typeof delta[key] == "object") {
|
||||
console.assert(key.substring(-3) == "Bin");
|
||||
console.assert(key != "InfestedFoundry");
|
||||
const left = InventoryChanges[key] as IBinChanges;
|
||||
const right: IBinChanges = delta[key];
|
||||
const right = delta[key] as IBinChanges;
|
||||
left.count += right.count;
|
||||
left.platinum += right.platinum;
|
||||
left.Slots += right.Slots;
|
||||
@ -95,7 +95,7 @@ export const combineInventoryChanges = (InventoryChanges: IInventoryChanges, del
|
||||
}
|
||||
};
|
||||
|
||||
export const getInventory = async (accountOwnerId: string) => {
|
||||
export const getInventory = async (accountOwnerId: string): Promise<TInventoryDatabaseDocument> => {
|
||||
const inventory = await Inventory.findOne({ accountOwnerId: accountOwnerId });
|
||||
|
||||
if (!inventory) {
|
||||
@ -106,13 +106,12 @@ export const getInventory = async (accountOwnerId: string) => {
|
||||
};
|
||||
|
||||
export const addItem = async (
|
||||
accountId: string,
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
typeName: string,
|
||||
quantity: number = 1
|
||||
): Promise<{ InventoryChanges: IInventoryChanges }> => {
|
||||
// Strict typing
|
||||
if (typeName in ExportRecipes) {
|
||||
const inventory = await getInventory(accountId);
|
||||
const recipeChanges = [
|
||||
{
|
||||
ItemType: typeName,
|
||||
@ -120,7 +119,6 @@ export const addItem = async (
|
||||
} satisfies ITypeCount
|
||||
];
|
||||
addRecipes(inventory, recipeChanges);
|
||||
await inventory.save();
|
||||
return {
|
||||
InventoryChanges: {
|
||||
Recipes: recipeChanges
|
||||
@ -128,11 +126,9 @@ export const addItem = async (
|
||||
};
|
||||
}
|
||||
if (typeName in ExportResources) {
|
||||
const inventory = await getInventory(accountId);
|
||||
if (ExportResources[typeName].productCategory == "Ships") {
|
||||
const oid = await createShip(new Types.ObjectId(accountId), typeName);
|
||||
const oid = await createShip(inventory.accountOwnerId, typeName);
|
||||
inventory.Ships.push(oid);
|
||||
await inventory.save();
|
||||
return {
|
||||
InventoryChanges: {
|
||||
Ships: [
|
||||
@ -144,11 +140,8 @@ export const addItem = async (
|
||||
}
|
||||
};
|
||||
} else if (ExportResources[typeName].productCategory == "CrewShips") {
|
||||
return {
|
||||
InventoryChanges: {
|
||||
CrewShips: [await addCrewShip(typeName, accountId)]
|
||||
}
|
||||
};
|
||||
const inventoryChanges = addCrewShip(inventory, typeName);
|
||||
return { InventoryChanges: inventoryChanges };
|
||||
} else {
|
||||
const miscItemChanges = [
|
||||
{
|
||||
@ -157,7 +150,6 @@ export const addItem = async (
|
||||
} satisfies IMiscItem
|
||||
];
|
||||
addMiscItems(inventory, miscItemChanges);
|
||||
await inventory.save();
|
||||
return {
|
||||
InventoryChanges: {
|
||||
MiscItems: miscItemChanges
|
||||
@ -166,21 +158,14 @@ export const addItem = async (
|
||||
}
|
||||
}
|
||||
if (typeName in ExportCustoms) {
|
||||
return {
|
||||
InventoryChanges: {
|
||||
WeaponSkins: [await addSkin(typeName, accountId)]
|
||||
}
|
||||
};
|
||||
const inventoryChanges = addSkin(inventory, typeName);
|
||||
return { InventoryChanges: inventoryChanges };
|
||||
}
|
||||
if (typeName in ExportFlavour) {
|
||||
return {
|
||||
InventoryChanges: {
|
||||
FlavourItems: [await addCustomization(typeName, accountId)]
|
||||
}
|
||||
};
|
||||
const inventoryChanges = addCustomization(inventory, typeName);
|
||||
return { InventoryChanges: inventoryChanges };
|
||||
}
|
||||
if (typeName in ExportUpgrades || typeName in ExportArcanes) {
|
||||
const inventory = await getInventory(accountId);
|
||||
const changes = [
|
||||
{
|
||||
ItemType: typeName,
|
||||
@ -188,7 +173,6 @@ export const addItem = async (
|
||||
}
|
||||
];
|
||||
addMods(inventory, changes);
|
||||
await inventory.save();
|
||||
return {
|
||||
InventoryChanges: {
|
||||
RawUpgrades: changes
|
||||
@ -196,7 +180,6 @@ export const addItem = async (
|
||||
};
|
||||
}
|
||||
if (typeName in ExportGear) {
|
||||
const inventory = await getInventory(accountId);
|
||||
const consumablesChanges = [
|
||||
{
|
||||
ItemType: typeName,
|
||||
@ -204,7 +187,6 @@ export const addItem = async (
|
||||
} satisfies IConsumable
|
||||
];
|
||||
addConsumables(inventory, consumablesChanges);
|
||||
await inventory.save();
|
||||
return {
|
||||
InventoryChanges: {
|
||||
Consumables: consumablesChanges
|
||||
@ -217,8 +199,8 @@ export const addItem = async (
|
||||
case "Powersuits":
|
||||
switch (typeName.substr(1).split("/")[2]) {
|
||||
default: {
|
||||
const inventoryChanges = await addPowerSuit(typeName, accountId);
|
||||
await updateSlots(accountId, InventorySlot.SUITS, 0, 1);
|
||||
const inventoryChanges = addPowerSuit(inventory, typeName);
|
||||
updateSlots(inventory, InventorySlot.SUITS, 0, 1);
|
||||
return {
|
||||
InventoryChanges: {
|
||||
...inventoryChanges,
|
||||
@ -231,22 +213,22 @@ export const addItem = async (
|
||||
};
|
||||
}
|
||||
case "Archwing": {
|
||||
const spaceSuit = await addSpaceSuit(typeName, accountId);
|
||||
await updateSlots(accountId, InventorySlot.SPACESUITS, 0, 1);
|
||||
const inventoryChanges = addSpaceSuit(inventory, typeName);
|
||||
updateSlots(inventory, InventorySlot.SPACESUITS, 0, 1);
|
||||
return {
|
||||
InventoryChanges: {
|
||||
...inventoryChanges,
|
||||
SpaceSuitBin: {
|
||||
count: 1,
|
||||
platinum: 0,
|
||||
Slots: -1
|
||||
},
|
||||
SpaceSuits: [spaceSuit]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
case "EntratiMech": {
|
||||
const inventoryChanges = await addMechSuit(typeName, accountId);
|
||||
await updateSlots(accountId, InventorySlot.MECHSUITS, 0, 1);
|
||||
const inventoryChanges = addMechSuit(inventory, typeName);
|
||||
updateSlots(inventory, InventorySlot.MECHSUITS, 0, 1);
|
||||
return {
|
||||
InventoryChanges: {
|
||||
...inventoryChanges,
|
||||
@ -262,18 +244,17 @@ export const addItem = async (
|
||||
break;
|
||||
case "Weapons": {
|
||||
const weaponType = getWeaponType(typeName);
|
||||
const weapon = await addEquipment(weaponType, typeName, accountId);
|
||||
await updateSlots(accountId, InventorySlot.WEAPONS, 0, 1);
|
||||
const inventoryChanges = addEquipment(inventory, weaponType, typeName);
|
||||
updateSlots(inventory, InventorySlot.WEAPONS, 0, 1);
|
||||
return {
|
||||
InventoryChanges: {
|
||||
WeaponBin: { count: 1, platinum: 0, Slots: -1 },
|
||||
[weaponType]: [weapon]
|
||||
...inventoryChanges,
|
||||
WeaponBin: { count: 1, platinum: 0, Slots: -1 }
|
||||
}
|
||||
};
|
||||
}
|
||||
case "Objects": {
|
||||
// /Lotus/Objects/Tenno/Props/TnoLisetTextProjector (Note Beacon)
|
||||
const inventory = await getInventory(accountId);
|
||||
const changes = [
|
||||
{
|
||||
ItemType: typeName,
|
||||
@ -281,7 +262,6 @@ export const addItem = async (
|
||||
} satisfies IMiscItem
|
||||
];
|
||||
addShipDecorations(inventory, changes);
|
||||
await inventory.save();
|
||||
return {
|
||||
InventoryChanges: {
|
||||
ShipDecorations: changes
|
||||
@ -291,8 +271,8 @@ export const addItem = async (
|
||||
case "Types":
|
||||
switch (typeName.substr(1).split("/")[2]) {
|
||||
case "Sentinels": {
|
||||
const inventoryChanges = await addSentinel(typeName, accountId);
|
||||
await updateSlots(accountId, InventorySlot.SENTINELS, 0, 1);
|
||||
const inventoryChanges = addSentinel(inventory, typeName);
|
||||
updateSlots(inventory, InventorySlot.SENTINELS, 0, 1);
|
||||
return {
|
||||
InventoryChanges: {
|
||||
...inventoryChanges,
|
||||
@ -303,7 +283,6 @@ export const addItem = async (
|
||||
case "Items": {
|
||||
switch (typeName.substr(1).split("/")[3]) {
|
||||
case "ShipDecos": {
|
||||
const inventory = await getInventory(accountId);
|
||||
const changes = [
|
||||
{
|
||||
ItemType: typeName,
|
||||
@ -311,7 +290,6 @@ export const addItem = async (
|
||||
} satisfies IMiscItem
|
||||
];
|
||||
addShipDecorations(inventory, changes);
|
||||
await inventory.save();
|
||||
return {
|
||||
InventoryChanges: {
|
||||
ShipDecorations: changes
|
||||
@ -319,7 +297,6 @@ export const addItem = async (
|
||||
};
|
||||
}
|
||||
default: {
|
||||
const inventory = await getInventory(accountId);
|
||||
const miscItemChanges = [
|
||||
{
|
||||
ItemType: typeName,
|
||||
@ -327,7 +304,6 @@ export const addItem = async (
|
||||
} satisfies IMiscItem
|
||||
];
|
||||
addMiscItems(inventory, miscItemChanges);
|
||||
await inventory.save();
|
||||
return {
|
||||
InventoryChanges: {
|
||||
MiscItems: miscItemChanges
|
||||
@ -339,7 +315,6 @@ export const addItem = async (
|
||||
case "Game":
|
||||
if (typeName.substr(1).split("/")[3] == "Projections") {
|
||||
// Void Relics, e.g. /Lotus/Types/Game/Projections/T2VoidProjectionGaussPrimeDBronze
|
||||
const inventory = await getInventory(accountId);
|
||||
const miscItemChanges = [
|
||||
{
|
||||
ItemType: typeName,
|
||||
@ -347,7 +322,6 @@ export const addItem = async (
|
||||
} satisfies IMiscItem
|
||||
];
|
||||
addMiscItems(inventory, miscItemChanges);
|
||||
await inventory.save();
|
||||
return {
|
||||
InventoryChanges: {
|
||||
MiscItems: miscItemChanges
|
||||
@ -364,13 +338,13 @@ export const addItem = async (
|
||||
};
|
||||
|
||||
//TODO: maybe genericMethod for all the add methods, they share a lot of logic
|
||||
export const addSentinel = async (sentinelName: string, accountId: string): Promise<IInventoryChanges> => {
|
||||
const inventoryChanges: IInventoryChanges = {};
|
||||
|
||||
export const addSentinel = (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
sentinelName: string,
|
||||
inventoryChanges: IInventoryChanges = {}
|
||||
): IInventoryChanges => {
|
||||
if (ExportSentinels[sentinelName]?.defaultWeapon) {
|
||||
inventoryChanges.SentinelWeapons = [
|
||||
await addSentinelWeapon(ExportSentinels[sentinelName].defaultWeapon, accountId)
|
||||
];
|
||||
addSentinelWeapon(inventory, ExportSentinels[sentinelName].defaultWeapon, inventoryChanges);
|
||||
}
|
||||
|
||||
const modsToGive: IRawUpgrade[] = [];
|
||||
@ -388,96 +362,109 @@ export const addSentinel = async (sentinelName: string, accountId: string): Prom
|
||||
}
|
||||
}
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
addMods(inventory, modsToGive);
|
||||
const sentinelIndex = inventory.Sentinels.push({ ItemType: sentinelName, Configs: configs, XP: 0 });
|
||||
const changedInventory = await inventory.save();
|
||||
inventoryChanges.Sentinels = [changedInventory.Sentinels[sentinelIndex - 1].toJSON()];
|
||||
const sentinelIndex = inventory.Sentinels.push({ ItemType: sentinelName, Configs: configs, XP: 0 }) - 1;
|
||||
inventoryChanges.Sentinels ??= [];
|
||||
(inventoryChanges.Sentinels as IEquipmentClient[]).push(
|
||||
inventory.Sentinels[sentinelIndex].toJSON<IEquipmentClient>()
|
||||
);
|
||||
|
||||
return inventoryChanges;
|
||||
};
|
||||
|
||||
export const addSentinelWeapon = async (typeName: string, accountId: string): Promise<IEquipmentClient> => {
|
||||
const inventory = await getInventory(accountId);
|
||||
const sentinelIndex = inventory.SentinelWeapons.push({ ItemType: typeName });
|
||||
const changedInventory = await inventory.save();
|
||||
return changedInventory.SentinelWeapons[sentinelIndex - 1].toJSON<IEquipmentClient>();
|
||||
export const addSentinelWeapon = (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
typeName: string,
|
||||
inventoryChanges: IInventoryChanges
|
||||
): void => {
|
||||
const index = inventory.SentinelWeapons.push({ ItemType: typeName }) - 1;
|
||||
inventoryChanges.SentinelWeapons ??= [];
|
||||
(inventoryChanges.SentinelWeapons as IEquipmentClient[]).push(
|
||||
inventory.SentinelWeapons[index].toJSON<IEquipmentClient>()
|
||||
);
|
||||
};
|
||||
|
||||
export const addPowerSuit = async (powersuitName: string, accountId: string): Promise<IInventoryChanges> => {
|
||||
const inventoryChanges: IInventoryChanges = {};
|
||||
export const addPowerSuit = (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
powersuitName: string,
|
||||
inventoryChanges: IInventoryChanges = {}
|
||||
): IInventoryChanges => {
|
||||
const specialItems = getExalted(powersuitName);
|
||||
if (specialItems) {
|
||||
for await (const specialItem of specialItems) {
|
||||
await addSpecialItem(specialItem, accountId, inventoryChanges);
|
||||
for (const specialItem of specialItems) {
|
||||
addSpecialItem(inventory, specialItem, inventoryChanges);
|
||||
}
|
||||
}
|
||||
const inventory = await getInventory(accountId);
|
||||
const suitIndex = inventory.Suits.push({ ItemType: powersuitName, Configs: [], UpgradeVer: 101, XP: 0 });
|
||||
const changedInventory = await inventory.save();
|
||||
inventoryChanges.Suits = [changedInventory.Suits[suitIndex - 1].toJSON()];
|
||||
const suitIndex = inventory.Suits.push({ ItemType: powersuitName, Configs: [], UpgradeVer: 101, XP: 0 }) - 1;
|
||||
inventoryChanges.Suits ??= [];
|
||||
(inventoryChanges.Suits as IEquipmentClient[]).push(inventory.Suits[suitIndex].toJSON<IEquipmentClient>());
|
||||
return inventoryChanges;
|
||||
};
|
||||
|
||||
export const addMechSuit = async (mechsuitName: string, accountId: string): Promise<IInventoryChanges> => {
|
||||
const inventoryChanges: IInventoryChanges = {};
|
||||
export const addMechSuit = (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
mechsuitName: string,
|
||||
inventoryChanges: IInventoryChanges = {}
|
||||
): IInventoryChanges => {
|
||||
const specialItems = getExalted(mechsuitName);
|
||||
if (specialItems) {
|
||||
for await (const specialItem of specialItems) {
|
||||
await addSpecialItem(specialItem, accountId, inventoryChanges);
|
||||
for (const specialItem of specialItems) {
|
||||
addSpecialItem(inventory, specialItem, inventoryChanges);
|
||||
}
|
||||
}
|
||||
const inventory = await getInventory(accountId);
|
||||
const suitIndex = inventory.MechSuits.push({ ItemType: mechsuitName, Configs: [], UpgradeVer: 101, XP: 0 });
|
||||
const changedInventory = await inventory.save();
|
||||
inventoryChanges.MechSuits = [changedInventory.MechSuits[suitIndex - 1].toJSON()];
|
||||
const suitIndex = inventory.MechSuits.push({ ItemType: mechsuitName, Configs: [], UpgradeVer: 101, XP: 0 }) - 1;
|
||||
inventoryChanges.MechSuits ??= [];
|
||||
(inventoryChanges.MechSuits as IEquipmentClient[]).push(inventory.MechSuits[suitIndex].toJSON<IEquipmentClient>());
|
||||
return inventoryChanges;
|
||||
};
|
||||
|
||||
export const addSpecialItem = async (
|
||||
export const addSpecialItem = (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
itemName: string,
|
||||
accountId: string,
|
||||
inventoryChanges: IInventoryChanges
|
||||
): Promise<void> => {
|
||||
const inventory = await getInventory(accountId);
|
||||
): void => {
|
||||
if (inventory.SpecialItems.find(x => x.ItemType == itemName)) {
|
||||
return;
|
||||
}
|
||||
const specialItemIndex = inventory.SpecialItems.push({
|
||||
ItemType: itemName,
|
||||
Configs: [],
|
||||
Features: 1,
|
||||
UpgradeVer: 101,
|
||||
XP: 0
|
||||
});
|
||||
const changedInventory = await inventory.save();
|
||||
const specialItemIndex =
|
||||
inventory.SpecialItems.push({
|
||||
ItemType: itemName,
|
||||
Configs: [],
|
||||
Features: 1,
|
||||
UpgradeVer: 101,
|
||||
XP: 0
|
||||
}) - 1;
|
||||
inventoryChanges.SpecialItems ??= [];
|
||||
(inventoryChanges.SpecialItems as object[]).push(changedInventory.SpecialItems[specialItemIndex - 1].toJSON());
|
||||
(inventoryChanges.SpecialItems as IEquipmentClient[]).push(
|
||||
inventory.SpecialItems[specialItemIndex].toJSON<IEquipmentClient>()
|
||||
);
|
||||
};
|
||||
|
||||
export const addSpaceSuit = async (spacesuitName: string, accountId: string): Promise<IEquipmentClient> => {
|
||||
const inventory = await getInventory(accountId);
|
||||
const suitIndex = inventory.SpaceSuits.push({ ItemType: spacesuitName, Configs: [], UpgradeVer: 101, XP: 0 });
|
||||
const changedInventory = await inventory.save();
|
||||
return changedInventory.SpaceSuits[suitIndex - 1].toJSON<IEquipmentClient>();
|
||||
export const addSpaceSuit = (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
spacesuitName: string,
|
||||
inventoryChanges: IInventoryChanges = {}
|
||||
): IInventoryChanges => {
|
||||
const suitIndex = inventory.SpaceSuits.push({ ItemType: spacesuitName, Configs: [], UpgradeVer: 101, XP: 0 }) - 1;
|
||||
inventoryChanges.SpaceSuits ??= [];
|
||||
(inventoryChanges.SpaceSuits as IEquipmentClient[]).push(
|
||||
inventory.SpaceSuits[suitIndex].toJSON<IEquipmentClient>()
|
||||
);
|
||||
return inventoryChanges;
|
||||
};
|
||||
|
||||
export const updateSlots = async (
|
||||
accountId: string,
|
||||
export const updateSlots = (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
slotName: SlotNames,
|
||||
slotAmount: number,
|
||||
extraAmount: number
|
||||
): Promise<void> => {
|
||||
const inventory = await getInventory(accountId);
|
||||
|
||||
): void => {
|
||||
inventory[slotName].Slots += slotAmount;
|
||||
if (inventory[slotName].Extra === undefined) {
|
||||
inventory[slotName].Extra = extraAmount;
|
||||
} else {
|
||||
inventory[slotName].Extra += extraAmount;
|
||||
}
|
||||
|
||||
await inventory.save();
|
||||
};
|
||||
|
||||
const isCurrencyTracked = (usePremium: boolean): boolean => {
|
||||
@ -485,7 +472,7 @@ const isCurrencyTracked = (usePremium: boolean): boolean => {
|
||||
};
|
||||
|
||||
export const updateCurrency = (
|
||||
inventory: IInventoryDatabaseDocument,
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
price: number,
|
||||
usePremium: boolean
|
||||
): ICurrencyChanges => {
|
||||
@ -549,48 +536,65 @@ export const updateTheme = async (data: IThemeUpdateRequest, accountId: string):
|
||||
await inventory.save();
|
||||
};
|
||||
|
||||
export const addEquipment = async (
|
||||
export const addEquipment = (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
category: TEquipmentKey,
|
||||
type: string,
|
||||
accountId: string,
|
||||
modularParts: string[] | undefined = undefined
|
||||
): Promise<IEquipmentClient> => {
|
||||
const inventory = await getInventory(accountId);
|
||||
modularParts: string[] | undefined = undefined,
|
||||
inventoryChanges: IInventoryChanges = {}
|
||||
): IInventoryChanges => {
|
||||
const index =
|
||||
inventory[category].push({
|
||||
ItemType: type,
|
||||
Configs: [],
|
||||
XP: 0,
|
||||
ModularParts: modularParts
|
||||
}) - 1;
|
||||
|
||||
const index = inventory[category].push({
|
||||
ItemType: type,
|
||||
Configs: [],
|
||||
XP: 0,
|
||||
ModularParts: modularParts
|
||||
});
|
||||
|
||||
const changedInventory = await inventory.save();
|
||||
return changedInventory[category][index - 1].toJSON() as object as IEquipmentClient;
|
||||
inventoryChanges[category] ??= [];
|
||||
(inventoryChanges[category] as IEquipmentClient[]).push(inventory[category][index].toJSON<IEquipmentClient>());
|
||||
return inventoryChanges;
|
||||
};
|
||||
|
||||
export const addCustomization = async (customizatonName: string, accountId: string): Promise<IFlavourItem> => {
|
||||
const inventory = await getInventory(accountId);
|
||||
const flavourItemIndex = inventory.FlavourItems.push({ ItemType: customizatonName }) - 1;
|
||||
const changedInventory = await inventory.save();
|
||||
return changedInventory.FlavourItems[flavourItemIndex].toJSON();
|
||||
export const addCustomization = (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
customizationName: string,
|
||||
inventoryChanges: IInventoryChanges = {}
|
||||
): IInventoryChanges => {
|
||||
const flavourItemIndex = inventory.FlavourItems.push({ ItemType: customizationName }) - 1;
|
||||
inventoryChanges.FlavourItems ??= [];
|
||||
(inventoryChanges.FlavourItems as IFlavourItem[]).push(
|
||||
inventory.FlavourItems[flavourItemIndex].toJSON<IFlavourItem>()
|
||||
);
|
||||
return inventoryChanges;
|
||||
};
|
||||
|
||||
export const addSkin = async (typeName: string, accountId: string): Promise<IWeaponSkinClient> => {
|
||||
const inventory = await getInventory(accountId);
|
||||
export const addSkin = (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
typeName: string,
|
||||
inventoryChanges: IInventoryChanges = {}
|
||||
): IInventoryChanges => {
|
||||
const index = inventory.WeaponSkins.push({ ItemType: typeName }) - 1;
|
||||
const changedInventory = await inventory.save();
|
||||
return changedInventory.WeaponSkins[index].toJSON() as object as IWeaponSkinClient;
|
||||
inventoryChanges.WeaponSkins ??= [];
|
||||
(inventoryChanges.WeaponSkins as IWeaponSkinClient[]).push(
|
||||
inventory.WeaponSkins[index].toJSON<IWeaponSkinClient>()
|
||||
);
|
||||
return inventoryChanges;
|
||||
};
|
||||
|
||||
const addCrewShip = async (typeName: string, accountId: string) => {
|
||||
const inventory = await getInventory(accountId);
|
||||
const addCrewShip = (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
typeName: string,
|
||||
inventoryChanges: IInventoryChanges = {}
|
||||
): IInventoryChanges => {
|
||||
const index = inventory.CrewShips.push({ ItemType: typeName }) - 1;
|
||||
const changedInventory = await inventory.save();
|
||||
return changedInventory.CrewShips[index].toJSON();
|
||||
inventoryChanges.CrewShips ??= [];
|
||||
(inventoryChanges.CrewShips as object[]).push(inventory.CrewShips[index].toJSON());
|
||||
return inventoryChanges;
|
||||
};
|
||||
|
||||
const addGearExpByCategory = (
|
||||
inventory: IInventoryDatabaseDocument,
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
gearArray: IEquipmentClient[] | undefined,
|
||||
categoryName: TEquipmentKey
|
||||
): void => {
|
||||
@ -622,7 +626,7 @@ const addGearExpByCategory = (
|
||||
});
|
||||
};
|
||||
|
||||
export const addMiscItems = (inventory: IInventoryDatabaseDocument, itemsArray: IMiscItem[] | undefined): void => {
|
||||
export const addMiscItems = (inventory: TInventoryDatabaseDocument, itemsArray: IMiscItem[] | undefined): void => {
|
||||
const { MiscItems } = inventory;
|
||||
|
||||
itemsArray?.forEach(({ ItemCount, ItemType }) => {
|
||||
@ -638,7 +642,7 @@ export const addMiscItems = (inventory: IInventoryDatabaseDocument, itemsArray:
|
||||
};
|
||||
|
||||
export const addShipDecorations = (
|
||||
inventory: IInventoryDatabaseDocument,
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
itemsArray: IConsumable[] | undefined
|
||||
): void => {
|
||||
const { ShipDecorations } = inventory;
|
||||
@ -655,7 +659,7 @@ export const addShipDecorations = (
|
||||
});
|
||||
};
|
||||
|
||||
export const addConsumables = (inventory: IInventoryDatabaseDocument, itemsArray: IConsumable[] | undefined): void => {
|
||||
export const addConsumables = (inventory: TInventoryDatabaseDocument, itemsArray: IConsumable[] | undefined): void => {
|
||||
const { Consumables } = inventory;
|
||||
|
||||
itemsArray?.forEach(({ ItemCount, ItemType }) => {
|
||||
@ -670,7 +674,7 @@ export const addConsumables = (inventory: IInventoryDatabaseDocument, itemsArray
|
||||
});
|
||||
};
|
||||
|
||||
export const addRecipes = (inventory: IInventoryDatabaseDocument, itemsArray: ITypeCount[] | undefined): void => {
|
||||
export const addRecipes = (inventory: TInventoryDatabaseDocument, itemsArray: ITypeCount[] | undefined): void => {
|
||||
const { Recipes } = inventory;
|
||||
|
||||
itemsArray?.forEach(({ ItemCount, ItemType }) => {
|
||||
@ -685,7 +689,7 @@ export const addRecipes = (inventory: IInventoryDatabaseDocument, itemsArray: IT
|
||||
});
|
||||
};
|
||||
|
||||
export const addMods = (inventory: IInventoryDatabaseDocument, itemsArray: IRawUpgrade[] | undefined): void => {
|
||||
export const addMods = (inventory: TInventoryDatabaseDocument, itemsArray: IRawUpgrade[] | undefined): void => {
|
||||
const { RawUpgrades } = inventory;
|
||||
itemsArray?.forEach(({ ItemType, ItemCount }) => {
|
||||
const itemIndex = RawUpgrades.findIndex(i => i.ItemType === ItemType);
|
||||
@ -700,7 +704,7 @@ export const addMods = (inventory: IInventoryDatabaseDocument, itemsArray: IRawU
|
||||
};
|
||||
|
||||
export const addFusionTreasures = (
|
||||
inventory: IInventoryDatabaseDocument,
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
itemsArray: IFusionTreasure[] | undefined
|
||||
): void => {
|
||||
const { FusionTreasures } = inventory;
|
||||
@ -729,7 +733,7 @@ export const updateChallengeProgress = async (
|
||||
};
|
||||
|
||||
export const addSeasonalChallengeHistory = (
|
||||
inventory: IInventoryDatabaseDocument,
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
itemsArray: ISeasonChallenge[] | undefined
|
||||
): void => {
|
||||
const category = inventory.SeasonChallengeHistory;
|
||||
@ -746,7 +750,7 @@ export const addSeasonalChallengeHistory = (
|
||||
};
|
||||
|
||||
export const addChallenges = (
|
||||
inventory: IInventoryDatabaseDocument,
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
itemsArray: IChallengeProgress[] | undefined
|
||||
): void => {
|
||||
const category = inventory.ChallengeProgress;
|
||||
@ -763,7 +767,7 @@ export const addChallenges = (
|
||||
});
|
||||
};
|
||||
|
||||
const addMissionComplete = (inventory: IInventoryDatabaseDocument, { Tag, Completes }: IMission): void => {
|
||||
const addMissionComplete = (inventory: TInventoryDatabaseDocument, { Tag, Completes }: IMission): void => {
|
||||
const { Missions } = inventory;
|
||||
const itemIndex = Missions.findIndex(item => item.Tag === Tag);
|
||||
|
||||
@ -865,7 +869,7 @@ export const addBooster = async (ItemType: string, time: number, accountId: stri
|
||||
existingBooster.ExpiryDate = Math.max(existingBooster.ExpiryDate, currentTime) + time;
|
||||
inventory.markModified(`Boosters.${itemIndex}.ExpiryDate`);
|
||||
} else {
|
||||
Boosters.push({ ItemType, ExpiryDate: currentTime + time }) - 1;
|
||||
Boosters.push({ ItemType, ExpiryDate: currentTime + time });
|
||||
}
|
||||
|
||||
await inventory.save();
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { getIndexAfter } from "@/src/helpers/stringHelpers";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import {
|
||||
dict_de,
|
||||
dict_en,
|
||||
@ -54,7 +53,6 @@ export const getWeaponType = (weaponName: string): WeaponTypeInternal => {
|
||||
const weaponType = weaponInfo.productCategory;
|
||||
|
||||
if (!weaponType) {
|
||||
logger.error(`unknown weapon category for item ${weaponName}`);
|
||||
throw new Error(`unknown weapon category for item ${weaponName}`);
|
||||
}
|
||||
|
||||
@ -83,7 +81,6 @@ export const getItemCategoryByUniqueName = (uniqueName: string): string => {
|
||||
|
||||
const index = getIndexAfter(uniqueName, splitWord);
|
||||
if (index === -1) {
|
||||
logger.error(`error parsing item category ${uniqueName}`);
|
||||
throw new Error(`error parsing item category ${uniqueName}`);
|
||||
}
|
||||
const category = uniqueName.substring(index).split("/")[0];
|
||||
|
@ -1,12 +1,10 @@
|
||||
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
|
||||
export const getLoadout = async (accountId: string) => {
|
||||
const loadout = await Loadout.findOne({ loadoutOwnerId: accountId });
|
||||
|
||||
if (!loadout) {
|
||||
logger.error(`loadout not found for account ${accountId}`);
|
||||
throw new Error("loadout not found");
|
||||
throw new Error(`loadout not found for account ${accountId}`);
|
||||
}
|
||||
|
||||
return loadout;
|
||||
|
@ -1,12 +1,10 @@
|
||||
import { PersonalRooms } from "@/src/models/personalRoomsModel";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
|
||||
export const getPersonalRooms = async (accountId: string) => {
|
||||
const personalRooms = await PersonalRooms.findOne({ personalRoomsOwnerId: accountId });
|
||||
|
||||
if (!personalRooms) {
|
||||
logger.error(`personal rooms not found for account ${accountId}`);
|
||||
throw new Error("personal rooms not found");
|
||||
throw new Error(`personal rooms not found for account ${accountId}`);
|
||||
}
|
||||
return personalRooms;
|
||||
};
|
||||
|
@ -204,9 +204,12 @@ export const handleStoreItemAcquisition = async (
|
||||
}
|
||||
}
|
||||
switch (storeCategory) {
|
||||
default:
|
||||
purchaseResponse = await addItem(accountId, internalName, quantity);
|
||||
default: {
|
||||
const inventory = await getInventory(accountId);
|
||||
purchaseResponse = await addItem(inventory, internalName, quantity);
|
||||
await inventory.save();
|
||||
break;
|
||||
}
|
||||
case "Types":
|
||||
purchaseResponse = await handleTypesPurchase(internalName, accountId, quantity);
|
||||
break;
|
||||
@ -237,7 +240,8 @@ export const slotPurchaseNameToSlotName: SlotPurchase = {
|
||||
// // number of frames = extra - slots + 2
|
||||
const handleSlotPurchase = async (
|
||||
slotPurchaseNameFull: string,
|
||||
accountId: string
|
||||
accountId: string,
|
||||
quantity: number
|
||||
): Promise<{ InventoryChanges: IInventoryChanges }> => {
|
||||
logger.debug(`slot name ${slotPurchaseNameFull}`);
|
||||
const slotPurchaseName = parseSlotPurchaseName(
|
||||
@ -246,19 +250,21 @@ const handleSlotPurchase = async (
|
||||
logger.debug(`slot purchase name ${slotPurchaseName}`);
|
||||
|
||||
const slotName = slotPurchaseNameToSlotName[slotPurchaseName].name;
|
||||
const slotsPerPurchase = slotPurchaseNameToSlotName[slotPurchaseName].slotsPerPurchase;
|
||||
const slotsPurchased = slotPurchaseNameToSlotName[slotPurchaseName].slotsPerPurchase * quantity;
|
||||
|
||||
await updateSlots(accountId, slotName, slotsPerPurchase, slotsPerPurchase);
|
||||
const inventory = await getInventory(accountId);
|
||||
updateSlots(inventory, slotName, slotsPurchased, slotsPurchased);
|
||||
await inventory.save();
|
||||
|
||||
logger.debug(`added ${slotsPerPurchase} slot ${slotName}`);
|
||||
logger.debug(`added ${slotsPurchased} slot ${slotName}`);
|
||||
|
||||
return {
|
||||
InventoryChanges: {
|
||||
[slotName]: {
|
||||
count: 0,
|
||||
platinum: 1,
|
||||
Slots: slotsPerPurchase,
|
||||
Extra: slotsPerPurchase
|
||||
Slots: slotsPurchased,
|
||||
Extra: slotsPurchased
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -277,6 +283,7 @@ const handleBoosterPackPurchase = async (
|
||||
BoosterPackItems: "",
|
||||
InventoryChanges: {}
|
||||
};
|
||||
const inventory = await getInventory(accountId);
|
||||
for (let i = 0; i != quantity; ++i) {
|
||||
for (const weights of pack.rarityWeightsPerRoll) {
|
||||
const result = getRandomWeightedReward(pack.components, weights);
|
||||
@ -286,11 +293,12 @@ const handleBoosterPackPurchase = async (
|
||||
result.type.split("/Lotus/").join("/Lotus/StoreItems/") + ',{"lvl":0};';
|
||||
combineInventoryChanges(
|
||||
purchaseResponse.InventoryChanges,
|
||||
(await addItem(accountId, result.type, result.itemCount)).InventoryChanges
|
||||
(await addItem(inventory, result.type, result.itemCount)).InventoryChanges
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
await inventory.save();
|
||||
return purchaseResponse;
|
||||
};
|
||||
|
||||
@ -303,12 +311,16 @@ const handleTypesPurchase = async (
|
||||
const typeCategory = getStoreItemTypesCategory(typesName);
|
||||
logger.debug(`type category ${typeCategory}`);
|
||||
switch (typeCategory) {
|
||||
default:
|
||||
return await addItem(accountId, typesName, quantity);
|
||||
default: {
|
||||
const inventory = await getInventory(accountId);
|
||||
const resp = await addItem(inventory, typesName, quantity);
|
||||
await inventory.save();
|
||||
return resp;
|
||||
}
|
||||
case "BoosterPacks":
|
||||
return await handleBoosterPackPurchase(typesName, accountId, quantity);
|
||||
case "SlotItems":
|
||||
return await handleSlotPurchase(typesName, accountId);
|
||||
return await handleSlotPurchase(typesName, accountId, quantity);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -47,7 +47,6 @@ export const handleSetShipDecorations = async (
|
||||
const roomToPlaceIn = rooms.find(room => room.Name === placedDecoration.Room);
|
||||
|
||||
if (!roomToPlaceIn) {
|
||||
logger.error("room not found");
|
||||
throw new Error("room not found");
|
||||
}
|
||||
|
||||
@ -59,7 +58,6 @@ export const handleSetShipDecorations = async (
|
||||
);
|
||||
|
||||
if (existingDecorationIndex === -1) {
|
||||
logger.error("decoration to be moved not found");
|
||||
throw new Error("decoration to be moved not found");
|
||||
}
|
||||
|
||||
@ -143,13 +141,11 @@ export const handleSetPlacedDecoInfo = async (accountId: string, req: ISetPlaced
|
||||
|
||||
const room = personalRooms.Ship.Rooms.find(room => room.Name === req.Room);
|
||||
if (!room) {
|
||||
logger.error("room not found");
|
||||
throw new Error("room not found");
|
||||
}
|
||||
|
||||
const placedDeco = room.PlacedDecos?.find(x => x._id.toString() == req.DecoId);
|
||||
if (!placedDeco) {
|
||||
logger.error("deco not found");
|
||||
throw new Error("deco not found");
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { Ship } from "@/src/models/shipModel";
|
||||
import { ILoadoutDatabase } from "@/src/types/saveLoadoutTypes";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { Types } from "mongoose";
|
||||
|
||||
export const createShip = async (
|
||||
@ -26,7 +25,6 @@ export const getShip = async (shipId: Types.ObjectId, fieldSelection: string = "
|
||||
const ship = await Ship.findOne({ _id: shipId }, fieldSelection);
|
||||
|
||||
if (!ship) {
|
||||
logger.error(`error finding a ship with id ${shipId.toString()}`);
|
||||
throw new Error(`error finding a ship with id ${shipId.toString()}`);
|
||||
}
|
||||
|
||||
@ -39,7 +37,6 @@ export const getShipLean = async (shipOwnerId: string) => {
|
||||
}>("LoadOutInventory.LoadOutPresets");
|
||||
|
||||
if (!ship) {
|
||||
logger.error(`error finding a ship for account ${shipOwnerId}`);
|
||||
throw new Error(`error finding a ship for account ${shipOwnerId}`);
|
||||
}
|
||||
|
||||
|
@ -78,8 +78,9 @@ export interface IEquipmentSelection {
|
||||
hide?: boolean;
|
||||
}
|
||||
|
||||
export interface IEquipmentClient extends Omit<IEquipmentDatabase, "_id"> {
|
||||
export interface IEquipmentClient extends Omit<IEquipmentDatabase, "_id" | "UpgradesExpiry"> {
|
||||
ItemId: IOid;
|
||||
UpgradesExpiry?: IMongoDate;
|
||||
}
|
||||
|
||||
export enum EquipmentFeatures {
|
||||
@ -112,6 +113,9 @@ export interface IEquipmentDatabase {
|
||||
UnlockLevel?: number;
|
||||
Expiry?: IMongoDate;
|
||||
SkillTree?: string;
|
||||
OffensiveUpgrade?: string;
|
||||
DefensiveUpgrade?: string;
|
||||
UpgradesExpiry?: Date;
|
||||
ArchonCrystalUpgrades?: IArchonCrystalUpgrade[];
|
||||
_id: Types.ObjectId;
|
||||
}
|
||||
|
@ -10,8 +10,6 @@ import {
|
||||
IEquipmentDatabase
|
||||
} from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||
|
||||
//Document extends will be deleted soon. TODO: delete and migrate uses to ...
|
||||
export interface IInventoryDatabaseDocument extends IInventoryDatabase, Document {}
|
||||
export interface IInventoryDatabase
|
||||
extends Omit<
|
||||
IInventoryResponse,
|
||||
@ -515,13 +513,15 @@ export interface IFusionTreasure {
|
||||
Sockets: number;
|
||||
}
|
||||
|
||||
export interface IHelminthFoodRecord {
|
||||
ItemType: string;
|
||||
Date: number;
|
||||
}
|
||||
|
||||
export interface IHelminthResource {
|
||||
ItemType: string;
|
||||
Count: number;
|
||||
RecentlyConvertedResources?: {
|
||||
ItemType: string;
|
||||
Date: number;
|
||||
}[];
|
||||
RecentlyConvertedResources?: IHelminthFoodRecord[];
|
||||
}
|
||||
|
||||
export interface IInfestedFoundry {
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { IInfestedFoundry } from "./inventoryTypes/inventoryTypes";
|
||||
|
||||
export interface IPurchaseRequest {
|
||||
PurchaseParams: IPurchaseParams;
|
||||
buildLabel: string;
|
||||
@ -25,8 +27,10 @@ export interface ICurrencyChanges {
|
||||
|
||||
export type IInventoryChanges = {
|
||||
[_ in SlotNames]?: IBinChanges;
|
||||
} & ICurrencyChanges &
|
||||
Record<string, IBinChanges | number | object[]>;
|
||||
} & ICurrencyChanges & { InfestedFoundry?: IInfestedFoundry } & Record<
|
||||
string,
|
||||
IBinChanges | number | object[] | IInfestedFoundry
|
||||
>;
|
||||
|
||||
export interface IPurchaseResponse {
|
||||
InventoryChanges: IInventoryChanges;
|
||||
|
@ -4346,5 +4346,17 @@
|
||||
{
|
||||
"scans": 9999,
|
||||
"type": "/Lotus/Weapons/Infested/Melee/InfBoomerang/InfBoomerangSpawnAvatar"
|
||||
},
|
||||
{
|
||||
"scans": 9999,
|
||||
"type": "/Lotus/Types/Game/CrewShip/GrineerDestroyer/DeepSpace/GrineerDSDestroyerAvatar"
|
||||
},
|
||||
{
|
||||
"scans": 9999,
|
||||
"type": "/Lotus/Types/Game/CrewShip/GrineerDestroyer/Saturn/GrineerSaturnDestroyerAvatar"
|
||||
},
|
||||
{
|
||||
"scans": 9999,
|
||||
"type": "/Lotus/Types/Game/CrewShip/GrineerDestroyer/GrineerDestroyerAvatar"
|
||||
}
|
||||
]
|
||||
|
3856
static/fixed_responses/getSkuCatalog.json
Normal file
3856
static/fixed_responses/getSkuCatalog.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -278,7 +278,8 @@
|
||||
<div class="card mb-4">
|
||||
<h5 class="card-header">Account</h5>
|
||||
<div class="card-body">
|
||||
<button class="btn btn-primary" onclick="doUnlockAllFocusSchools();">Unlock All Focus Schools</button>
|
||||
<p><button class="btn btn-primary" onclick="doUnlockAllFocusSchools();">Unlock All Focus Schools</button></p>
|
||||
<button class="btn btn-primary" onclick="doHelminthUnlockAll();">Fully Level Up Helminth</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -956,6 +956,12 @@ function unlockFocusSchool(upgradeType) {
|
||||
});
|
||||
}
|
||||
|
||||
function doHelminthUnlockAll() {
|
||||
revalidateAuthz(() => {
|
||||
$.post("/api/infestedFoundry.php?" + window.authz + "&mode=custom_unlockall");
|
||||
});
|
||||
}
|
||||
|
||||
// Powersuit Route
|
||||
|
||||
single.getRoute("#powersuit-route").on("beforeload", function () {
|
||||
|
Loading…
x
Reference in New Issue
Block a user