Merge branch 'main' of https://github.com/spaceninjaserver/SpaceNinjaServer
This commit is contained in:
commit
c3065e38c2
@ -17,6 +17,8 @@
|
|||||||
"completeAllQuests": true,
|
"completeAllQuests": true,
|
||||||
"infiniteCredits": true,
|
"infiniteCredits": true,
|
||||||
"infinitePlatinum": true,
|
"infinitePlatinum": true,
|
||||||
|
"infiniteEndo": true,
|
||||||
|
"infiniteRegalAya": true,
|
||||||
"unlockAllShipFeatures": true,
|
"unlockAllShipFeatures": true,
|
||||||
"unlockAllShipDecorations": true,
|
"unlockAllShipDecorations": true,
|
||||||
"unlockAllFlavourItems": true,
|
"unlockAllFlavourItems": true,
|
||||||
|
8
package-lock.json
generated
8
package-lock.json
generated
@ -12,7 +12,7 @@
|
|||||||
"copyfiles": "^2.4.1",
|
"copyfiles": "^2.4.1",
|
||||||
"express": "^5",
|
"express": "^5",
|
||||||
"mongoose": "^8.9.2",
|
"mongoose": "^8.9.2",
|
||||||
"warframe-public-export-plus": "^0.5.19",
|
"warframe-public-export-plus": "^0.5.21",
|
||||||
"warframe-riven-info": "^0.1.2",
|
"warframe-riven-info": "^0.1.2",
|
||||||
"winston": "^3.17.0",
|
"winston": "^3.17.0",
|
||||||
"winston-daily-rotate-file": "^5.0.0"
|
"winston-daily-rotate-file": "^5.0.0"
|
||||||
@ -3778,9 +3778,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/warframe-public-export-plus": {
|
"node_modules/warframe-public-export-plus": {
|
||||||
"version": "0.5.19",
|
"version": "0.5.21",
|
||||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.19.tgz",
|
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.21.tgz",
|
||||||
"integrity": "sha512-ERCPAe4ojJXts6tyNPBvNsFcgAwJuV3M04iDfXhudJfpJrg0qseDO4AExjSyFo+WUvKoWROMCy9dCRzxIbNATw=="
|
"integrity": "sha512-06k63L99wfX+lPx7ReYzGiMK/7NtNEiO97r+kemrtn4QIEKCfvBvmKiJcYbkSo79x35CQ+6FQfMtDilf6DGz6Q=="
|
||||||
},
|
},
|
||||||
"node_modules/warframe-riven-info": {
|
"node_modules/warframe-riven-info": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
"copyfiles": "^2.4.1",
|
"copyfiles": "^2.4.1",
|
||||||
"express": "^5",
|
"express": "^5",
|
||||||
"mongoose": "^8.9.2",
|
"mongoose": "^8.9.2",
|
||||||
"warframe-public-export-plus": "^0.5.19",
|
"warframe-public-export-plus": "^0.5.21",
|
||||||
"warframe-riven-info": "^0.1.2",
|
"warframe-riven-info": "^0.1.2",
|
||||||
"winston": "^3.17.0",
|
"winston": "^3.17.0",
|
||||||
"winston-daily-rotate-file": "^5.0.0"
|
"winston-daily-rotate-file": "^5.0.0"
|
||||||
|
98
src/controllers/api/activateRandomModController.ts
Normal file
98
src/controllers/api/activateRandomModController.ts
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
|
import { addMods, getInventory } from "@/src/services/inventoryService";
|
||||||
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
import { getRandomElement, getRandomInt, getRandomReward, IRngResult } from "@/src/services/rngService";
|
||||||
|
import { logger } from "@/src/utils/logger";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
import { ExportUpgrades } from "warframe-public-export-plus";
|
||||||
|
|
||||||
|
export const activateRandomModController: RequestHandler = async (req, res) => {
|
||||||
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
const inventory = await getInventory(accountId);
|
||||||
|
const request = getJSONfromString(String(req.body)) as IActiveRandomModRequest;
|
||||||
|
addMods(inventory, [
|
||||||
|
{
|
||||||
|
ItemType: request.ItemType,
|
||||||
|
ItemCount: -1
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
const rivenType = getRandomElement(rivenRawToRealWeighted[request.ItemType]);
|
||||||
|
const challenge = getRandomElement(ExportUpgrades[rivenType].availableChallenges!);
|
||||||
|
const fingerprintChallenge: IRandomModChallenge = {
|
||||||
|
Type: challenge.fullName,
|
||||||
|
Progress: 0,
|
||||||
|
Required: getRandomInt(challenge.countRange[0], challenge.countRange[1])
|
||||||
|
};
|
||||||
|
if (Math.random() < challenge.complicationChance) {
|
||||||
|
const complicationsAsRngResults: IRngResult[] = [];
|
||||||
|
for (const complication of challenge.complications) {
|
||||||
|
complicationsAsRngResults.push({
|
||||||
|
type: complication.fullName,
|
||||||
|
itemCount: 1,
|
||||||
|
probability: complication.weight
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fingerprintChallenge.Complication = getRandomReward(complicationsAsRngResults)!.type;
|
||||||
|
logger.debug(
|
||||||
|
`riven rolled challenge ${fingerprintChallenge.Type} with complication ${fingerprintChallenge.Complication}`
|
||||||
|
);
|
||||||
|
const complication = challenge.complications.find(x => x.fullName == fingerprintChallenge.Complication)!;
|
||||||
|
fingerprintChallenge.Required *= complication.countMultiplier;
|
||||||
|
} else {
|
||||||
|
logger.debug(`riven rolled challenge ${fingerprintChallenge.Type}`);
|
||||||
|
}
|
||||||
|
const upgradeIndex =
|
||||||
|
inventory.Upgrades.push({
|
||||||
|
ItemType: rivenType,
|
||||||
|
UpgradeFingerprint: JSON.stringify({ challenge: fingerprintChallenge })
|
||||||
|
}) - 1;
|
||||||
|
await inventory.save();
|
||||||
|
res.json({
|
||||||
|
NewMod: inventory.Upgrades[upgradeIndex].toJSON()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
interface IActiveRandomModRequest {
|
||||||
|
ItemType: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IRandomModChallenge {
|
||||||
|
Type: string;
|
||||||
|
Progress: number;
|
||||||
|
Required: number;
|
||||||
|
Complication?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rivenRawToRealWeighted: Record<string, string[]> = {
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/RawArchgunRandomMod": [
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusArchgunRandomModRare"
|
||||||
|
],
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/RawMeleeRandomMod": [
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/PlayerMeleeWeaponRandomModRare"
|
||||||
|
],
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/RawModularMeleeRandomMod": [
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusModularMeleeRandomModRare"
|
||||||
|
],
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/RawModularPistolRandomMod": [
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusModularPistolRandomModRare"
|
||||||
|
],
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/RawPistolRandomMod": ["/Lotus/Upgrades/Mods/Randomized/LotusPistolRandomModRare"],
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/RawRifleRandomMod": ["/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare"],
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/RawShotgunRandomMod": [
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusShotgunRandomModRare"
|
||||||
|
],
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/RawSentinelWeaponRandomMod": [
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusShotgunRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusPistolRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/PlayerMeleeWeaponRandomModRare"
|
||||||
|
]
|
||||||
|
};
|
@ -59,6 +59,30 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
logger.debug("Claiming Recipe", { recipe, pendingRecipe });
|
logger.debug("Claiming Recipe", { recipe, pendingRecipe });
|
||||||
|
|
||||||
|
if (recipe.secretIngredientAction == "SIA_SPECTRE_LOADOUT_COPY") {
|
||||||
|
const inventory = await getInventory(accountId);
|
||||||
|
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);
|
||||||
|
await inventory.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let InventoryChanges = {};
|
let InventoryChanges = {};
|
||||||
if (recipe.consumeOnUse) {
|
if (recipe.consumeOnUse) {
|
||||||
const recipeChanges = [
|
const recipeChanges = [
|
||||||
|
99
src/controllers/api/getVoidProjectionRewardsController.ts
Normal file
99
src/controllers/api/getVoidProjectionRewardsController.ts
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
|
import { addMiscItems, getInventory } from "@/src/services/inventoryService";
|
||||||
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
||||||
|
import { getRandomWeightedReward2 } from "@/src/services/rngService";
|
||||||
|
import { ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
|
import { logger } from "@/src/utils/logger";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
import { ExportRelics, ExportRewards, TRarity } from "warframe-public-export-plus";
|
||||||
|
|
||||||
|
export const getVoidProjectionRewardsController: RequestHandler = async (req, res) => {
|
||||||
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
const data = getJSONfromString(String(req.body)) as IVoidProjectionRewardRequest;
|
||||||
|
const response: IVoidProjectionRewardResponse = {
|
||||||
|
CurrentWave: data.CurrentWave,
|
||||||
|
ParticipantInfo: data.ParticipantInfo,
|
||||||
|
DifficultyTier: data.DifficultyTier
|
||||||
|
};
|
||||||
|
if (data.ParticipantInfo.QualifiesForReward) {
|
||||||
|
const relic = ExportRelics[data.ParticipantInfo.VoidProjection];
|
||||||
|
const weights = refinementToWeights[relic.quality];
|
||||||
|
logger.debug(`opening a relic of quality ${relic.quality}; rarity weights are`, weights);
|
||||||
|
const reward = getRandomWeightedReward2(
|
||||||
|
ExportRewards[relic.rewardManifest][0] as { type: string; itemCount: number; rarity: TRarity }[], // rarity is nullable in PE+ typings, but always present for relics
|
||||||
|
weights
|
||||||
|
)!;
|
||||||
|
logger.debug(`relic rolled`, reward);
|
||||||
|
response.ParticipantInfo.Reward = reward.type;
|
||||||
|
|
||||||
|
// Remove relic
|
||||||
|
const inventory = await getInventory(accountId);
|
||||||
|
addMiscItems(inventory, [
|
||||||
|
{
|
||||||
|
ItemType: data.ParticipantInfo.VoidProjection,
|
||||||
|
ItemCount: -1
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
await inventory.save();
|
||||||
|
|
||||||
|
// Give reward
|
||||||
|
await handleStoreItemAcquisition(reward.type, accountId, reward.itemCount);
|
||||||
|
}
|
||||||
|
res.json(response);
|
||||||
|
};
|
||||||
|
|
||||||
|
const refinementToWeights = {
|
||||||
|
VPQ_BRONZE: {
|
||||||
|
COMMON: 0.76,
|
||||||
|
UNCOMMON: 0.22,
|
||||||
|
RARE: 0.02,
|
||||||
|
LEGENDARY: 0
|
||||||
|
},
|
||||||
|
VPQ_SILVER: {
|
||||||
|
COMMON: 0.7,
|
||||||
|
UNCOMMON: 0.26,
|
||||||
|
RARE: 0.04,
|
||||||
|
LEGENDARY: 0
|
||||||
|
},
|
||||||
|
VPQ_GOLD: {
|
||||||
|
COMMON: 0.6,
|
||||||
|
UNCOMMON: 0.34,
|
||||||
|
RARE: 0.06,
|
||||||
|
LEGENDARY: 0
|
||||||
|
},
|
||||||
|
VPQ_PLATINUM: {
|
||||||
|
COMMON: 0.5,
|
||||||
|
UNCOMMON: 0.4,
|
||||||
|
RARE: 0.1,
|
||||||
|
LEGENDARY: 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
interface IVoidProjectionRewardRequest {
|
||||||
|
CurrentWave: number;
|
||||||
|
ParticipantInfo: IParticipantInfo;
|
||||||
|
VoidTier: string;
|
||||||
|
DifficultyTier: number;
|
||||||
|
VoidProjectionRemovalHash: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IVoidProjectionRewardResponse {
|
||||||
|
CurrentWave: number;
|
||||||
|
ParticipantInfo: IParticipantInfo;
|
||||||
|
DifficultyTier: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IParticipantInfo {
|
||||||
|
AccountId: string;
|
||||||
|
Name: string;
|
||||||
|
ChosenRewardOwner: string;
|
||||||
|
MissionHash: string;
|
||||||
|
VoidProjection: string;
|
||||||
|
Reward: string;
|
||||||
|
QualifiesForReward: boolean;
|
||||||
|
HaveRewardResponse: boolean;
|
||||||
|
RewardsMultiplier: number;
|
||||||
|
RewardProjection: string;
|
||||||
|
HardModeReward: ITypeCount;
|
||||||
|
}
|
@ -3,7 +3,13 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
|
|||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
import { getInventory, addMiscItems, updateCurrency, addRecipes } from "@/src/services/inventoryService";
|
import { getInventory, addMiscItems, updateCurrency, addRecipes } from "@/src/services/inventoryService";
|
||||||
import { IOid } from "@/src/types/commonTypes";
|
import { IOid } from "@/src/types/commonTypes";
|
||||||
import { IConsumedSuit, IInfestedFoundry, IMiscItem, ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
|
import {
|
||||||
|
IConsumedSuit,
|
||||||
|
IHelminthFoodRecord,
|
||||||
|
IInfestedFoundry,
|
||||||
|
IMiscItem,
|
||||||
|
ITypeCount
|
||||||
|
} from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
import { ExportMisc, ExportRecipes } from "warframe-public-export-plus";
|
import { ExportMisc, ExportRecipes } from "warframe-public-export-plus";
|
||||||
import { getRecipe } from "@/src/services/itemDataService";
|
import { getRecipe } from "@/src/services/itemDataService";
|
||||||
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
||||||
@ -46,14 +52,33 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
|
|||||||
const request = getJSONfromString(String(req.body)) as IShardUninstallRequest;
|
const request = getJSONfromString(String(req.body)) as IShardUninstallRequest;
|
||||||
const inventory = await getInventory(accountId);
|
const inventory = await getInventory(accountId);
|
||||||
const suit = inventory.Suits.find(suit => suit._id.toString() == request.SuitId.$oid)!;
|
const suit = inventory.Suits.find(suit => suit._id.toString() == request.SuitId.$oid)!;
|
||||||
|
|
||||||
|
// refund shard
|
||||||
|
const shard = Object.entries(colorToShard).find(
|
||||||
|
([color]) => color == suit.ArchonCrystalUpgrades![request.Slot].Color
|
||||||
|
)![1];
|
||||||
|
const miscItemChanges = [
|
||||||
|
{
|
||||||
|
ItemType: shard,
|
||||||
|
ItemCount: 1
|
||||||
|
}
|
||||||
|
];
|
||||||
|
addMiscItems(inventory, miscItemChanges);
|
||||||
|
|
||||||
|
// remove from suit
|
||||||
suit.ArchonCrystalUpgrades![request.Slot] = {};
|
suit.ArchonCrystalUpgrades![request.Slot] = {};
|
||||||
|
|
||||||
|
// remove bile
|
||||||
const bile = inventory.InfestedFoundry!.Resources!.find(
|
const bile = inventory.InfestedFoundry!.Resources!.find(
|
||||||
x => x.ItemType == "/Lotus/Types/Items/InfestedFoundry/HelminthBile"
|
x => x.ItemType == "/Lotus/Types/Items/InfestedFoundry/HelminthBile"
|
||||||
)!;
|
)!;
|
||||||
bile.Count -= 300;
|
bile.Count -= 300;
|
||||||
|
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
InventoryChanges: {
|
InventoryChanges: {
|
||||||
|
MiscItems: miscItemChanges,
|
||||||
InfestedFoundry: inventory.toJSON().InfestedFoundry
|
InfestedFoundry: inventory.toJSON().InfestedFoundry
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -92,6 +117,34 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
|
|||||||
for (const contribution of request.ResourceContributions) {
|
for (const contribution of request.ResourceContributions) {
|
||||||
const snack = ExportMisc.helminthSnacks[contribution.ItemType];
|
const snack = ExportMisc.helminthSnacks[contribution.ItemType];
|
||||||
|
|
||||||
|
// tally items for removal
|
||||||
|
const change = miscItemChanges.find(x => x.ItemType == contribution.ItemType);
|
||||||
|
if (change) {
|
||||||
|
change.ItemCount -= snack.count;
|
||||||
|
} else {
|
||||||
|
miscItemChanges.push({ ItemType: contribution.ItemType, ItemCount: snack.count * -1 });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snack.type == "/Lotus/Types/Items/InfestedFoundry/HelminthAppetiteCooldownReducer") {
|
||||||
|
// sentinent apetite
|
||||||
|
let mostDislikedSnackRecord: IHelminthFoodRecord = { ItemType: "", Date: 0 };
|
||||||
|
for (const resource of inventory.InfestedFoundry.Resources) {
|
||||||
|
if (resource.RecentlyConvertedResources) {
|
||||||
|
for (const record of resource.RecentlyConvertedResources) {
|
||||||
|
if (record.Date > mostDislikedSnackRecord.Date) {
|
||||||
|
mostDislikedSnackRecord = record;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.debug("helminth eats sentient resource; most disliked snack:", {
|
||||||
|
type: mostDislikedSnackRecord.ItemType,
|
||||||
|
date: mostDislikedSnackRecord.Date
|
||||||
|
});
|
||||||
|
mostDislikedSnackRecord.Date = currentUnixSeconds + 24 * 60 * 60; // Possibly unfaithful
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let resource = inventory.InfestedFoundry.Resources.find(x => x.ItemType == snack.type);
|
let resource = inventory.InfestedFoundry.Resources.find(x => x.ItemType == snack.type);
|
||||||
if (!resource) {
|
if (!resource) {
|
||||||
resource =
|
resource =
|
||||||
@ -116,21 +169,13 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
|
|||||||
apetiteFactor
|
apetiteFactor
|
||||||
});
|
});
|
||||||
if (hoursRemaining >= 18) {
|
if (hoursRemaining >= 18) {
|
||||||
record.Date = currentUnixSeconds + 72 * 60 * 60;
|
record.Date = currentUnixSeconds + 72 * 60 * 60; // Possibly unfaithful
|
||||||
} else {
|
} else {
|
||||||
record.Date = currentUnixSeconds + 24 * 60 * 60;
|
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.
|
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.
|
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) {
|
|
||||||
change.ItemCount -= snack.count;
|
|
||||||
} else {
|
|
||||||
miscItemChanges.push({ ItemType: contribution.ItemType, ItemCount: snack.count * -1 });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const recipeChanges = addInfestedFoundryXP(inventory.InfestedFoundry, 666 * totalPercentagePointsGained);
|
const recipeChanges = addInfestedFoundryXP(inventory.InfestedFoundry, 666 * totalPercentagePointsGained);
|
||||||
@ -435,6 +480,8 @@ interface IHelminthInvigorationRequest {
|
|||||||
ResourceCosts: number[];
|
ResourceCosts: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A fitted model for observed apetite values. Likely slightly inaccurate.
|
||||||
|
//
|
||||||
// Hours remaining, percentage points gained (out of 30 total)
|
// Hours remaining, percentage points gained (out of 30 total)
|
||||||
// 0, 30
|
// 0, 30
|
||||||
// 5, 25.8
|
// 5, 25.8
|
||||||
|
@ -74,6 +74,12 @@ export const inventoryController: RequestHandler = async (request, response) =>
|
|||||||
inventoryResponse.PremiumCreditsFree = 999999999;
|
inventoryResponse.PremiumCreditsFree = 999999999;
|
||||||
inventoryResponse.PremiumCredits = 999999999;
|
inventoryResponse.PremiumCredits = 999999999;
|
||||||
}
|
}
|
||||||
|
if (config.infiniteEndo) {
|
||||||
|
inventoryResponse.FusionPoints = 999999999;
|
||||||
|
}
|
||||||
|
if (config.infiniteRegalAya) {
|
||||||
|
inventoryResponse.PrimeTokens = 999999999;
|
||||||
|
}
|
||||||
|
|
||||||
if (config.skipAllDialogue) {
|
if (config.skipAllDialogue) {
|
||||||
inventoryResponse.TauntHistory = [
|
inventoryResponse.TauntHistory = [
|
||||||
|
31
src/controllers/api/playerSkillsController.ts
Normal file
31
src/controllers/api/playerSkillsController.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
|
import { getInventory } from "@/src/services/inventoryService";
|
||||||
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
import { IPlayerSkills } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
|
export const playerSkillsController: RequestHandler = async (req, res) => {
|
||||||
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
const inventory = await getInventory(accountId);
|
||||||
|
const request = getJSONfromString(String(req.body)) as IPlayerSkillsRequest;
|
||||||
|
|
||||||
|
const oldRank: number = inventory.PlayerSkills[request.Skill as keyof IPlayerSkills];
|
||||||
|
const cost = (request.Pool == "LPP_DRIFTER" ? drifterCosts[oldRank] : 1 << oldRank) * 1000;
|
||||||
|
inventory.PlayerSkills[request.Pool as keyof IPlayerSkills] -= cost;
|
||||||
|
inventory.PlayerSkills[request.Skill as keyof IPlayerSkills]++;
|
||||||
|
await inventory.save();
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
Pool: request.Pool,
|
||||||
|
PoolInc: -cost,
|
||||||
|
Skill: request.Skill,
|
||||||
|
Rank: oldRank + 1
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
interface IPlayerSkillsRequest {
|
||||||
|
Pool: string;
|
||||||
|
Skill: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const drifterCosts = [20, 25, 30, 45, 65, 90, 125, 160, 205, 255];
|
@ -1,5 +1,4 @@
|
|||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
import { ISellRequest } from "@/src/types/sellTypes";
|
|
||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { getInventory, addMods, addRecipes, addMiscItems, addConsumables } from "@/src/services/inventoryService";
|
import { getInventory, addMods, addRecipes, addMiscItems, addConsumables } from "@/src/services/inventoryService";
|
||||||
|
|
||||||
@ -100,3 +99,30 @@ export const sellController: RequestHandler = async (req, res) => {
|
|||||||
await inventory.save();
|
await inventory.save();
|
||||||
res.json({});
|
res.json({});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface ISellRequest {
|
||||||
|
Items: {
|
||||||
|
Suits?: ISellItem[];
|
||||||
|
LongGuns?: ISellItem[];
|
||||||
|
Pistols?: ISellItem[];
|
||||||
|
Melee?: ISellItem[];
|
||||||
|
Consumables?: ISellItem[];
|
||||||
|
Recipes?: ISellItem[];
|
||||||
|
Upgrades?: ISellItem[];
|
||||||
|
MiscItems?: ISellItem[];
|
||||||
|
};
|
||||||
|
SellPrice: number;
|
||||||
|
SellCurrency:
|
||||||
|
| "SC_RegularCredits"
|
||||||
|
| "SC_PrimeBucks"
|
||||||
|
| "SC_FusionPoints"
|
||||||
|
| "SC_DistillPoints"
|
||||||
|
| "SC_CrewShipFusionPoints"
|
||||||
|
| "SC_Resources";
|
||||||
|
buildLabel: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISellItem {
|
||||||
|
String: string; // oid or uniqueName
|
||||||
|
Count: number;
|
||||||
|
}
|
||||||
|
@ -2,11 +2,23 @@ import { RequestHandler } from "express";
|
|||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { getPersonalRooms } from "@/src/services/personalRoomsService";
|
import { getPersonalRooms } from "@/src/services/personalRoomsService";
|
||||||
import { TBootLocation } from "@/src/types/shipTypes";
|
import { TBootLocation } from "@/src/types/shipTypes";
|
||||||
|
import { getInventory } from "@/src/services/inventoryService";
|
||||||
|
|
||||||
export const setBootLocationController: RequestHandler = async (req, res) => {
|
export const setBootLocationController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
const personalRooms = await getPersonalRooms(accountId);
|
const personalRooms = await getPersonalRooms(accountId);
|
||||||
personalRooms.Ship.BootLocation = req.query.bootLocation as string as TBootLocation;
|
personalRooms.Ship.BootLocation = req.query.bootLocation as string as TBootLocation;
|
||||||
await personalRooms.save();
|
await personalRooms.save();
|
||||||
|
|
||||||
|
if (personalRooms.Ship.BootLocation == "SHOP") {
|
||||||
|
// Temp fix so the motorcycle in the backroom doesn't appear broken.
|
||||||
|
// This code may be removed when quests are fully implemented.
|
||||||
|
const inventory = await getInventory(accountId);
|
||||||
|
if (inventory.Motorcycles.length == 0) {
|
||||||
|
inventory.Motorcycles.push({ ItemType: "/Lotus/Types/Vehicles/Motorcycle/MotorcyclePowerSuit" });
|
||||||
|
await inventory.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
res.end();
|
res.end();
|
||||||
};
|
};
|
||||||
|
@ -6,6 +6,7 @@ import { getRecipe } from "@/src/services/itemDataService";
|
|||||||
import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inventoryService";
|
import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inventoryService";
|
||||||
import { unixTimesInMs } from "@/src/constants/timeConstants";
|
import { unixTimesInMs } from "@/src/constants/timeConstants";
|
||||||
import { Types } from "mongoose";
|
import { Types } from "mongoose";
|
||||||
|
import { ISpectreLoadout } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
|
|
||||||
interface IStartRecipeRequest {
|
interface IStartRecipeRequest {
|
||||||
RecipeName: string;
|
RecipeName: string;
|
||||||
@ -43,6 +44,59 @@ export const startRecipeController: RequestHandler = async (req, res) => {
|
|||||||
_id: new Types.ObjectId()
|
_id: new Types.ObjectId()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (recipe.secretIngredientAction == "SIA_SPECTRE_LOADOUT_COPY") {
|
||||||
|
const spectreLoadout: ISpectreLoadout = {
|
||||||
|
ItemType: recipe.resultType,
|
||||||
|
Suits: "",
|
||||||
|
LongGuns: "",
|
||||||
|
Pistols: "",
|
||||||
|
Melee: ""
|
||||||
|
};
|
||||||
|
for (
|
||||||
|
let secretIngredientsIndex = 0;
|
||||||
|
secretIngredientsIndex != recipe.secretIngredients!.length;
|
||||||
|
++secretIngredientsIndex
|
||||||
|
) {
|
||||||
|
const type = recipe.secretIngredients![secretIngredientsIndex].ItemType;
|
||||||
|
const oid = startRecipeRequest.Ids[recipe.ingredients.length + secretIngredientsIndex];
|
||||||
|
if (oid == "ffffffffffffffffffffffff") {
|
||||||
|
// user chose to preserve the active loadout
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (type == "/Lotus/Types/Game/PowerSuits/PlayerPowerSuit") {
|
||||||
|
const item = inventory.Suits.find(x => x._id.toString() == oid)!;
|
||||||
|
spectreLoadout.Suits = item.ItemType;
|
||||||
|
} else if (type == "/Lotus/Weapons/Tenno/Pistol/LotusPistol") {
|
||||||
|
const item = inventory.Pistols.find(x => x._id.toString() == oid)!;
|
||||||
|
spectreLoadout.Pistols = item.ItemType;
|
||||||
|
spectreLoadout.PistolsModularParts = item.ModularParts;
|
||||||
|
} else if (type == "/Lotus/Weapons/Tenno/LotusLongGun") {
|
||||||
|
const item = inventory.LongGuns.find(x => x._id.toString() == oid)!;
|
||||||
|
spectreLoadout.LongGuns = item.ItemType;
|
||||||
|
spectreLoadout.LongGunsModularParts = item.ModularParts;
|
||||||
|
} else {
|
||||||
|
console.assert(type == "/Lotus/Types/Game/LotusMeleeWeapon");
|
||||||
|
const item = inventory.Melee.find(x => x._id.toString() == oid)!;
|
||||||
|
spectreLoadout.Melee = item.ItemType;
|
||||||
|
spectreLoadout.MeleeModularParts = item.ModularParts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
spectreLoadout.Suits != "" &&
|
||||||
|
spectreLoadout.LongGuns != "" &&
|
||||||
|
spectreLoadout.Pistols != "" &&
|
||||||
|
spectreLoadout.Melee != ""
|
||||||
|
) {
|
||||||
|
inventory.PendingSpectreLoadouts ??= [];
|
||||||
|
const existingIndex = inventory.PendingSpectreLoadouts.findIndex(x => x.ItemType == recipe.resultType);
|
||||||
|
if (existingIndex != -1) {
|
||||||
|
inventory.PendingSpectreLoadouts.splice(existingIndex, 1);
|
||||||
|
}
|
||||||
|
inventory.PendingSpectreLoadouts.push(spectreLoadout);
|
||||||
|
logger.debug("pending spectre loadout", spectreLoadout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const newInventory = await inventory.save();
|
const newInventory = await inventory.save();
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
|
@ -1,29 +1,21 @@
|
|||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { ExportSyndicates } from "warframe-public-export-plus";
|
import { ExportSyndicates, ISyndicateSacrifice } from "warframe-public-export-plus";
|
||||||
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
||||||
import { getInventory } from "@/src/services/inventoryService";
|
import { addMiscItems, combineInventoryChanges, getInventory, updateCurrency } from "@/src/services/inventoryService";
|
||||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
||||||
|
|
||||||
export const syndicateSacrificeController: RequestHandler = async (request, response) => {
|
export const syndicateSacrificeController: RequestHandler = async (request, response) => {
|
||||||
const accountId = await getAccountIdForRequest(request);
|
const accountId = await getAccountIdForRequest(request);
|
||||||
const inventory = await getInventory(accountId);
|
const inventory = await getInventory(accountId);
|
||||||
const data = getJSONfromString(String(request.body)) as ISyndicateSacrifice;
|
const data = getJSONfromString(String(request.body)) as ISyndicateSacrificeRequest;
|
||||||
|
|
||||||
let syndicate = inventory.Affiliations.find(x => x.Tag == data.AffiliationTag);
|
let syndicate = inventory.Affiliations.find(x => x.Tag == data.AffiliationTag);
|
||||||
if (!syndicate) {
|
if (!syndicate) {
|
||||||
syndicate = inventory.Affiliations[inventory.Affiliations.push({ Tag: data.AffiliationTag, Standing: 0 }) - 1];
|
syndicate = inventory.Affiliations[inventory.Affiliations.push({ Tag: data.AffiliationTag, Standing: 0 }) - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
let reward: string | undefined;
|
|
||||||
|
|
||||||
const manifest = ExportSyndicates[data.AffiliationTag];
|
|
||||||
if (manifest?.initiationReward && data.SacrificeLevel == 0) {
|
|
||||||
reward = manifest.initiationReward;
|
|
||||||
syndicate.Initiated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const level = data.SacrificeLevel - (syndicate.Title ?? 0);
|
const level = data.SacrificeLevel - (syndicate.Title ?? 0);
|
||||||
const res: ISyndicateSacrificeResponse = {
|
const res: ISyndicateSacrificeResponse = {
|
||||||
AffiliationTag: data.AffiliationTag,
|
AffiliationTag: data.AffiliationTag,
|
||||||
@ -33,18 +25,43 @@ export const syndicateSacrificeController: RequestHandler = async (request, resp
|
|||||||
NewEpisodeReward: syndicate?.Tag == "RadioLegionIntermission9Syndicate"
|
NewEpisodeReward: syndicate?.Tag == "RadioLegionIntermission9Syndicate"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const manifest = ExportSyndicates[data.AffiliationTag];
|
||||||
|
let sacrifice: ISyndicateSacrifice | undefined;
|
||||||
|
let reward: string | undefined;
|
||||||
|
if (data.SacrificeLevel == 0) {
|
||||||
|
sacrifice = manifest.initiationSacrifice;
|
||||||
|
reward = manifest.initiationReward;
|
||||||
|
syndicate.Initiated = true;
|
||||||
|
} else {
|
||||||
|
sacrifice = manifest.titles?.find(x => x.level == data.SacrificeLevel)?.sacrifice;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sacrifice) {
|
||||||
|
res.InventoryChanges = { ...updateCurrency(inventory, sacrifice.credits, false) };
|
||||||
|
|
||||||
|
const miscItemChanges = sacrifice.items.map(x => ({
|
||||||
|
ItemType: x.ItemType,
|
||||||
|
ItemCount: x.ItemCount * -1
|
||||||
|
}));
|
||||||
|
addMiscItems(inventory, miscItemChanges);
|
||||||
|
res.InventoryChanges.MiscItems = miscItemChanges;
|
||||||
|
}
|
||||||
|
|
||||||
if (syndicate?.Title !== undefined) syndicate.Title += 1;
|
if (syndicate?.Title !== undefined) syndicate.Title += 1;
|
||||||
|
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
|
|
||||||
if (reward) {
|
if (reward) {
|
||||||
res.InventoryChanges = (await handleStoreItemAcquisition(reward, accountId)).InventoryChanges;
|
combineInventoryChanges(
|
||||||
|
res.InventoryChanges,
|
||||||
|
(await handleStoreItemAcquisition(reward, accountId)).InventoryChanges
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
response.json(res);
|
response.json(res);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface ISyndicateSacrifice {
|
interface ISyndicateSacrificeRequest {
|
||||||
AffiliationTag: string;
|
AffiliationTag: string;
|
||||||
SacrificeLevel: number;
|
SacrificeLevel: number;
|
||||||
AllowMultiple: boolean;
|
AllowMultiple: boolean;
|
||||||
|
@ -439,18 +439,17 @@ const seasonChallengeHistorySchema = new Schema<ISeasonChallenge>(
|
|||||||
//TODO: check whether this is complete
|
//TODO: check whether this is complete
|
||||||
const playerSkillsSchema = new Schema<IPlayerSkills>(
|
const playerSkillsSchema = new Schema<IPlayerSkills>(
|
||||||
{
|
{
|
||||||
LPP_SPACE: Number,
|
LPP_SPACE: { type: Number, default: 0 },
|
||||||
LPP_DRIFTER: Number,
|
LPS_PILOTING: { type: Number, default: 0 },
|
||||||
LPS_NONE: Number,
|
LPS_GUNNERY: { type: Number, default: 0 },
|
||||||
LPS_PILOTING: Number,
|
LPS_TACTICAL: { type: Number, default: 0 },
|
||||||
LPS_GUNNERY: Number,
|
LPS_ENGINEERING: { type: Number, default: 0 },
|
||||||
LPS_TACTICAL: Number,
|
LPS_COMMAND: { type: Number, default: 0 },
|
||||||
LPS_ENGINEERING: Number,
|
LPP_DRIFTER: { type: Number, default: 0 },
|
||||||
LPS_COMMAND: Number,
|
LPS_DRIFT_COMBAT: { type: Number, default: 0 },
|
||||||
LPS_DRIFT_COMBAT: Number,
|
LPS_DRIFT_RIDING: { type: Number, default: 0 },
|
||||||
LPS_DRIFT_RIDING: Number,
|
LPS_DRIFT_OPPORTUNITY: { type: Number, default: 0 },
|
||||||
LPS_DRIFT_OPPORTUNITY: Number,
|
LPS_DRIFT_ENDURANCE: { type: Number, default: 0 }
|
||||||
LPS_DRIFT_ENDURANCE: Number
|
|
||||||
},
|
},
|
||||||
{ _id: false }
|
{ _id: false }
|
||||||
);
|
);
|
||||||
@ -548,13 +547,14 @@ const fusionTreasuresSchema = new Schema<IFusionTreasure>().add(typeCountSchema)
|
|||||||
|
|
||||||
const spectreLoadoutsSchema = new Schema<ISpectreLoadout>(
|
const spectreLoadoutsSchema = new Schema<ISpectreLoadout>(
|
||||||
{
|
{
|
||||||
LongGuns: String,
|
ItemType: String,
|
||||||
Melee: String,
|
|
||||||
Pistols: String,
|
|
||||||
PistolsFeatures: Number,
|
|
||||||
PistolsModularParts: [String],
|
|
||||||
Suits: String,
|
Suits: String,
|
||||||
ItemType: String
|
LongGuns: String,
|
||||||
|
LongGunsModularParts: { type: [String], default: undefined },
|
||||||
|
Pistols: String,
|
||||||
|
PistolsModularParts: { type: [String], default: undefined },
|
||||||
|
Melee: String,
|
||||||
|
MeleeModularParts: { type: [String], default: undefined }
|
||||||
},
|
},
|
||||||
{ _id: false }
|
{ _id: false }
|
||||||
);
|
);
|
||||||
@ -936,11 +936,9 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
|||||||
QualifyingInvasions: [Schema.Types.Mixed],
|
QualifyingInvasions: [Schema.Types.Mixed],
|
||||||
FactionScores: [Number],
|
FactionScores: [Number],
|
||||||
|
|
||||||
//Have only Suit+Pistols+LongGuns+Melee+ItemType(BronzeSpectre,GoldSpectre,PlatinumSpectreArmy,SilverSpectreArmy)
|
// https://warframe.fandom.com/wiki/Specter_(Tenno)
|
||||||
//"/Lotus/Types/Game/SpectreArmies/BronzeSpectreArmy": "Vapor Specter Regiment",
|
PendingSpectreLoadouts: { type: [spectreLoadoutsSchema], default: undefined },
|
||||||
SpectreLoadouts: [spectreLoadoutsSchema],
|
SpectreLoadouts: { type: [spectreLoadoutsSchema], default: undefined },
|
||||||
//If you want change Spectre Gear id
|
|
||||||
PendingSpectreLoadouts: [Schema.Types.Mixed],
|
|
||||||
|
|
||||||
//New Quest Email
|
//New Quest Email
|
||||||
EmailItems: [TypeXPItemSchema],
|
EmailItems: [TypeXPItemSchema],
|
||||||
@ -1019,7 +1017,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
|||||||
|
|
||||||
//Modulars lvl and exp(Railjack|Duviri)
|
//Modulars lvl and exp(Railjack|Duviri)
|
||||||
//https://warframe.fandom.com/wiki/Intrinsics
|
//https://warframe.fandom.com/wiki/Intrinsics
|
||||||
PlayerSkills: playerSkillsSchema,
|
PlayerSkills: { type: playerSkillsSchema, default: {} },
|
||||||
|
|
||||||
//TradeBannedUntil data
|
//TradeBannedUntil data
|
||||||
TradeBannedUntil: Schema.Types.Mixed,
|
TradeBannedUntil: Schema.Types.Mixed,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import express from "express";
|
import express from "express";
|
||||||
|
import { activateRandomModController } from "@/src/controllers/api/activateRandomModController";
|
||||||
import { addFriendImageController } from "@/src/controllers/api/addFriendImageController";
|
import { addFriendImageController } from "@/src/controllers/api/addFriendImageController";
|
||||||
import { arcaneCommonController } from "@/src/controllers/api/arcaneCommonController";
|
import { arcaneCommonController } from "@/src/controllers/api/arcaneCommonController";
|
||||||
import { artifactsController } from "../controllers/api/artifactsController";
|
import { artifactsController } from "../controllers/api/artifactsController";
|
||||||
@ -26,6 +27,7 @@ import { getIgnoredUsersController } from "@/src/controllers/api/getIgnoredUsers
|
|||||||
import { getNewRewardSeedController } from "@/src/controllers/api/getNewRewardSeedController";
|
import { getNewRewardSeedController } from "@/src/controllers/api/getNewRewardSeedController";
|
||||||
import { getShipController } from "@/src/controllers/api/getShipController";
|
import { getShipController } from "@/src/controllers/api/getShipController";
|
||||||
import { getVendorInfoController } from "@/src/controllers/api/getVendorInfoController";
|
import { getVendorInfoController } from "@/src/controllers/api/getVendorInfoController";
|
||||||
|
import { getVoidProjectionRewardsController } from "@/src/controllers/api/getVoidProjectionRewardsController";
|
||||||
import { gildWeaponController } from "@/src/controllers/api/gildWeaponController";
|
import { gildWeaponController } from "@/src/controllers/api/gildWeaponController";
|
||||||
import { guildTechController } from "../controllers/api/guildTechController";
|
import { guildTechController } from "../controllers/api/guildTechController";
|
||||||
import { hostSessionController } from "@/src/controllers/api/hostSessionController";
|
import { hostSessionController } from "@/src/controllers/api/hostSessionController";
|
||||||
@ -44,6 +46,7 @@ import { missionInventoryUpdateController } from "@/src/controllers/api/missionI
|
|||||||
import { modularWeaponCraftingController } from "@/src/controllers/api/modularWeaponCraftingController";
|
import { modularWeaponCraftingController } from "@/src/controllers/api/modularWeaponCraftingController";
|
||||||
import { modularWeaponSaleController } from "@/src/controllers/api/modularWeaponSaleController";
|
import { modularWeaponSaleController } from "@/src/controllers/api/modularWeaponSaleController";
|
||||||
import { nameWeaponController } from "@/src/controllers/api/nameWeaponController";
|
import { nameWeaponController } from "@/src/controllers/api/nameWeaponController";
|
||||||
|
import { playerSkillsController } from "@/src/controllers/api/playerSkillsController";
|
||||||
import { projectionManagerController } from "../controllers/api/projectionManagerController";
|
import { projectionManagerController } from "../controllers/api/projectionManagerController";
|
||||||
import { purchaseController } from "@/src/controllers/api/purchaseController";
|
import { purchaseController } from "@/src/controllers/api/purchaseController";
|
||||||
import { queueDojoComponentDestructionController } from "@/src/controllers/api/queueDojoComponentDestructionController";
|
import { queueDojoComponentDestructionController } from "@/src/controllers/api/queueDojoComponentDestructionController";
|
||||||
@ -107,6 +110,7 @@ apiRouter.get("/surveys.php", surveysController);
|
|||||||
apiRouter.get("/updateSession.php", updateSessionGetController);
|
apiRouter.get("/updateSession.php", updateSessionGetController);
|
||||||
|
|
||||||
// post
|
// post
|
||||||
|
apiRouter.post("/activateRandomMod.php", activateRandomModController);
|
||||||
apiRouter.post("/addFriendImage.php", addFriendImageController);
|
apiRouter.post("/addFriendImage.php", addFriendImageController);
|
||||||
apiRouter.post("/arcaneCommon.php", arcaneCommonController);
|
apiRouter.post("/arcaneCommon.php", arcaneCommonController);
|
||||||
apiRouter.post("/artifacts.php", artifactsController);
|
apiRouter.post("/artifacts.php", artifactsController);
|
||||||
@ -120,6 +124,7 @@ apiRouter.post("/focus.php", focusController);
|
|||||||
apiRouter.post("/fusionTreasures.php", fusionTreasuresController);
|
apiRouter.post("/fusionTreasures.php", fusionTreasuresController);
|
||||||
apiRouter.post("/genericUpdate.php", genericUpdateController);
|
apiRouter.post("/genericUpdate.php", genericUpdateController);
|
||||||
apiRouter.post("/getAlliance.php", getAllianceController);
|
apiRouter.post("/getAlliance.php", getAllianceController);
|
||||||
|
apiRouter.post("/getVoidProjectionRewards.php", getVoidProjectionRewardsController);
|
||||||
apiRouter.post("/gildWeapon.php", gildWeaponController);
|
apiRouter.post("/gildWeapon.php", gildWeaponController);
|
||||||
apiRouter.post("/guildTech.php", guildTechController);
|
apiRouter.post("/guildTech.php", guildTechController);
|
||||||
apiRouter.post("/hostSession.php", hostSessionController);
|
apiRouter.post("/hostSession.php", hostSessionController);
|
||||||
@ -130,6 +135,7 @@ apiRouter.post("/login.php", loginController);
|
|||||||
apiRouter.post("/missionInventoryUpdate.php", missionInventoryUpdateController);
|
apiRouter.post("/missionInventoryUpdate.php", missionInventoryUpdateController);
|
||||||
apiRouter.post("/modularWeaponCrafting.php", modularWeaponCraftingController);
|
apiRouter.post("/modularWeaponCrafting.php", modularWeaponCraftingController);
|
||||||
apiRouter.post("/nameWeapon.php", nameWeaponController);
|
apiRouter.post("/nameWeapon.php", nameWeaponController);
|
||||||
|
apiRouter.post("/playerSkills.php", playerSkillsController);
|
||||||
apiRouter.post("/projectionManager.php", projectionManagerController);
|
apiRouter.post("/projectionManager.php", projectionManagerController);
|
||||||
apiRouter.post("/purchase.php", purchaseController);
|
apiRouter.post("/purchase.php", purchaseController);
|
||||||
apiRouter.post("/rerollRandomMod.php", rerollRandomModController);
|
apiRouter.post("/rerollRandomMod.php", rerollRandomModController);
|
||||||
|
@ -43,6 +43,8 @@ interface IConfig {
|
|||||||
completeAllQuests?: boolean;
|
completeAllQuests?: boolean;
|
||||||
infiniteCredits?: boolean;
|
infiniteCredits?: boolean;
|
||||||
infinitePlatinum?: boolean;
|
infinitePlatinum?: boolean;
|
||||||
|
infiniteEndo?: boolean;
|
||||||
|
infiniteRegalAya?: boolean;
|
||||||
unlockAllShipFeatures?: boolean;
|
unlockAllShipFeatures?: boolean;
|
||||||
unlockAllShipDecorations?: boolean;
|
unlockAllShipDecorations?: boolean;
|
||||||
unlockAllFlavourItems?: boolean;
|
unlockAllFlavourItems?: boolean;
|
||||||
|
@ -908,8 +908,12 @@ export const upgradeMod = async (artifactsData: IArtifactsRequest, accountId: st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!config.infiniteCredits) {
|
||||||
inventory.RegularCredits -= Cost;
|
inventory.RegularCredits -= Cost;
|
||||||
|
}
|
||||||
|
if (!config.infiniteEndo) {
|
||||||
inventory.FusionPoints -= FusionPointCost;
|
inventory.FusionPoints -= FusionPointCost;
|
||||||
|
}
|
||||||
|
|
||||||
const changedInventory = await inventory.save();
|
const changedInventory = await inventory.save();
|
||||||
const itemId = changedInventory.toJSON().Upgrades[itemIndex]?.ItemId?.$oid;
|
const itemId = changedInventory.toJSON().Upgrades[itemIndex]?.ItemId?.$oid;
|
||||||
|
@ -24,6 +24,7 @@ import {
|
|||||||
ExportVendors,
|
ExportVendors,
|
||||||
TRarity
|
TRarity
|
||||||
} from "warframe-public-export-plus";
|
} from "warframe-public-export-plus";
|
||||||
|
import { config } from "./configService";
|
||||||
|
|
||||||
export const getStoreItemCategory = (storeItem: string): string => {
|
export const getStoreItemCategory = (storeItem: string): string => {
|
||||||
const storeItemString = getSubstringFromKeyword(storeItem, "StoreItems/");
|
const storeItemString = getSubstringFromKeyword(storeItem, "StoreItems/");
|
||||||
@ -152,7 +153,7 @@ export const handlePurchase = async (
|
|||||||
|
|
||||||
purchaseResponse.InventoryChanges.MiscItems ??= [];
|
purchaseResponse.InventoryChanges.MiscItems ??= [];
|
||||||
(purchaseResponse.InventoryChanges.MiscItems as IMiscItem[]).push(invItem);
|
(purchaseResponse.InventoryChanges.MiscItems as IMiscItem[]).push(invItem);
|
||||||
} else {
|
} else if (!config.infiniteRegalAya) {
|
||||||
inventory.PrimeTokens -= offer.PrimePrice! * purchaseRequest.PurchaseParams.Quantity;
|
inventory.PrimeTokens -= offer.PrimePrice! * purchaseRequest.PurchaseParams.Quantity;
|
||||||
}
|
}
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
|
@ -6,6 +6,18 @@ export interface IRngResult {
|
|||||||
probability: number;
|
probability: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getRandomElement = <T>(arr: T[]): T => {
|
||||||
|
return arr[Math.floor(Math.random() * arr.length)];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns a random integer between min (inclusive) and max (inclusive).
|
||||||
|
// https://stackoverflow.com/a/1527820
|
||||||
|
export const getRandomInt = (min: number, max: number): number => {
|
||||||
|
min = Math.ceil(min);
|
||||||
|
max = Math.floor(max);
|
||||||
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
|
};
|
||||||
|
|
||||||
export const getRandomReward = (pool: IRngResult[]): IRngResult | undefined => {
|
export const getRandomReward = (pool: IRngResult[]): IRngResult | undefined => {
|
||||||
if (pool.length == 0) return;
|
if (pool.length == 0) return;
|
||||||
|
|
||||||
@ -40,3 +52,22 @@ export const getRandomWeightedReward = (
|
|||||||
}
|
}
|
||||||
return getRandomReward(resultPool);
|
return getRandomReward(resultPool);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getRandomWeightedReward2 = (
|
||||||
|
pool: { type: string; itemCount: number; rarity: TRarity }[],
|
||||||
|
weights: Record<TRarity, number>
|
||||||
|
): IRngResult | undefined => {
|
||||||
|
const resultPool: IRngResult[] = [];
|
||||||
|
const rarityCounts: Record<TRarity, number> = { COMMON: 0, UNCOMMON: 0, RARE: 0, LEGENDARY: 0 };
|
||||||
|
for (const entry of pool) {
|
||||||
|
++rarityCounts[entry.rarity];
|
||||||
|
}
|
||||||
|
for (const entry of pool) {
|
||||||
|
resultPool.push({
|
||||||
|
type: entry.type,
|
||||||
|
itemCount: entry.itemCount,
|
||||||
|
probability: weights[entry.rarity] / rarityCounts[entry.rarity]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return getRandomReward(resultPool);
|
||||||
|
};
|
||||||
|
@ -15,16 +15,17 @@ import DuviriAcrithisVendorManifest from "@/static/fixed_responses/getVendorInfo
|
|||||||
import EntratiLabsEntratiLabsCommisionsManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabsCommisionsManifest.json";
|
import EntratiLabsEntratiLabsCommisionsManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabsCommisionsManifest.json";
|
||||||
import EntratiLabsEntratiLabVendorManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabVendorManifest.json";
|
import EntratiLabsEntratiLabVendorManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabVendorManifest.json";
|
||||||
import HubsIronwakeDondaVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsIronwakeDondaVendorManifest.json";
|
import HubsIronwakeDondaVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsIronwakeDondaVendorManifest.json";
|
||||||
import HubsRailjackCrewMemberVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsRailjackCrewMemberVendorManifest.json";
|
|
||||||
import HubsPerrinSequenceWeaponVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsPerrinSequenceWeaponVendorManifest.json";
|
import HubsPerrinSequenceWeaponVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsPerrinSequenceWeaponVendorManifest.json";
|
||||||
|
import HubsRailjackCrewMemberVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsRailjackCrewMemberVendorManifest.json";
|
||||||
import MaskSalesmanManifest from "@/static/fixed_responses/getVendorInfo/MaskSalesmanManifest.json";
|
import MaskSalesmanManifest from "@/static/fixed_responses/getVendorInfo/MaskSalesmanManifest.json";
|
||||||
import OstronFishmongerVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronFishmongerVendorManifest.json";
|
import OstronFishmongerVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronFishmongerVendorManifest.json";
|
||||||
import OstronProspectorVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronProspectorVendorManifest.json";
|
|
||||||
import OstronPetVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronPetVendorManifest.json";
|
import OstronPetVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronPetVendorManifest.json";
|
||||||
import SolarisFishmongerVendorManifest from "@/static/fixed_responses/getVendorInfo/SolarisFishmongerVendorManifest.json";
|
import OstronProspectorVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronProspectorVendorManifest.json";
|
||||||
import SolarisProspectorVendorManifest from "@/static/fixed_responses/getVendorInfo/SolarisProspectorVendorManifest.json";
|
|
||||||
import SolarisDebtTokenVendorManifest from "@/static/fixed_responses/getVendorInfo/SolarisDebtTokenVendorManifest.json";
|
import SolarisDebtTokenVendorManifest from "@/static/fixed_responses/getVendorInfo/SolarisDebtTokenVendorManifest.json";
|
||||||
import SolarisDebtTokenVendorRepossessionsManifest from "@/static/fixed_responses/getVendorInfo/SolarisDebtTokenVendorRepossessionsManifest.json";
|
import SolarisDebtTokenVendorRepossessionsManifest from "@/static/fixed_responses/getVendorInfo/SolarisDebtTokenVendorRepossessionsManifest.json";
|
||||||
|
import SolarisFishmongerVendorManifest from "@/static/fixed_responses/getVendorInfo/SolarisFishmongerVendorManifest.json";
|
||||||
|
import SolarisProspectorVendorManifest from "@/static/fixed_responses/getVendorInfo/SolarisProspectorVendorManifest.json";
|
||||||
|
import TeshinHardModeVendorManifest from "@/static/fixed_responses/getVendorInfo/TeshinHardModeVendorManifest.json";
|
||||||
import ZarimanCommisionsManifestArchimedean from "@/static/fixed_responses/getVendorInfo/ZarimanCommisionsManifestArchimedean.json";
|
import ZarimanCommisionsManifestArchimedean from "@/static/fixed_responses/getVendorInfo/ZarimanCommisionsManifestArchimedean.json";
|
||||||
|
|
||||||
interface IVendorManifest {
|
interface IVendorManifest {
|
||||||
@ -55,16 +56,17 @@ const vendorManifests: IVendorManifest[] = [
|
|||||||
EntratiLabsEntratiLabsCommisionsManifest,
|
EntratiLabsEntratiLabsCommisionsManifest,
|
||||||
EntratiLabsEntratiLabVendorManifest,
|
EntratiLabsEntratiLabVendorManifest,
|
||||||
HubsIronwakeDondaVendorManifest,
|
HubsIronwakeDondaVendorManifest,
|
||||||
HubsRailjackCrewMemberVendorManifest,
|
|
||||||
HubsPerrinSequenceWeaponVendorManifest,
|
HubsPerrinSequenceWeaponVendorManifest,
|
||||||
|
HubsRailjackCrewMemberVendorManifest,
|
||||||
MaskSalesmanManifest,
|
MaskSalesmanManifest,
|
||||||
OstronFishmongerVendorManifest,
|
OstronFishmongerVendorManifest,
|
||||||
OstronProspectorVendorManifest,
|
|
||||||
OstronPetVendorManifest,
|
OstronPetVendorManifest,
|
||||||
SolarisFishmongerVendorManifest,
|
OstronProspectorVendorManifest,
|
||||||
SolarisProspectorVendorManifest,
|
|
||||||
SolarisDebtTokenVendorManifest,
|
SolarisDebtTokenVendorManifest,
|
||||||
SolarisDebtTokenVendorRepossessionsManifest,
|
SolarisDebtTokenVendorRepossessionsManifest,
|
||||||
|
SolarisFishmongerVendorManifest,
|
||||||
|
SolarisProspectorVendorManifest,
|
||||||
|
TeshinHardModeVendorManifest,
|
||||||
ZarimanCommisionsManifestArchimedean
|
ZarimanCommisionsManifestArchimedean
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -102,7 +102,8 @@ export type TSolarMapRegion =
|
|||||||
| "Uranus"
|
| "Uranus"
|
||||||
| "Venus"
|
| "Venus"
|
||||||
| "Void"
|
| "Void"
|
||||||
| "SolarMapDeimosName";
|
| "SolarMapDeimosName"
|
||||||
|
| "1999MapName";
|
||||||
|
|
||||||
//TODO: perhaps split response and database into their own files
|
//TODO: perhaps split response and database into their own files
|
||||||
|
|
||||||
@ -203,8 +204,8 @@ export interface IInventoryResponse {
|
|||||||
SpaceMelee: IEquipmentDatabase[];
|
SpaceMelee: IEquipmentDatabase[];
|
||||||
SpaceGuns: IEquipmentDatabase[];
|
SpaceGuns: IEquipmentDatabase[];
|
||||||
ArchwingEnabled: boolean;
|
ArchwingEnabled: boolean;
|
||||||
PendingSpectreLoadouts: any[];
|
PendingSpectreLoadouts?: ISpectreLoadout[];
|
||||||
SpectreLoadouts: ISpectreLoadout[];
|
SpectreLoadouts?: ISpectreLoadout[];
|
||||||
SentinelWeapons: IEquipmentDatabase[];
|
SentinelWeapons: IEquipmentDatabase[];
|
||||||
Sentinels: IEquipmentDatabase[];
|
Sentinels: IEquipmentDatabase[];
|
||||||
EmailItems: ITypeCount[];
|
EmailItems: ITypeCount[];
|
||||||
@ -727,6 +728,8 @@ export interface IPendingRecipe {
|
|||||||
ItemType: string;
|
ItemType: string;
|
||||||
CompletionDate: Date;
|
CompletionDate: Date;
|
||||||
ItemId: IOid;
|
ItemId: IOid;
|
||||||
|
TargetItemId?: string; // likely related to liches
|
||||||
|
TargetFingerprint?: string; // likely related to liches
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPendingTrade {
|
export interface IPendingTrade {
|
||||||
@ -816,13 +819,12 @@ export interface IPersonalTechProject {
|
|||||||
|
|
||||||
export interface IPlayerSkills {
|
export interface IPlayerSkills {
|
||||||
LPP_SPACE: number;
|
LPP_SPACE: number;
|
||||||
LPP_DRIFTER: number;
|
|
||||||
LPS_NONE: number;
|
|
||||||
LPS_PILOTING: number;
|
LPS_PILOTING: number;
|
||||||
LPS_GUNNERY: number;
|
LPS_GUNNERY: number;
|
||||||
LPS_TACTICAL: number;
|
LPS_TACTICAL: number;
|
||||||
LPS_ENGINEERING: number;
|
LPS_ENGINEERING: number;
|
||||||
LPS_COMMAND: number;
|
LPS_COMMAND: number;
|
||||||
|
LPP_DRIFTER: number;
|
||||||
LPS_DRIFT_COMBAT: number;
|
LPS_DRIFT_COMBAT: number;
|
||||||
LPS_DRIFT_RIDING: number;
|
LPS_DRIFT_RIDING: number;
|
||||||
LPS_DRIFT_OPPORTUNITY: number;
|
LPS_DRIFT_OPPORTUNITY: number;
|
||||||
@ -871,13 +873,14 @@ export interface IShipInventory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ISpectreLoadout {
|
export interface ISpectreLoadout {
|
||||||
LongGuns: string;
|
|
||||||
Melee: string;
|
|
||||||
Pistols: string;
|
|
||||||
PistolsFeatures: number;
|
|
||||||
PistolsModularParts: string[];
|
|
||||||
Suits: string;
|
|
||||||
ItemType: string;
|
ItemType: string;
|
||||||
|
Suits: string;
|
||||||
|
LongGuns: string;
|
||||||
|
LongGunsModularParts?: string[];
|
||||||
|
Pistols: string;
|
||||||
|
PistolsModularParts?: string[];
|
||||||
|
Melee: string;
|
||||||
|
MeleeModularParts?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IStepSequencer {
|
export interface IStepSequencer {
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
export interface ISellRequest {
|
|
||||||
Items: {
|
|
||||||
Suits?: ISellItem[];
|
|
||||||
LongGuns?: ISellItem[];
|
|
||||||
Pistols?: ISellItem[];
|
|
||||||
Melee?: ISellItem[];
|
|
||||||
Consumables?: ISellItem[];
|
|
||||||
Recipes?: ISellItem[];
|
|
||||||
Upgrades?: ISellItem[];
|
|
||||||
MiscItems?: ISellItem[];
|
|
||||||
};
|
|
||||||
SellPrice: number;
|
|
||||||
SellCurrency:
|
|
||||||
| "SC_RegularCredits"
|
|
||||||
| "SC_PrimeBucks"
|
|
||||||
| "SC_FusionPoints"
|
|
||||||
| "SC_DistillPoints"
|
|
||||||
| "SC_CrewShipFusionPoints"
|
|
||||||
| "SC_Resources";
|
|
||||||
buildLabel: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ISellItem {
|
|
||||||
String: string; // oid or uniqueName
|
|
||||||
Count: number;
|
|
||||||
}
|
|
@ -0,0 +1,603 @@
|
|||||||
|
{
|
||||||
|
"VendorInfo":{
|
||||||
|
"_id":{
|
||||||
|
"$oid":"63ed01efbdaa38891767bac9"
|
||||||
|
},
|
||||||
|
"TypeName":"/Lotus/Types/Game/VendorManifests/Hubs/TeshinHardModeVendorManifest",
|
||||||
|
"ItemManifest":[
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/Recipes/OperatorArmour/HardMode/OperatorTeshinArmsBlueprint",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":15,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e9947"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/Recipes/OperatorArmour/HardMode/OperatorTeshinBodyBlueprint",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":25,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e9948"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/Recipes/OperatorArmour/HardMode/OperatorTeshinHeadBlueprint",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":20,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e9949"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/Recipes/OperatorArmour/HardMode/OperatorTeshinLegsBlueprint",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":25,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e994a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/Items/MiscItems/WeaponPrimaryArcaneUnlocker",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":15,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e994b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/Items/MiscItems/WeaponSecondaryArcaneUnlocker",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":15,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e994c"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/Recipes/Components/FormaStanceBlueprint",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":10,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e994d"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Upgrades/Skins/Effects/OrbsEphemera",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":3,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e994e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Upgrades/Skins/Effects/TatsuSkullEphemera",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":85,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e994f"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Upgrades/Mods/Randomized/RawShotgunRandomMod",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":75,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PurchaseQuantityLimit":1,
|
||||||
|
"RotatedWeekly":true,
|
||||||
|
"AllowMultipurchase":false,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e9950"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/Recipes/Components/UmbraFormaBlueprint",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":150,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PurchaseQuantityLimit":1,
|
||||||
|
"RotatedWeekly":true,
|
||||||
|
"AllowMultipurchase":false,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e9951"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/Items/MiscItems/Kuva",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":55,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":50000,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PurchaseQuantityLimit":1,
|
||||||
|
"RotatedWeekly":true,
|
||||||
|
"AllowMultipurchase":false,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e9952"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Upgrades/Mods/Randomized/RawModularPistolRandomMod",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":75,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PurchaseQuantityLimit":1,
|
||||||
|
"RotatedWeekly":true,
|
||||||
|
"AllowMultipurchase":false,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e9953"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/Items/MiscItems/Forma",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":75,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":3,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PurchaseQuantityLimit":1,
|
||||||
|
"RotatedWeekly":true,
|
||||||
|
"AllowMultipurchase":false,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e9954"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Upgrades/Mods/Randomized/RawModularMeleeRandomMod",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":75,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PurchaseQuantityLimit":1,
|
||||||
|
"RotatedWeekly":true,
|
||||||
|
"AllowMultipurchase":false,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e9955"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Upgrades/Mods/FusionBundles/EvergreenLoginRewardFusionBundle",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":150,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PurchaseQuantityLimit":1,
|
||||||
|
"RotatedWeekly":true,
|
||||||
|
"AllowMultipurchase":false,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e9956"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Upgrades/Mods/Randomized/RawRifleRandomMod",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":75,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PurchaseQuantityLimit":1,
|
||||||
|
"RotatedWeekly":true,
|
||||||
|
"AllowMultipurchase":false,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e9957"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Upgrades/Mods/Shotgun/WeaponRecoilReductionMod",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":35,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e9958"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/Items/ShipDecos/TeshinBobbleHead",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":35,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e9959"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/StoreItems/AvatarImages/ImageGaussVED",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":15,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e995a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/StoreItems/AvatarImages/ImageGrendelVED",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":15,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e995b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/StoreItems/AvatarImages/AvatarImageProteaAction",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":15,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e995c"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/Items/ShipDecos/TeaSet",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":15,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e995d"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/StoreItems/AvatarImages/AvatarImageXakuAction",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":15,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e995e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/Items/MiscItems/RivenIdentifier",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":20,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PurchaseQuantityLimit":1,
|
||||||
|
"RotatedWeekly":true,
|
||||||
|
"AllowMultipurchase":false,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e995f"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/BoosterPacks/RandomSyndicateProjectionPack",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":15,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":1,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"1736726400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PurchaseQuantityLimit":25,
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e997c"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem":"/Lotus/StoreItems/Types/Items/MiscItems/Kuva",
|
||||||
|
"ItemPrices":[
|
||||||
|
{
|
||||||
|
"ItemCount":15,
|
||||||
|
"ItemType":"/Lotus/Types/Items/MiscItems/SteelEssence",
|
||||||
|
"ProductCategory":"MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin":"BIN_0",
|
||||||
|
"QuantityMultiplier":10000,
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"1736726400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PurchaseQuantityLimit":25,
|
||||||
|
"AllowMultipurchase":true,
|
||||||
|
"Id":{
|
||||||
|
"$oid":"66fd60b20ba592c4c95e997d"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"PropertyTextHash":"0A0F20AFA748FBEE490510DBF5A33A0D",
|
||||||
|
"Expiry":{
|
||||||
|
"$date":{
|
||||||
|
"$numberLong":"1736726400000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -235,6 +235,14 @@
|
|||||||
<input class="form-check-input" type="checkbox" id="infinitePlatinum" />
|
<input class="form-check-input" type="checkbox" id="infinitePlatinum" />
|
||||||
<label class="form-check-label" for="infinitePlatinum">Infinite Platinum</label>
|
<label class="form-check-label" for="infinitePlatinum">Infinite Platinum</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="infiniteEndo" />
|
||||||
|
<label class="form-check-label" for="infiniteEndo">Infinite Endo</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="infiniteRegalAya" />
|
||||||
|
<label class="form-check-label" for="infiniteRegalAya">Infinite Regal Aya</label>
|
||||||
|
</div>
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="checkbox" id="unlockAllShipFeatures" />
|
<input class="form-check-input" type="checkbox" id="unlockAllShipFeatures" />
|
||||||
<label class="form-check-label" for="unlockAllShipFeatures">Unlock All Ship Features</label>
|
<label class="form-check-label" for="unlockAllShipFeatures">Unlock All Ship Features</label>
|
||||||
|
@ -805,6 +805,8 @@ const uiConfigs = [
|
|||||||
"completeAllQuests",
|
"completeAllQuests",
|
||||||
"infiniteCredits",
|
"infiniteCredits",
|
||||||
"infinitePlatinum",
|
"infinitePlatinum",
|
||||||
|
"infiniteEndo",
|
||||||
|
"infiniteRegalAya",
|
||||||
"unlockAllShipFeatures",
|
"unlockAllShipFeatures",
|
||||||
"unlockAllShipDecorations",
|
"unlockAllShipDecorations",
|
||||||
"unlockAllFlavourItems",
|
"unlockAllFlavourItems",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user