forked from OpenWF/SpaceNinjaServer
Compare commits
25 Commits
efc7467a99
...
f3e56480e5
Author | SHA1 | Date | |
---|---|---|---|
f3e56480e5 | |||
6f46ace40c | |||
883426e429 | |||
13432bf034 | |||
a1267e5f64 | |||
2058207b6a | |||
c7c416c100 | |||
90e97d7888 | |||
3f6734ac1c | |||
6f64690b91 | |||
fb5a7320bb | |||
143b358a03 | |||
0b75757277 | |||
fd7f4c9e92 | |||
fa6fac494b | |||
6b3f524574 | |||
506365f97e | |||
70646160c3 | |||
3ffa4a7fd3 | |||
826a09a473 | |||
100aefcee4 | |||
409c089d11 | |||
8c32dc2670 | |||
a67f99b665 | |||
756a01d270 |
@ -2,15 +2,18 @@ const millisecondsPerSecond = 1000;
|
|||||||
const secondsPerMinute = 60;
|
const secondsPerMinute = 60;
|
||||||
const minutesPerHour = 60;
|
const minutesPerHour = 60;
|
||||||
const hoursPerDay = 24;
|
const hoursPerDay = 24;
|
||||||
|
const daysPerWeek = 7;
|
||||||
|
|
||||||
const unixSecond = millisecondsPerSecond;
|
const unixSecond = millisecondsPerSecond;
|
||||||
const unixMinute = secondsPerMinute * millisecondsPerSecond;
|
const unixMinute = secondsPerMinute * millisecondsPerSecond;
|
||||||
const unixHour = unixMinute * minutesPerHour;
|
const unixHour = unixMinute * minutesPerHour;
|
||||||
const unixDay = hoursPerDay * unixHour;
|
const unixDay = hoursPerDay * unixHour;
|
||||||
|
const unixWeek = daysPerWeek * unixDay;
|
||||||
|
|
||||||
export const unixTimesInMs = {
|
export const unixTimesInMs = {
|
||||||
second: unixSecond,
|
second: unixSecond,
|
||||||
minute: unixMinute,
|
minute: unixMinute,
|
||||||
hour: unixHour,
|
hour: unixHour,
|
||||||
day: unixDay
|
day: unixDay,
|
||||||
|
week: unixWeek
|
||||||
};
|
};
|
||||||
|
41
src/controllers/api/completeCalendarEventController.ts
Normal file
41
src/controllers/api/completeCalendarEventController.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { getCalendarProgress, getInventory } from "@/src/services/inventoryService";
|
||||||
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
||||||
|
import { getWorldState } from "@/src/services/worldStateService";
|
||||||
|
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
|
// GET request; query parameters: CompletedEventIdx=0&Iteration=4&Version=19&Season=CST_SUMMER
|
||||||
|
export const completeCalendarEventController: RequestHandler = async (req, res) => {
|
||||||
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
const inventory = await getInventory(accountId);
|
||||||
|
const calendarProgress = getCalendarProgress(inventory);
|
||||||
|
const currentSeason = getWorldState().KnownCalendarSeasons[0];
|
||||||
|
let inventoryChanges: IInventoryChanges = {};
|
||||||
|
let dayIndex = 0;
|
||||||
|
for (const day of currentSeason.Days) {
|
||||||
|
if (day.events.length == 0 || day.events[0].type != "CET_CHALLENGE") {
|
||||||
|
if (dayIndex == calendarProgress.SeasonProgress.LastCompletedDayIdx) {
|
||||||
|
if (day.events.length != 0) {
|
||||||
|
const selection = day.events[parseInt(req.query.CompletedEventIdx as string)];
|
||||||
|
if (selection.type == "CET_REWARD") {
|
||||||
|
inventoryChanges = (await handleStoreItemAcquisition(selection.reward!, inventory))
|
||||||
|
.InventoryChanges;
|
||||||
|
} else if (selection.type == "CET_UPGRADE") {
|
||||||
|
calendarProgress.YearProgress.Upgrades.push(selection.upgrade!);
|
||||||
|
} else if (selection.type != "CET_PLOT") {
|
||||||
|
throw new Error(`unexpected selection type: ${selection.type}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++dayIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
calendarProgress.SeasonProgress.LastCompletedDayIdx++;
|
||||||
|
await inventory.save();
|
||||||
|
res.json({
|
||||||
|
InventoryChanges: inventoryChanges,
|
||||||
|
CalendarProgress: inventory.CalendarProgress
|
||||||
|
});
|
||||||
|
};
|
@ -3,7 +3,7 @@ import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
|||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { IMissionInventoryUpdateRequest } from "@/src/types/requestTypes";
|
import { IMissionInventoryUpdateRequest } from "@/src/types/requestTypes";
|
||||||
import { addMissionInventoryUpdates, addMissionRewards } from "@/src/services/missionInventoryUpdateService";
|
import { addMissionInventoryUpdates, addMissionRewards } from "@/src/services/missionInventoryUpdateService";
|
||||||
import { getInventory } from "@/src/services/inventoryService";
|
import { generateRewardSeed, getInventory } from "@/src/services/inventoryService";
|
||||||
import { getInventoryResponse } from "./inventoryController";
|
import { getInventoryResponse } from "./inventoryController";
|
||||||
import { logger } from "@/src/utils/logger";
|
import { logger } from "@/src/utils/logger";
|
||||||
import { IMissionInventoryUpdateResponse } from "@/src/types/missionTypes";
|
import { IMissionInventoryUpdateResponse } from "@/src/types/missionTypes";
|
||||||
@ -63,6 +63,7 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
|
|||||||
missionReport.MissionStatus !== "GS_SUCCESS" &&
|
missionReport.MissionStatus !== "GS_SUCCESS" &&
|
||||||
!(missionReport.RewardInfo?.jobId || missionReport.RewardInfo?.challengeMissionId)
|
!(missionReport.RewardInfo?.jobId || missionReport.RewardInfo?.challengeMissionId)
|
||||||
) {
|
) {
|
||||||
|
inventory.RewardSeed = generateRewardSeed();
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
const inventoryResponse = await getInventoryResponse(inventory, true);
|
const inventoryResponse = await getInventoryResponse(inventory, true);
|
||||||
res.json({
|
res.json({
|
||||||
@ -81,6 +82,7 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
|
|||||||
ConquestCompletedMissionsCount
|
ConquestCompletedMissionsCount
|
||||||
} = await addMissionRewards(inventory, missionReport, firstCompletion);
|
} = await addMissionRewards(inventory, missionReport, firstCompletion);
|
||||||
|
|
||||||
|
inventory.RewardSeed = generateRewardSeed();
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
const inventoryResponse = await getInventoryResponse(inventory, true);
|
const inventoryResponse = await getInventoryResponse(inventory, true);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ import { getDefaultUpgrades } from "@/src/services/itemDataService";
|
|||||||
import { modularWeaponTypes } from "@/src/helpers/modularWeaponHelper";
|
import { modularWeaponTypes } from "@/src/helpers/modularWeaponHelper";
|
||||||
import { IEquipmentDatabase } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
import { IEquipmentDatabase } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||||
import { getRandomInt } from "@/src/services/rngService";
|
import { getRandomInt } from "@/src/services/rngService";
|
||||||
import { ExportSentinels, IDefaultUpgrade } from "warframe-public-export-plus";
|
import { ExportSentinels, ExportWeapons, IDefaultUpgrade } from "warframe-public-export-plus";
|
||||||
import { Status } from "@/src/types/inventoryTypes/inventoryTypes";
|
import { Status } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
|
|
||||||
interface IModularCraftRequest {
|
interface IModularCraftRequest {
|
||||||
@ -138,6 +138,18 @@ export const modularWeaponCraftingController: RequestHandler = async (req, res)
|
|||||||
} else {
|
} else {
|
||||||
defaultUpgrades = getDefaultUpgrades(data.Parts);
|
defaultUpgrades = getDefaultUpgrades(data.Parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (category == "MoaPets") {
|
||||||
|
const weapon = ExportSentinels[data.WeaponType].defaultWeapon;
|
||||||
|
if (weapon) {
|
||||||
|
const category = ExportWeapons[weapon].productCategory;
|
||||||
|
addEquipment(inventory, category, weapon, undefined, inventoryChanges);
|
||||||
|
combineInventoryChanges(
|
||||||
|
inventoryChanges,
|
||||||
|
occupySlot(inventory, productCategoryToInventoryBin(category)!, !!data.isWebUi)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
defaultOverwrites.Configs = applyDefaultUpgrades(inventory, defaultUpgrades);
|
defaultOverwrites.Configs = applyDefaultUpgrades(inventory, defaultUpgrades);
|
||||||
addEquipment(inventory, category, data.WeaponType, data.Parts, inventoryChanges, defaultOverwrites);
|
addEquipment(inventory, category, data.WeaponType, data.Parts, inventoryChanges, defaultOverwrites);
|
||||||
combineInventoryChanges(
|
combineInventoryChanges(
|
||||||
|
@ -45,7 +45,7 @@ export const sellController: RequestHandler = async (req, res) => {
|
|||||||
if (payload.Items.SpaceGuns || payload.Items.SpaceMelee) {
|
if (payload.Items.SpaceGuns || payload.Items.SpaceMelee) {
|
||||||
requiredFields.add(InventorySlot.SPACEWEAPONS);
|
requiredFields.add(InventorySlot.SPACEWEAPONS);
|
||||||
}
|
}
|
||||||
if (payload.Items.Sentinels || payload.Items.SentinelWeapons) {
|
if (payload.Items.Sentinels || payload.Items.SentinelWeapons || payload.Items.MoaPets) {
|
||||||
requiredFields.add(InventorySlot.SENTINELS);
|
requiredFields.add(InventorySlot.SENTINELS);
|
||||||
}
|
}
|
||||||
if (payload.Items.OperatorAmps) {
|
if (payload.Items.OperatorAmps) {
|
||||||
@ -148,6 +148,12 @@ export const sellController: RequestHandler = async (req, res) => {
|
|||||||
freeUpSlot(inventory, InventorySlot.SENTINELS);
|
freeUpSlot(inventory, InventorySlot.SENTINELS);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (payload.Items.MoaPets) {
|
||||||
|
payload.Items.MoaPets.forEach(sellItem => {
|
||||||
|
inventory.MoaPets.pull({ _id: sellItem.String });
|
||||||
|
freeUpSlot(inventory, InventorySlot.SENTINELS);
|
||||||
|
});
|
||||||
|
}
|
||||||
if (payload.Items.OperatorAmps) {
|
if (payload.Items.OperatorAmps) {
|
||||||
payload.Items.OperatorAmps.forEach(sellItem => {
|
payload.Items.OperatorAmps.forEach(sellItem => {
|
||||||
inventory.OperatorAmps.pull({ _id: sellItem.String });
|
inventory.OperatorAmps.pull({ _id: sellItem.String });
|
||||||
@ -281,6 +287,7 @@ interface ISellRequest {
|
|||||||
SpaceMelee?: ISellItem[];
|
SpaceMelee?: ISellItem[];
|
||||||
Sentinels?: ISellItem[];
|
Sentinels?: ISellItem[];
|
||||||
SentinelWeapons?: ISellItem[];
|
SentinelWeapons?: ISellItem[];
|
||||||
|
MoaPets?: ISellItem[];
|
||||||
OperatorAmps?: ISellItem[];
|
OperatorAmps?: ISellItem[];
|
||||||
Hoverboards?: ISellItem[];
|
Hoverboards?: ISellItem[];
|
||||||
Drones?: ISellItem[];
|
Drones?: ISellItem[];
|
||||||
|
@ -20,7 +20,7 @@ export const setShipFavouriteLoadoutController: RequestHandler = async (req, res
|
|||||||
throw new Error(`unexpected BootLocation: ${body.BootLocation}`);
|
throw new Error(`unexpected BootLocation: ${body.BootLocation}`);
|
||||||
}
|
}
|
||||||
await personalRooms.save();
|
await personalRooms.save();
|
||||||
res.json({});
|
res.json(body);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface ISetShipFavouriteLoadoutRequest {
|
interface ISetShipFavouriteLoadoutRequest {
|
||||||
|
@ -6,6 +6,9 @@ import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
|||||||
import { addMiscItems, combineInventoryChanges, getInventory, updateCurrency } 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";
|
||||||
import { isStoreItem, toStoreItem } from "@/src/services/itemDataService";
|
import { isStoreItem, toStoreItem } from "@/src/services/itemDataService";
|
||||||
|
import { logger } from "@/src/utils/logger";
|
||||||
|
|
||||||
|
const nightwaveCredsItemType = ExportNightwave.rewards[ExportNightwave.rewards.length - 1].uniqueName;
|
||||||
|
|
||||||
export const syndicateSacrificeController: RequestHandler = async (request, response) => {
|
export const syndicateSacrificeController: RequestHandler = async (request, response) => {
|
||||||
const accountId = await getAccountIdForRequest(request);
|
const accountId = await getAccountIdForRequest(request);
|
||||||
@ -74,10 +77,14 @@ export const syndicateSacrificeController: RequestHandler = async (request, resp
|
|||||||
if (!isStoreItem(rewardType)) {
|
if (!isStoreItem(rewardType)) {
|
||||||
rewardType = toStoreItem(rewardType);
|
rewardType = toStoreItem(rewardType);
|
||||||
}
|
}
|
||||||
combineInventoryChanges(
|
const rewardInventoryChanges = (await handleStoreItemAcquisition(rewardType, inventory, reward.itemCount))
|
||||||
res.InventoryChanges,
|
.InventoryChanges;
|
||||||
(await handleStoreItemAcquisition(rewardType, inventory, reward.itemCount)).InventoryChanges
|
if (Object.keys(rewardInventoryChanges).length == 0) {
|
||||||
);
|
logger.debug(`nightwave rank up reward did not seem to get added, giving 50 creds instead`);
|
||||||
|
rewardInventoryChanges.MiscItems = [{ ItemType: nightwaveCredsItemType, ItemCount: 50 }];
|
||||||
|
addMiscItems(inventory, rewardInventoryChanges.MiscItems);
|
||||||
|
}
|
||||||
|
combineInventoryChanges(res.InventoryChanges, rewardInventoryChanges);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import {
|
|||||||
TRelicQuality
|
TRelicQuality
|
||||||
} from "warframe-public-export-plus";
|
} from "warframe-public-export-plus";
|
||||||
import archonCrystalUpgrades from "@/static/fixed_responses/webuiArchonCrystalUpgrades.json";
|
import archonCrystalUpgrades from "@/static/fixed_responses/webuiArchonCrystalUpgrades.json";
|
||||||
|
import allIncarnons from "@/static/fixed_responses/allIncarnonList.json";
|
||||||
|
|
||||||
interface ListedItem {
|
interface ListedItem {
|
||||||
uniqueName: string;
|
uniqueName: string;
|
||||||
@ -51,6 +52,7 @@ interface ItemLists {
|
|||||||
OperatorAmps: ListedItem[];
|
OperatorAmps: ListedItem[];
|
||||||
QuestKeys: ListedItem[];
|
QuestKeys: ListedItem[];
|
||||||
KubrowPets: ListedItem[];
|
KubrowPets: ListedItem[];
|
||||||
|
EvolutionProgress: ListedItem[];
|
||||||
mods: ListedItem[];
|
mods: ListedItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,6 +84,7 @@ const getItemListsController: RequestHandler = (req, response) => {
|
|||||||
OperatorAmps: [],
|
OperatorAmps: [],
|
||||||
QuestKeys: [],
|
QuestKeys: [],
|
||||||
KubrowPets: [],
|
KubrowPets: [],
|
||||||
|
EvolutionProgress: [],
|
||||||
mods: []
|
mods: []
|
||||||
};
|
};
|
||||||
for (const [uniqueName, item] of Object.entries(ExportWarframes)) {
|
for (const [uniqueName, item] of Object.entries(ExportWarframes)) {
|
||||||
@ -283,6 +286,12 @@ const getItemListsController: RequestHandler = (req, response) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const uniqueName of allIncarnons) {
|
||||||
|
res.EvolutionProgress.push({
|
||||||
|
uniqueName,
|
||||||
|
name: getString(getItemName(uniqueName) || "", lang)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
response.json(res);
|
response.json(res);
|
||||||
};
|
};
|
||||||
|
33
src/controllers/custom/setEvolutionProgressController.ts
Normal file
33
src/controllers/custom/setEvolutionProgressController.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { getInventory } from "@/src/services/inventoryService";
|
||||||
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
|
export const setEvolutionProgressController: RequestHandler = async (req, res) => {
|
||||||
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
const inventory = await getInventory(accountId);
|
||||||
|
const payload = req.body as ISetEvolutionProgressRequest;
|
||||||
|
|
||||||
|
inventory.EvolutionProgress ??= [];
|
||||||
|
payload.forEach(element => {
|
||||||
|
const entry = inventory.EvolutionProgress!.find(entry => entry.ItemType === element.ItemType);
|
||||||
|
|
||||||
|
if (entry) {
|
||||||
|
entry.Progress = 0;
|
||||||
|
entry.Rank = element.Rank;
|
||||||
|
} else {
|
||||||
|
inventory.EvolutionProgress!.push({
|
||||||
|
Progress: 0,
|
||||||
|
Rank: element.Rank,
|
||||||
|
ItemType: element.ItemType
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await inventory.save();
|
||||||
|
res.end();
|
||||||
|
};
|
||||||
|
|
||||||
|
type ISetEvolutionProgressRequest = {
|
||||||
|
ItemType: string;
|
||||||
|
Rank: number;
|
||||||
|
}[];
|
@ -390,7 +390,7 @@ MailboxSchema.set("toJSON", {
|
|||||||
|
|
||||||
const DuviriInfoSchema = new Schema<IDuviriInfo>(
|
const DuviriInfoSchema = new Schema<IDuviriInfo>(
|
||||||
{
|
{
|
||||||
Seed: Number,
|
Seed: BigInt,
|
||||||
NumCompletions: { type: Number, default: 0 }
|
NumCompletions: { type: Number, default: 0 }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1125,15 +1125,15 @@ const CustomMarkersSchema = new Schema<ICustomMarkers>(
|
|||||||
const calenderProgressSchema = new Schema<ICalendarProgress>(
|
const calenderProgressSchema = new Schema<ICalendarProgress>(
|
||||||
{
|
{
|
||||||
Version: { type: Number, default: 19 },
|
Version: { type: Number, default: 19 },
|
||||||
Iteration: { type: Number, default: 2 },
|
Iteration: { type: Number, required: true },
|
||||||
YearProgress: {
|
YearProgress: {
|
||||||
Upgrades: { type: [] }
|
Upgrades: { type: [String], default: [] }
|
||||||
},
|
},
|
||||||
SeasonProgress: {
|
SeasonProgress: {
|
||||||
SeasonType: String,
|
SeasonType: { type: String, required: true },
|
||||||
LastCompletedDayIdx: { type: Number, default: -1 },
|
LastCompletedDayIdx: { type: Number, default: 0 },
|
||||||
LastCompletedChallengeDayIdx: { type: Number, default: -1 },
|
LastCompletedChallengeDayIdx: { type: Number, default: 0 },
|
||||||
ActivatedChallenges: []
|
ActivatedChallenges: { type: [String], default: [] }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ _id: false }
|
{ _id: false }
|
||||||
|
@ -19,6 +19,7 @@ import { claimCompletedRecipeController } from "@/src/controllers/api/claimCompl
|
|||||||
import { claimLibraryDailyTaskRewardController } from "@/src/controllers/api/claimLibraryDailyTaskRewardController";
|
import { claimLibraryDailyTaskRewardController } from "@/src/controllers/api/claimLibraryDailyTaskRewardController";
|
||||||
import { clearDialogueHistoryController } from "@/src/controllers/api/clearDialogueHistoryController";
|
import { clearDialogueHistoryController } from "@/src/controllers/api/clearDialogueHistoryController";
|
||||||
import { clearNewEpisodeRewardController } from "@/src/controllers/api/clearNewEpisodeRewardController";
|
import { clearNewEpisodeRewardController } from "@/src/controllers/api/clearNewEpisodeRewardController";
|
||||||
|
import { completeCalendarEventController } from "@/src/controllers/api/completeCalendarEventController";
|
||||||
import { completeRandomModChallengeController } from "@/src/controllers/api/completeRandomModChallengeController";
|
import { completeRandomModChallengeController } from "@/src/controllers/api/completeRandomModChallengeController";
|
||||||
import { confirmAllianceInvitationController } from "@/src/controllers/api/confirmAllianceInvitationController";
|
import { confirmAllianceInvitationController } from "@/src/controllers/api/confirmAllianceInvitationController";
|
||||||
import { confirmGuildInvitationGetController, confirmGuildInvitationPostController } from "@/src/controllers/api/confirmGuildInvitationController";
|
import { confirmGuildInvitationGetController, confirmGuildInvitationPostController } from "@/src/controllers/api/confirmGuildInvitationController";
|
||||||
@ -158,6 +159,7 @@ apiRouter.get("/changeDojoRoot.php", changeDojoRootController);
|
|||||||
apiRouter.get("/changeGuildRank.php", changeGuildRankController);
|
apiRouter.get("/changeGuildRank.php", changeGuildRankController);
|
||||||
apiRouter.get("/checkDailyMissionBonus.php", checkDailyMissionBonusController);
|
apiRouter.get("/checkDailyMissionBonus.php", checkDailyMissionBonusController);
|
||||||
apiRouter.get("/claimLibraryDailyTaskReward.php", claimLibraryDailyTaskRewardController);
|
apiRouter.get("/claimLibraryDailyTaskReward.php", claimLibraryDailyTaskRewardController);
|
||||||
|
apiRouter.get("/completeCalendarEvent.php", completeCalendarEventController);
|
||||||
apiRouter.get("/confirmAllianceInvitation.php", confirmAllianceInvitationController);
|
apiRouter.get("/confirmAllianceInvitation.php", confirmAllianceInvitationController);
|
||||||
apiRouter.get("/confirmGuildInvitation.php", confirmGuildInvitationGetController);
|
apiRouter.get("/confirmGuildInvitation.php", confirmGuildInvitationGetController);
|
||||||
apiRouter.get("/credits.php", creditsController);
|
apiRouter.get("/credits.php", creditsController);
|
||||||
|
@ -17,10 +17,11 @@ import { addCurrencyController } from "@/src/controllers/custom/addCurrencyContr
|
|||||||
import { addItemsController } from "@/src/controllers/custom/addItemsController";
|
import { addItemsController } from "@/src/controllers/custom/addItemsController";
|
||||||
import { addXpController } from "@/src/controllers/custom/addXpController";
|
import { addXpController } from "@/src/controllers/custom/addXpController";
|
||||||
import { importController } from "@/src/controllers/custom/importController";
|
import { importController } from "@/src/controllers/custom/importController";
|
||||||
|
import { manageQuestsController } from "@/src/controllers/custom/manageQuestsController";
|
||||||
|
import { setEvolutionProgressController } from "@/src/controllers/custom/setEvolutionProgressController";
|
||||||
|
|
||||||
import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController";
|
import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController";
|
||||||
import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController";
|
import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController";
|
||||||
import { manageQuestsController } from "@/src/controllers/custom/manageQuestsController";
|
|
||||||
|
|
||||||
const customRouter = express.Router();
|
const customRouter = express.Router();
|
||||||
|
|
||||||
@ -42,6 +43,7 @@ customRouter.post("/addItems", addItemsController);
|
|||||||
customRouter.post("/addXp", addXpController);
|
customRouter.post("/addXp", addXpController);
|
||||||
customRouter.post("/import", importController);
|
customRouter.post("/import", importController);
|
||||||
customRouter.post("/manageQuests", manageQuestsController);
|
customRouter.post("/manageQuests", manageQuestsController);
|
||||||
|
customRouter.post("/setEvolutionProgress", setEvolutionProgressController);
|
||||||
|
|
||||||
customRouter.get("/config", getConfigDataController);
|
customRouter.get("/config", getConfigDataController);
|
||||||
customRouter.post("/config", updateConfigDataController);
|
customRouter.post("/config", updateConfigDataController);
|
||||||
|
@ -105,6 +105,7 @@ export const getGuildClient = async (guild: TGuildDatabaseDocument, accountId: s
|
|||||||
Members: members,
|
Members: members,
|
||||||
Ranks: guild.Ranks,
|
Ranks: guild.Ranks,
|
||||||
Tier: guild.Tier,
|
Tier: guild.Tier,
|
||||||
|
Emblem: guild.Emblem,
|
||||||
Vault: getGuildVault(guild),
|
Vault: getGuildVault(guild),
|
||||||
ActiveDojoColorResearch: guild.ActiveDojoColorResearch,
|
ActiveDojoColorResearch: guild.ActiveDojoColorResearch,
|
||||||
Class: guild.Class,
|
Class: guild.Class,
|
||||||
@ -133,7 +134,7 @@ export const getGuildVault = (guild: TGuildDatabaseDocument): IGuildVault => {
|
|||||||
export const getDojoClient = async (
|
export const getDojoClient = async (
|
||||||
guild: TGuildDatabaseDocument,
|
guild: TGuildDatabaseDocument,
|
||||||
status: number,
|
status: number,
|
||||||
componentId: Types.ObjectId | string | undefined = undefined
|
componentId?: Types.ObjectId | string
|
||||||
): Promise<IDojoClient> => {
|
): Promise<IDojoClient> => {
|
||||||
const dojo: IDojoClient = {
|
const dojo: IDojoClient = {
|
||||||
_id: { $oid: guild._id.toString() },
|
_id: { $oid: guild._id.toString() },
|
||||||
@ -553,7 +554,7 @@ export const setGuildTechLogState = (
|
|||||||
guild: TGuildDatabaseDocument,
|
guild: TGuildDatabaseDocument,
|
||||||
type: string,
|
type: string,
|
||||||
state: number,
|
state: number,
|
||||||
dateTime: Date | undefined = undefined
|
dateTime?: Date
|
||||||
): boolean => {
|
): boolean => {
|
||||||
guild.TechChanges ??= [];
|
guild.TechChanges ??= [];
|
||||||
const entry = guild.TechChanges.find(x => x.details == type);
|
const entry = guild.TechChanges.find(x => x.details == type);
|
||||||
|
@ -169,6 +169,7 @@ const convertPendingRecipe = (client: IPendingRecipeClient): IPendingRecipeDatab
|
|||||||
const convertNemesis = (client: INemesisClient): INemesisDatabase => {
|
const convertNemesis = (client: INemesisClient): INemesisDatabase => {
|
||||||
return {
|
return {
|
||||||
...client,
|
...client,
|
||||||
|
fp: BigInt(client.fp),
|
||||||
d: convertDate(client.d)
|
d: convertDate(client.d)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -18,7 +18,6 @@ import {
|
|||||||
IKubrowPetEggDatabase,
|
IKubrowPetEggDatabase,
|
||||||
IKubrowPetEggClient,
|
IKubrowPetEggClient,
|
||||||
ILibraryDailyTaskInfo,
|
ILibraryDailyTaskInfo,
|
||||||
ICalendarProgress,
|
|
||||||
IDroneClient,
|
IDroneClient,
|
||||||
IUpgradeClient,
|
IUpgradeClient,
|
||||||
TPartialStartingGear,
|
TPartialStartingGear,
|
||||||
@ -26,7 +25,8 @@ import {
|
|||||||
ICrewMemberClient,
|
ICrewMemberClient,
|
||||||
Status,
|
Status,
|
||||||
IKubrowPetDetailsDatabase,
|
IKubrowPetDetailsDatabase,
|
||||||
ITraits
|
ITraits,
|
||||||
|
ICalendarProgress
|
||||||
} from "@/src/types/inventoryTypes/inventoryTypes";
|
} from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
import { IGenericUpdate, IUpdateNodeIntrosResponse } from "../types/genericUpdate";
|
import { IGenericUpdate, IUpdateNodeIntrosResponse } from "../types/genericUpdate";
|
||||||
import { IKeyChainRequest, IMissionInventoryUpdateRequest } from "../types/requestTypes";
|
import { IKeyChainRequest, IMissionInventoryUpdateRequest } from "../types/requestTypes";
|
||||||
@ -78,6 +78,7 @@ import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json";
|
|||||||
import { getRandomElement, getRandomInt, getRandomWeightedReward, SRng } from "./rngService";
|
import { getRandomElement, getRandomInt, getRandomWeightedReward, SRng } from "./rngService";
|
||||||
import { createMessage } from "./inboxService";
|
import { createMessage } from "./inboxService";
|
||||||
import { getMaxStanding } from "@/src/helpers/syndicateStandingHelper";
|
import { getMaxStanding } from "@/src/helpers/syndicateStandingHelper";
|
||||||
|
import { getWorldState } from "./worldStateService";
|
||||||
|
|
||||||
export const createInventory = async (
|
export const createInventory = async (
|
||||||
accountOwnerId: Types.ObjectId,
|
accountOwnerId: Types.ObjectId,
|
||||||
@ -91,7 +92,6 @@ export const createInventory = async (
|
|||||||
});
|
});
|
||||||
|
|
||||||
inventory.LibraryAvailableDailyTaskInfo = createLibraryDailyTask();
|
inventory.LibraryAvailableDailyTaskInfo = createLibraryDailyTask();
|
||||||
inventory.CalendarProgress = createCalendar();
|
|
||||||
inventory.RewardSeed = generateRewardSeed();
|
inventory.RewardSeed = generateRewardSeed();
|
||||||
inventory.DuviriInfo = {
|
inventory.DuviriInfo = {
|
||||||
Seed: generateRewardSeed(),
|
Seed: generateRewardSeed(),
|
||||||
@ -120,10 +120,15 @@ export const createInventory = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const generateRewardSeed = (): number => {
|
export const generateRewardSeed = (): bigint => {
|
||||||
const min = -Number.MAX_SAFE_INTEGER;
|
const hiDword = getRandomInt(0, 0x7fffffff);
|
||||||
const max = Number.MAX_SAFE_INTEGER;
|
const loDword = getRandomInt(0, 0xffffffff);
|
||||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
let seed = (BigInt(hiDword) << 32n) | BigInt(loDword);
|
||||||
|
if (Math.random() < 0.5) {
|
||||||
|
seed *= -1n;
|
||||||
|
seed -= 1n;
|
||||||
|
}
|
||||||
|
return seed;
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: RawUpgrades might need to return a LastAdded
|
//TODO: RawUpgrades might need to return a LastAdded
|
||||||
@ -138,7 +143,7 @@ const awakeningRewards = [
|
|||||||
|
|
||||||
export const addStartingGear = async (
|
export const addStartingGear = async (
|
||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
startingGear: TPartialStartingGear | undefined = undefined
|
startingGear?: TPartialStartingGear
|
||||||
): Promise<IInventoryChanges> => {
|
): Promise<IInventoryChanges> => {
|
||||||
const { LongGuns, Pistols, Suits, Melee } = startingGear || {
|
const { LongGuns, Pistols, Suits, Melee } = startingGear || {
|
||||||
LongGuns: [{ ItemType: "/Lotus/Weapons/Tenno/Rifle/Rifle" }],
|
LongGuns: [{ ItemType: "/Lotus/Weapons/Tenno/Rifle/Rifle" }],
|
||||||
@ -240,7 +245,7 @@ export const combineInventoryChanges = (InventoryChanges: IInventoryChanges, del
|
|||||||
|
|
||||||
export const getInventory = async (
|
export const getInventory = async (
|
||||||
accountOwnerId: string,
|
accountOwnerId: string,
|
||||||
projection: string | undefined = undefined
|
projection?: string
|
||||||
): Promise<TInventoryDatabaseDocument> => {
|
): Promise<TInventoryDatabaseDocument> => {
|
||||||
const inventory = await Inventory.findOne({ accountOwnerId: accountOwnerId }, projection);
|
const inventory = await Inventory.findOne({ accountOwnerId: accountOwnerId }, projection);
|
||||||
|
|
||||||
@ -851,7 +856,7 @@ export const addPowerSuit = async (
|
|||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
powersuitName: string,
|
powersuitName: string,
|
||||||
inventoryChanges: IInventoryChanges = {},
|
inventoryChanges: IInventoryChanges = {},
|
||||||
features: number | undefined = undefined
|
features?: number
|
||||||
): Promise<IInventoryChanges> => {
|
): Promise<IInventoryChanges> => {
|
||||||
const powersuit = ExportWarframes[powersuitName] as IPowersuit | undefined;
|
const powersuit = ExportWarframes[powersuitName] as IPowersuit | undefined;
|
||||||
const exalted = powersuit?.exalted ?? [];
|
const exalted = powersuit?.exalted ?? [];
|
||||||
@ -883,7 +888,7 @@ export const addMechSuit = async (
|
|||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
mechsuitName: string,
|
mechsuitName: string,
|
||||||
inventoryChanges: IInventoryChanges = {},
|
inventoryChanges: IInventoryChanges = {},
|
||||||
features: number | undefined = undefined
|
features?: number
|
||||||
): Promise<IInventoryChanges> => {
|
): Promise<IInventoryChanges> => {
|
||||||
const powersuit = ExportWarframes[mechsuitName] as IPowersuit | undefined;
|
const powersuit = ExportWarframes[mechsuitName] as IPowersuit | undefined;
|
||||||
const exalted = powersuit?.exalted ?? [];
|
const exalted = powersuit?.exalted ?? [];
|
||||||
@ -935,7 +940,7 @@ export const addSpaceSuit = (
|
|||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
spacesuitName: string,
|
spacesuitName: string,
|
||||||
inventoryChanges: IInventoryChanges = {},
|
inventoryChanges: IInventoryChanges = {},
|
||||||
features: number | undefined = undefined
|
features?: number
|
||||||
): IInventoryChanges => {
|
): IInventoryChanges => {
|
||||||
const suitIndex =
|
const suitIndex =
|
||||||
inventory.SpaceSuits.push({
|
inventory.SpaceSuits.push({
|
||||||
@ -1194,9 +1199,9 @@ export const addEquipment = (
|
|||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
category: TEquipmentKey,
|
category: TEquipmentKey,
|
||||||
type: string,
|
type: string,
|
||||||
modularParts: string[] | undefined = undefined,
|
modularParts?: string[],
|
||||||
inventoryChanges: IInventoryChanges = {},
|
inventoryChanges: IInventoryChanges = {},
|
||||||
defaultOverwrites: Partial<IEquipmentDatabase> | undefined = undefined
|
defaultOverwrites?: Partial<IEquipmentDatabase>
|
||||||
): IInventoryChanges => {
|
): IInventoryChanges => {
|
||||||
const equipment = Object.assign(
|
const equipment = Object.assign(
|
||||||
{
|
{
|
||||||
@ -1236,12 +1241,16 @@ export const addSkin = (
|
|||||||
typeName: string,
|
typeName: string,
|
||||||
inventoryChanges: IInventoryChanges = {}
|
inventoryChanges: IInventoryChanges = {}
|
||||||
): IInventoryChanges => {
|
): IInventoryChanges => {
|
||||||
|
if (inventory.WeaponSkins.find(x => x.ItemType == typeName)) {
|
||||||
|
logger.debug(`refusing to add WeaponSkin ${typeName} because account already owns it`);
|
||||||
|
} else {
|
||||||
const index = inventory.WeaponSkins.push({ ItemType: typeName, IsNew: true }) - 1;
|
const index = inventory.WeaponSkins.push({ ItemType: typeName, IsNew: true }) - 1;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
inventoryChanges.WeaponSkins ??= [];
|
inventoryChanges.WeaponSkins ??= [];
|
||||||
(inventoryChanges.WeaponSkins as IWeaponSkinClient[]).push(
|
(inventoryChanges.WeaponSkins as IWeaponSkinClient[]).push(
|
||||||
inventory.WeaponSkins[index].toJSON<IWeaponSkinClient>()
|
inventory.WeaponSkins[index].toJSON<IWeaponSkinClient>()
|
||||||
);
|
);
|
||||||
|
}
|
||||||
return inventoryChanges;
|
return inventoryChanges;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1752,20 +1761,6 @@ export const createLibraryDailyTask = (): ILibraryDailyTaskInfo => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const createCalendar = (): ICalendarProgress => {
|
|
||||||
return {
|
|
||||||
Version: 19,
|
|
||||||
Iteration: 2,
|
|
||||||
YearProgress: { Upgrades: [] },
|
|
||||||
SeasonProgress: {
|
|
||||||
SeasonType: "CST_SPRING",
|
|
||||||
LastCompletedDayIdx: -1,
|
|
||||||
LastCompletedChallengeDayIdx: -1,
|
|
||||||
ActivatedChallenges: []
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const setupKahlSyndicate = (inventory: TInventoryDatabaseDocument): void => {
|
export const setupKahlSyndicate = (inventory: TInventoryDatabaseDocument): void => {
|
||||||
inventory.Affiliations.push({
|
inventory.Affiliations.push({
|
||||||
Title: 1,
|
Title: 1,
|
||||||
@ -1802,3 +1797,37 @@ export const cleanupInventory = (inventory: TInventoryDatabaseDocument): void =>
|
|||||||
LibrarySyndicate.FreeFavorsEarned = undefined;
|
LibrarySyndicate.FreeFavorsEarned = undefined;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getCalendarProgress = (inventory: TInventoryDatabaseDocument): ICalendarProgress => {
|
||||||
|
const currentSeason = getWorldState().KnownCalendarSeasons[0];
|
||||||
|
|
||||||
|
if (!inventory.CalendarProgress) {
|
||||||
|
inventory.CalendarProgress = {
|
||||||
|
Version: 19,
|
||||||
|
Iteration: currentSeason.YearIteration,
|
||||||
|
YearProgress: {
|
||||||
|
Upgrades: []
|
||||||
|
},
|
||||||
|
SeasonProgress: {
|
||||||
|
SeasonType: currentSeason.Season,
|
||||||
|
LastCompletedDayIdx: 0,
|
||||||
|
LastCompletedChallengeDayIdx: 0,
|
||||||
|
ActivatedChallenges: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const yearRolledOver = inventory.CalendarProgress.Iteration != currentSeason.YearIteration;
|
||||||
|
if (yearRolledOver) {
|
||||||
|
inventory.CalendarProgress.Iteration = currentSeason.YearIteration;
|
||||||
|
inventory.CalendarProgress.YearProgress.Upgrades = [];
|
||||||
|
}
|
||||||
|
if (yearRolledOver || inventory.CalendarProgress.SeasonProgress.SeasonType != currentSeason.Season) {
|
||||||
|
inventory.CalendarProgress.SeasonProgress.SeasonType = currentSeason.Season;
|
||||||
|
inventory.CalendarProgress.SeasonProgress.LastCompletedDayIdx = -1;
|
||||||
|
inventory.CalendarProgress.SeasonProgress.LastCompletedChallengeDayIdx = -1;
|
||||||
|
inventory.CalendarProgress.SeasonProgress.ActivatedChallenges = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return inventory.CalendarProgress;
|
||||||
|
};
|
||||||
|
@ -33,6 +33,7 @@ import {
|
|||||||
addStanding,
|
addStanding,
|
||||||
combineInventoryChanges,
|
combineInventoryChanges,
|
||||||
generateRewardSeed,
|
generateRewardSeed,
|
||||||
|
getCalendarProgress,
|
||||||
updateCurrency,
|
updateCurrency,
|
||||||
updateSyndicate
|
updateSyndicate
|
||||||
} from "@/src/services/inventoryService";
|
} from "@/src/services/inventoryService";
|
||||||
@ -73,13 +74,11 @@ const getRotations = (rewardInfo: IRewardInfo, tierOverride?: number): number[]
|
|||||||
return [rewardInfo.rewardTier];
|
return [rewardInfo.rewardTier];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aborting a railjack mission should not give any rewards (https://onlyg.it/OpenWF/SpaceNinjaServer/issues/1741)
|
const rotationCount = rewardInfo.rewardQualifications?.length || 0;
|
||||||
if (rewardInfo.rewardQualifications === undefined) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const rotationCount = rewardInfo.rewardQualifications.length || 0;
|
// Empty or absent rewardQualifications should not give rewards:
|
||||||
if (rotationCount === 0) return [0];
|
// - Aborting a railjack mission (https://onlyg.it/OpenWF/SpaceNinjaServer/issues/1741)
|
||||||
|
// - Completing only 1 zone of (E)SO (https://onlyg.it/OpenWF/SpaceNinjaServer/issues/1823)
|
||||||
|
|
||||||
const rotationPattern =
|
const rotationPattern =
|
||||||
tierOverride === undefined
|
tierOverride === undefined
|
||||||
@ -562,6 +561,22 @@ export const addMissionInventoryUpdates = async (
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "CalendarProgress": {
|
||||||
|
const calendarProgress = getCalendarProgress(inventory);
|
||||||
|
for (const progress of value) {
|
||||||
|
const challengeName = progress.challenge.substring(progress.challenge.lastIndexOf("/") + 1);
|
||||||
|
calendarProgress.SeasonProgress.LastCompletedChallengeDayIdx++;
|
||||||
|
calendarProgress.SeasonProgress.ActivatedChallenges.push(challengeName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "duviriCaveOffers": {
|
||||||
|
// Duviri cave offers (generated with the duviri seed) change after completing one of its game modes (not when aborting).
|
||||||
|
if (inventoryUpdates.MissionStatus != "GS_QUIT") {
|
||||||
|
inventory.DuviriInfo.Seed = generateRewardSeed();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
// Equipment XP updates
|
// Equipment XP updates
|
||||||
if (equipmentKeys.includes(key as TEquipmentKey)) {
|
if (equipmentKeys.includes(key as TEquipmentKey)) {
|
||||||
@ -742,11 +757,6 @@ export const addMissionRewards = async (
|
|||||||
return { MissionRewards: [] };
|
return { MissionRewards: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rewardInfo.rewardSeed) {
|
|
||||||
// We're using a reward seed, so give the client a new one in the response. On live, missionInventoryUpdate seems to always provide a fresh one in the response.
|
|
||||||
inventory.RewardSeed = generateRewardSeed();
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: check double reward merging
|
//TODO: check double reward merging
|
||||||
const MissionRewards: IMissionReward[] = getRandomMissionDrops(inventory, rewardInfo, wagerTier, firstCompletion);
|
const MissionRewards: IMissionReward[] = getRandomMissionDrops(inventory, rewardInfo, wagerTier, firstCompletion);
|
||||||
logger.debug("random mission drops:", MissionRewards);
|
logger.debug("random mission drops:", MissionRewards);
|
||||||
@ -792,7 +802,8 @@ export const addMissionRewards = async (
|
|||||||
missions.Tag != "SolNode761" && // the index
|
missions.Tag != "SolNode761" && // the index
|
||||||
missions.Tag != "SolNode762" && // the index
|
missions.Tag != "SolNode762" && // the index
|
||||||
missions.Tag != "SolNode763" && // the index
|
missions.Tag != "SolNode763" && // the index
|
||||||
missions.Tag != "CrewBattleNode556" // free flight
|
missions.Tag != "CrewBattleNode556" && // free flight
|
||||||
|
getRotations(rewardInfo).length > 0 // (E)SO should not give credits for only completing zone 1, in which case it has no rewardQualifications (https://onlyg.it/OpenWF/SpaceNinjaServer/issues/1823)
|
||||||
) {
|
) {
|
||||||
const levelCreditReward = getLevelCreditRewards(node);
|
const levelCreditReward = getLevelCreditRewards(node);
|
||||||
missionCompletionCredits += levelCreditReward;
|
missionCompletionCredits += levelCreditReward;
|
||||||
@ -804,6 +815,14 @@ export const addMissionRewards = async (
|
|||||||
missionCompletionCredits += addFixedLevelRewards(node.missionReward, inventory, MissionRewards, rewardInfo);
|
missionCompletionCredits += addFixedLevelRewards(node.missionReward, inventory, MissionRewards, rewardInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rewardInfo.sortieTag == "Mission1") {
|
||||||
|
missionCompletionCredits += 20_000;
|
||||||
|
} else if (rewardInfo.sortieTag == "Mission2") {
|
||||||
|
missionCompletionCredits += 30_000;
|
||||||
|
} else if (rewardInfo.sortieTag == "Final") {
|
||||||
|
missionCompletionCredits += 50_000;
|
||||||
|
}
|
||||||
|
|
||||||
if (missions.Tag == "PlutoToErisJunction") {
|
if (missions.Tag == "PlutoToErisJunction") {
|
||||||
await createMessage(inventory.accountOwnerId, [
|
await createMessage(inventory.accountOwnerId, [
|
||||||
{
|
{
|
||||||
@ -1406,6 +1425,11 @@ function getRandomMissionDrops(
|
|||||||
if (rewardManifests.length != 0) {
|
if (rewardManifests.length != 0) {
|
||||||
logger.debug(`generating random mission rewards`, { rewardManifests, rotations });
|
logger.debug(`generating random mission rewards`, { rewardManifests, rotations });
|
||||||
}
|
}
|
||||||
|
if (RewardInfo.rewardSeed) {
|
||||||
|
if (RewardInfo.rewardSeed != inventory.RewardSeed) {
|
||||||
|
logger.warn(`RewardSeed mismatch:`, { client: RewardInfo.rewardSeed, database: inventory.RewardSeed });
|
||||||
|
}
|
||||||
|
}
|
||||||
const rng = new SRng(BigInt(RewardInfo.rewardSeed ?? generateRewardSeed()) ^ 0xffffffffffffffffn);
|
const rng = new SRng(BigInt(RewardInfo.rewardSeed ?? generateRewardSeed()) ^ 0xffffffffffffffffn);
|
||||||
rewardManifests.forEach(name => {
|
rewardManifests.forEach(name => {
|
||||||
const table = ExportRewards[name];
|
const table = ExportRewards[name];
|
||||||
|
@ -97,9 +97,17 @@ export class CRng {
|
|||||||
}
|
}
|
||||||
|
|
||||||
randomInt(min: number, max: number): number {
|
randomInt(min: number, max: number): number {
|
||||||
min = Math.ceil(min);
|
const diff = max - min;
|
||||||
max = Math.floor(max);
|
if (diff != 0) {
|
||||||
return Math.floor(this.random() * (max - min + 1)) + min;
|
if (diff < 0) {
|
||||||
|
throw new Error(`max must be greater than min`);
|
||||||
|
}
|
||||||
|
if (diff > 0x3fffffff) {
|
||||||
|
throw new Error(`insufficient entropy`);
|
||||||
|
}
|
||||||
|
min += Math.floor(this.random() * (diff + 1));
|
||||||
|
}
|
||||||
|
return min;
|
||||||
}
|
}
|
||||||
|
|
||||||
randomElement<T>(arr: T[]): T {
|
randomElement<T>(arr: T[]): T {
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
import { unixTimesInMs } from "@/src/constants/timeConstants";
|
import { unixTimesInMs } from "@/src/constants/timeConstants";
|
||||||
import { CRng, mixSeeds } from "@/src/services/rngService";
|
import { CRng, mixSeeds } from "@/src/services/rngService";
|
||||||
import { IMongoDate } from "@/src/types/commonTypes";
|
import { IMongoDate } from "@/src/types/commonTypes";
|
||||||
import {
|
import { IItemManifest, IVendorInfo, IVendorManifest } from "@/src/types/vendorTypes";
|
||||||
IItemManifestPreprocessed,
|
import { ExportVendors, IRange } from "warframe-public-export-plus";
|
||||||
IRawVendorManifest,
|
|
||||||
IVendorInfo,
|
|
||||||
IVendorManifestPreprocessed
|
|
||||||
} from "@/src/types/vendorTypes";
|
|
||||||
import { ExportVendors } from "warframe-public-export-plus";
|
|
||||||
|
|
||||||
import ArchimedeanVendorManifest from "@/static/fixed_responses/getVendorInfo/ArchimedeanVendorManifest.json";
|
import ArchimedeanVendorManifest from "@/static/fixed_responses/getVendorInfo/ArchimedeanVendorManifest.json";
|
||||||
import DeimosEntratiFragmentVendorProductsManifest from "@/static/fixed_responses/getVendorInfo/DeimosEntratiFragmentVendorProductsManifest.json";
|
import DeimosEntratiFragmentVendorProductsManifest from "@/static/fixed_responses/getVendorInfo/DeimosEntratiFragmentVendorProductsManifest.json";
|
||||||
@ -23,7 +18,6 @@ import DeimosProspectorVendorManifest from "@/static/fixed_responses/getVendorIn
|
|||||||
import DuviriAcrithisVendorManifest from "@/static/fixed_responses/getVendorInfo/DuviriAcrithisVendorManifest.json";
|
import DuviriAcrithisVendorManifest from "@/static/fixed_responses/getVendorInfo/DuviriAcrithisVendorManifest.json";
|
||||||
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 GuildAdvertisementVendorManifest from "@/static/fixed_responses/getVendorInfo/GuildAdvertisementVendorManifest.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 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";
|
||||||
@ -32,14 +26,14 @@ import OstronFishmongerVendorManifest from "@/static/fixed_responses/getVendorIn
|
|||||||
import OstronPetVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronPetVendorManifest.json";
|
import OstronPetVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronPetVendorManifest.json";
|
||||||
import OstronProspectorVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronProspectorVendorManifest.json";
|
import OstronProspectorVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronProspectorVendorManifest.json";
|
||||||
import RadioLegionIntermission12VendorManifest from "@/static/fixed_responses/getVendorInfo/RadioLegionIntermission12VendorManifest.json";
|
import RadioLegionIntermission12VendorManifest from "@/static/fixed_responses/getVendorInfo/RadioLegionIntermission12VendorManifest.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 SolarisFishmongerVendorManifest from "@/static/fixed_responses/getVendorInfo/SolarisFishmongerVendorManifest.json";
|
||||||
import SolarisProspectorVendorManifest from "@/static/fixed_responses/getVendorInfo/SolarisProspectorVendorManifest.json";
|
import SolarisProspectorVendorManifest from "@/static/fixed_responses/getVendorInfo/SolarisProspectorVendorManifest.json";
|
||||||
|
import Temple1999VendorManifest from "@/static/fixed_responses/getVendorInfo/Temple1999VendorManifest.json";
|
||||||
import TeshinHardModeVendorManifest from "@/static/fixed_responses/getVendorInfo/TeshinHardModeVendorManifest.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";
|
||||||
|
|
||||||
const rawVendorManifests: IRawVendorManifest[] = [
|
const rawVendorManifests: IVendorManifest[] = [
|
||||||
ArchimedeanVendorManifest,
|
ArchimedeanVendorManifest,
|
||||||
DeimosEntratiFragmentVendorProductsManifest,
|
DeimosEntratiFragmentVendorProductsManifest,
|
||||||
DeimosFishmongerVendorManifest,
|
DeimosFishmongerVendorManifest,
|
||||||
@ -54,7 +48,6 @@ const rawVendorManifests: IRawVendorManifest[] = [
|
|||||||
DuviriAcrithisVendorManifest,
|
DuviriAcrithisVendorManifest,
|
||||||
EntratiLabsEntratiLabsCommisionsManifest,
|
EntratiLabsEntratiLabsCommisionsManifest,
|
||||||
EntratiLabsEntratiLabVendorManifest,
|
EntratiLabsEntratiLabVendorManifest,
|
||||||
GuildAdvertisementVendorManifest, // uses preprocessing
|
|
||||||
HubsIronwakeDondaVendorManifest, // uses preprocessing
|
HubsIronwakeDondaVendorManifest, // uses preprocessing
|
||||||
HubsRailjackCrewMemberVendorManifest,
|
HubsRailjackCrewMemberVendorManifest,
|
||||||
MaskSalesmanManifest,
|
MaskSalesmanManifest,
|
||||||
@ -63,16 +56,16 @@ const rawVendorManifests: IRawVendorManifest[] = [
|
|||||||
OstronPetVendorManifest,
|
OstronPetVendorManifest,
|
||||||
OstronProspectorVendorManifest,
|
OstronProspectorVendorManifest,
|
||||||
RadioLegionIntermission12VendorManifest,
|
RadioLegionIntermission12VendorManifest,
|
||||||
SolarisDebtTokenVendorManifest,
|
|
||||||
SolarisDebtTokenVendorRepossessionsManifest,
|
SolarisDebtTokenVendorRepossessionsManifest,
|
||||||
SolarisFishmongerVendorManifest,
|
SolarisFishmongerVendorManifest,
|
||||||
SolarisProspectorVendorManifest,
|
SolarisProspectorVendorManifest,
|
||||||
|
Temple1999VendorManifest,
|
||||||
TeshinHardModeVendorManifest, // uses preprocessing
|
TeshinHardModeVendorManifest, // uses preprocessing
|
||||||
ZarimanCommisionsManifestArchimedean
|
ZarimanCommisionsManifestArchimedean
|
||||||
];
|
];
|
||||||
|
|
||||||
interface IGeneratableVendorInfo extends Omit<IVendorInfo, "ItemManifest" | "Expiry"> {
|
interface IGeneratableVendorInfo extends Omit<IVendorInfo, "ItemManifest" | "Expiry"> {
|
||||||
cycleStart: number;
|
cycleOffset?: number;
|
||||||
cycleDuration: number;
|
cycleDuration: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +77,7 @@ const generatableVendors: IGeneratableVendorInfo[] = [
|
|||||||
RandomSeedType: "VRST_WEAPON",
|
RandomSeedType: "VRST_WEAPON",
|
||||||
RequiredGoalTag: "",
|
RequiredGoalTag: "",
|
||||||
WeaponUpgradeValueAttenuationExponent: 2.25,
|
WeaponUpgradeValueAttenuationExponent: 2.25,
|
||||||
cycleStart: 1740960000_000,
|
cycleOffset: 1740960000_000,
|
||||||
cycleDuration: 4 * unixTimesInMs.day
|
cycleDuration: 4 * unixTimesInMs.day
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -93,8 +86,22 @@ const generatableVendors: IGeneratableVendorInfo[] = [
|
|||||||
PropertyTextHash: "34F8CF1DFF745F0D67433A5EF0A03E70",
|
PropertyTextHash: "34F8CF1DFF745F0D67433A5EF0A03E70",
|
||||||
RandomSeedType: "VRST_WEAPON",
|
RandomSeedType: "VRST_WEAPON",
|
||||||
WeaponUpgradeValueAttenuationExponent: 2.25,
|
WeaponUpgradeValueAttenuationExponent: 2.25,
|
||||||
cycleStart: 1744934400_000,
|
cycleOffset: 1744934400_000,
|
||||||
cycleDuration: 4 * unixTimesInMs.day
|
cycleDuration: 4 * unixTimesInMs.day
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_id: { $oid: "5be4a159b144f3cdf1c22efa" },
|
||||||
|
TypeName: "/Lotus/Types/Game/VendorManifests/Solaris/DebtTokenVendorManifest",
|
||||||
|
PropertyTextHash: "A39621049CA3CA13761028CD21C239EF",
|
||||||
|
RandomSeedType: "VRST_FLAVOUR_TEXT",
|
||||||
|
cycleDuration: unixTimesInMs.hour
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_id: { $oid: "61ba123467e5d37975aeeb03" },
|
||||||
|
TypeName: "/Lotus/Types/Game/VendorManifests/Hubs/GuildAdvertisementVendorManifest",
|
||||||
|
PropertyTextHash: "255AFE2169BAE4130B4B20D7C55D14FA",
|
||||||
|
RandomSeedType: "VRST_FLAVOUR_TEXT",
|
||||||
|
cycleDuration: unixTimesInMs.week
|
||||||
}
|
}
|
||||||
// {
|
// {
|
||||||
// _id: { $oid: "5dbb4c41e966f7886c3ce939" },
|
// _id: { $oid: "5dbb4c41e966f7886c3ce939" },
|
||||||
@ -103,7 +110,7 @@ const generatableVendors: IGeneratableVendorInfo[] = [
|
|||||||
// }
|
// }
|
||||||
];
|
];
|
||||||
|
|
||||||
export const getVendorManifestByTypeName = (typeName: string): IVendorManifestPreprocessed | undefined => {
|
export const getVendorManifestByTypeName = (typeName: string): IVendorManifest | undefined => {
|
||||||
for (const vendorManifest of rawVendorManifests) {
|
for (const vendorManifest of rawVendorManifests) {
|
||||||
if (vendorManifest.VendorInfo.TypeName == typeName) {
|
if (vendorManifest.VendorInfo.TypeName == typeName) {
|
||||||
return preprocessVendorManifest(vendorManifest);
|
return preprocessVendorManifest(vendorManifest);
|
||||||
@ -117,7 +124,7 @@ export const getVendorManifestByTypeName = (typeName: string): IVendorManifestPr
|
|||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getVendorManifestByOid = (oid: string): IVendorManifestPreprocessed | undefined => {
|
export const getVendorManifestByOid = (oid: string): IVendorManifest | undefined => {
|
||||||
for (const vendorManifest of rawVendorManifests) {
|
for (const vendorManifest of rawVendorManifests) {
|
||||||
if (vendorManifest.VendorInfo._id.$oid == oid) {
|
if (vendorManifest.VendorInfo._id.$oid == oid) {
|
||||||
return preprocessVendorManifest(vendorManifest);
|
return preprocessVendorManifest(vendorManifest);
|
||||||
@ -131,29 +138,20 @@ export const getVendorManifestByOid = (oid: string): IVendorManifestPreprocessed
|
|||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const preprocessVendorManifest = (originalManifest: IRawVendorManifest): IVendorManifestPreprocessed => {
|
const preprocessVendorManifest = (originalManifest: IVendorManifest): IVendorManifest => {
|
||||||
if (Date.now() >= parseInt(originalManifest.VendorInfo.Expiry.$date.$numberLong)) {
|
if (Date.now() >= parseInt(originalManifest.VendorInfo.Expiry.$date.$numberLong)) {
|
||||||
const manifest = structuredClone(originalManifest);
|
const manifest = structuredClone(originalManifest);
|
||||||
const info = manifest.VendorInfo;
|
const info = manifest.VendorInfo;
|
||||||
refreshExpiry(info.Expiry);
|
refreshExpiry(info.Expiry);
|
||||||
for (const offer of info.ItemManifest) {
|
for (const offer of info.ItemManifest) {
|
||||||
const iteration = refreshExpiry(offer.Expiry);
|
refreshExpiry(offer.Expiry);
|
||||||
if (offer.ItemPrices) {
|
|
||||||
for (const price of offer.ItemPrices) {
|
|
||||||
if (typeof price.ItemType != "string") {
|
|
||||||
const itemSeed = parseInt(offer.Id.$oid.substring(16), 16);
|
|
||||||
const rng = new CRng(mixSeeds(itemSeed, iteration));
|
|
||||||
price.ItemType = rng.randomElement(price.ItemType);
|
|
||||||
}
|
}
|
||||||
|
return manifest;
|
||||||
}
|
}
|
||||||
}
|
return originalManifest;
|
||||||
}
|
|
||||||
return manifest as IVendorManifestPreprocessed;
|
|
||||||
}
|
|
||||||
return originalManifest as IVendorManifestPreprocessed;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const refreshExpiry = (expiry: IMongoDate): number => {
|
const refreshExpiry = (expiry: IMongoDate): void => {
|
||||||
const period = parseInt(expiry.$date.$numberLong);
|
const period = parseInt(expiry.$date.$numberLong);
|
||||||
if (Date.now() >= period) {
|
if (Date.now() >= period) {
|
||||||
const epoch = 1734307200_000; // Monday (for weekly schedules)
|
const epoch = 1734307200_000; // Monday (for weekly schedules)
|
||||||
@ -161,65 +159,136 @@ const refreshExpiry = (expiry: IMongoDate): number => {
|
|||||||
const start = epoch + iteration * period;
|
const start = epoch + iteration * period;
|
||||||
const end = start + period;
|
const end = start + period;
|
||||||
expiry.$date.$numberLong = end.toString();
|
expiry.$date.$numberLong = end.toString();
|
||||||
return iteration;
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorManifestPreprocessed => {
|
const toRange = (value: IRange | number): IRange => {
|
||||||
const EPOCH = vendorInfo.cycleStart;
|
if (typeof value == "number") {
|
||||||
|
return { minValue: value, maxValue: value };
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const vendorInfoCache: Record<string, IVendorInfo> = {};
|
||||||
|
|
||||||
|
const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorManifest => {
|
||||||
|
if (!(vendorInfo.TypeName in vendorInfoCache)) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const { cycleOffset, cycleDuration, ...clientVendorInfo } = vendorInfo;
|
||||||
|
vendorInfoCache[vendorInfo.TypeName] = {
|
||||||
|
...clientVendorInfo,
|
||||||
|
ItemManifest: [],
|
||||||
|
Expiry: { $date: { $numberLong: "0" } }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const processed = vendorInfoCache[vendorInfo.TypeName];
|
||||||
|
if (Date.now() >= parseInt(processed.Expiry.$date.$numberLong)) {
|
||||||
|
// Remove expired offers
|
||||||
|
for (let i = 0; i != processed.ItemManifest.length; ) {
|
||||||
|
if (Date.now() >= parseInt(processed.ItemManifest[i].Expiry.$date.$numberLong)) {
|
||||||
|
processed.ItemManifest.splice(i, 1);
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new offers
|
||||||
|
const vendorSeed = parseInt(vendorInfo._id.$oid.substring(16), 16);
|
||||||
|
const cycleOffset = vendorInfo.cycleOffset ?? 1734307200_000;
|
||||||
|
const cycleDuration = vendorInfo.cycleDuration;
|
||||||
|
const cycleIndex = Math.trunc((Date.now() - cycleOffset) / cycleDuration);
|
||||||
|
const rng = new CRng(mixSeeds(vendorSeed, cycleIndex));
|
||||||
const manifest = ExportVendors[vendorInfo.TypeName];
|
const manifest = ExportVendors[vendorInfo.TypeName];
|
||||||
|
const offersToAdd = [];
|
||||||
|
if (manifest.numItems && manifest.numItems.minValue != manifest.numItems.maxValue) {
|
||||||
|
const numItemsTarget = rng.randomInt(manifest.numItems.minValue, manifest.numItems.maxValue);
|
||||||
|
while (processed.ItemManifest.length + offersToAdd.length < numItemsTarget) {
|
||||||
|
// TODO: Consider per-bin item limits
|
||||||
|
// TODO: Consider item probability weightings
|
||||||
|
offersToAdd.push(rng.randomElement(manifest.items));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
let binThisCycle;
|
let binThisCycle;
|
||||||
if (manifest.isOneBinPerCycle) {
|
if (manifest.isOneBinPerCycle) {
|
||||||
const cycleDuration = vendorInfo.cycleDuration; // manifest.items[0].durationHours! * 3600_000;
|
|
||||||
const cycleIndex = Math.trunc((Date.now() - EPOCH) / cycleDuration);
|
|
||||||
binThisCycle = cycleIndex % 2; // Note: May want to auto-compute the bin size, but this is only used for coda weapons right now.
|
binThisCycle = cycleIndex % 2; // Note: May want to auto-compute the bin size, but this is only used for coda weapons right now.
|
||||||
}
|
}
|
||||||
const items: IItemManifestPreprocessed[] = [];
|
for (const rawItem of manifest.items) {
|
||||||
let soonestOfferExpiry: number = Number.MAX_SAFE_INTEGER;
|
if (!manifest.isOneBinPerCycle || rawItem.bin == binThisCycle) {
|
||||||
for (let i = 0; i != manifest.items.length; ++i) {
|
offersToAdd.push(rawItem);
|
||||||
const rawItem = manifest.items[i];
|
|
||||||
if (manifest.isOneBinPerCycle && rawItem.bin != binThisCycle) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
const cycleDuration = vendorInfo.cycleDuration; // rawItem.durationHours! * 3600_000;
|
|
||||||
const cycleIndex = Math.trunc((Date.now() - EPOCH) / cycleDuration);
|
|
||||||
const cycleStart = EPOCH + cycleIndex * cycleDuration;
|
|
||||||
const cycleEnd = cycleStart + cycleDuration;
|
|
||||||
if (soonestOfferExpiry > cycleEnd) {
|
|
||||||
soonestOfferExpiry = cycleEnd;
|
|
||||||
}
|
}
|
||||||
const rng = new CRng(cycleIndex);
|
|
||||||
rng.churnSeed(i);
|
// For most vendors, the offers seem to roughly be in reverse order from the manifest. Coda weapons are an odd exception.
|
||||||
/*for (let j = -1; j != rawItem.duplicates; ++j)*/ {
|
if (!manifest.isOneBinPerCycle) {
|
||||||
const item: IItemManifestPreprocessed = {
|
offersToAdd.reverse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const cycleStart = cycleOffset + cycleIndex * cycleDuration;
|
||||||
|
for (const rawItem of offersToAdd) {
|
||||||
|
const durationHoursRange = toRange(rawItem.durationHours);
|
||||||
|
const expiry =
|
||||||
|
cycleStart +
|
||||||
|
rng.randomInt(durationHoursRange.minValue, durationHoursRange.maxValue) * unixTimesInMs.hour;
|
||||||
|
const item: IItemManifest = {
|
||||||
StoreItem: rawItem.storeItem,
|
StoreItem: rawItem.storeItem,
|
||||||
ItemPrices: rawItem.itemPrices!.map(itemPrice => ({ ...itemPrice, ProductCategory: "MiscItems" })),
|
ItemPrices: rawItem.itemPrices?.map(itemPrice => ({ ...itemPrice, ProductCategory: "MiscItems" })),
|
||||||
Bin: "BIN_" + rawItem.bin,
|
Bin: "BIN_" + rawItem.bin,
|
||||||
QuantityMultiplier: 1,
|
QuantityMultiplier: 1,
|
||||||
Expiry: { $date: { $numberLong: cycleEnd.toString() } },
|
Expiry: { $date: { $numberLong: expiry.toString() } },
|
||||||
AllowMultipurchase: false,
|
AllowMultipurchase: false,
|
||||||
Id: {
|
Id: {
|
||||||
$oid:
|
$oid:
|
||||||
i.toString(16).padStart(8, "0") +
|
((cycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") +
|
||||||
vendorInfo._id.$oid.substring(8, 16) +
|
vendorInfo._id.$oid.substring(8, 16) +
|
||||||
rng.randomInt(0, 0xffffffff).toString(16).padStart(8, "0")
|
rng.randomInt(0, 0xffff).toString(16).padStart(4, "0") +
|
||||||
|
rng.randomInt(0, 0xffff).toString(16).padStart(4, "0")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
if (rawItem.numRandomItemPrices) {
|
||||||
|
item.ItemPrices = [];
|
||||||
|
for (let i = 0; i != rawItem.numRandomItemPrices; ++i) {
|
||||||
|
let itemPrice: { type: string; count: IRange };
|
||||||
|
do {
|
||||||
|
itemPrice = rng.randomElement(manifest.randomItemPricesPerBin![rawItem.bin]);
|
||||||
|
} while (item.ItemPrices.find(x => x.ItemType == itemPrice.type));
|
||||||
|
item.ItemPrices.push({
|
||||||
|
ItemType: itemPrice.type,
|
||||||
|
ItemCount: rng.randomInt(itemPrice.count.minValue, itemPrice.count.maxValue),
|
||||||
|
ProductCategory: "MiscItems"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rawItem.credits) {
|
||||||
|
const value =
|
||||||
|
typeof rawItem.credits == "number"
|
||||||
|
? rawItem.credits
|
||||||
|
: rng.randomInt(
|
||||||
|
rawItem.credits.minValue / rawItem.credits.step,
|
||||||
|
rawItem.credits.maxValue / rawItem.credits.step
|
||||||
|
) * rawItem.credits.step;
|
||||||
|
item.RegularPrice = [value, value];
|
||||||
|
}
|
||||||
if (vendorInfo.RandomSeedType) {
|
if (vendorInfo.RandomSeedType) {
|
||||||
item.LocTagRandSeed =
|
item.LocTagRandSeed = (rng.randomInt(0, 0xffff) << 16) | rng.randomInt(0, 0xffff);
|
||||||
(BigInt(rng.randomInt(0, 0xffffffff)) << 32n) | BigInt(rng.randomInt(0, 0xffffffff));
|
if (vendorInfo.RandomSeedType == "VRST_WEAPON") {
|
||||||
}
|
const highDword = (rng.randomInt(0, 0xffff) << 16) | rng.randomInt(0, 0xffff);
|
||||||
items.push(item);
|
item.LocTagRandSeed = (BigInt(highDword) << 32n) | BigInt(item.LocTagRandSeed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
processed.ItemManifest.push(item);
|
||||||
const { cycleStart, cycleDuration, ...clientVendorInfo } = vendorInfo;
|
}
|
||||||
|
|
||||||
|
// Update vendor expiry
|
||||||
|
let soonestOfferExpiry: number = Number.MAX_SAFE_INTEGER;
|
||||||
|
for (const offer of processed.ItemManifest) {
|
||||||
|
const offerExpiry = parseInt(offer.Expiry.$date.$numberLong);
|
||||||
|
if (soonestOfferExpiry > offerExpiry) {
|
||||||
|
soonestOfferExpiry = offerExpiry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
processed.Expiry.$date.$numberLong = soonestOfferExpiry.toString();
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
VendorInfo: {
|
VendorInfo: processed
|
||||||
...clientVendorInfo,
|
|
||||||
ItemManifest: items,
|
|
||||||
Expiry: { $date: { $numberLong: soonestOfferExpiry.toString() } }
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -7,6 +7,7 @@ import { CRng } from "@/src/services/rngService";
|
|||||||
import { eMissionType, ExportNightwave, ExportRegions, IRegion } from "warframe-public-export-plus";
|
import { eMissionType, ExportNightwave, ExportRegions, IRegion } from "warframe-public-export-plus";
|
||||||
import {
|
import {
|
||||||
ICalendarDay,
|
ICalendarDay,
|
||||||
|
ICalendarEvent,
|
||||||
ICalendarSeason,
|
ICalendarSeason,
|
||||||
ILiteSortie,
|
ILiteSortie,
|
||||||
ISeasonChallenge,
|
ISeasonChallenge,
|
||||||
@ -186,10 +187,12 @@ const pushSyndicateMissions = (
|
|||||||
for (const [key, value] of Object.entries(ExportRegions)) {
|
for (const [key, value] of Object.entries(ExportRegions)) {
|
||||||
if (
|
if (
|
||||||
!isArchwingMission(value) &&
|
!isArchwingMission(value) &&
|
||||||
value.systemIndex != 23 && // no 1999 stuff
|
!value.questReq && // Exclude zariman, murmor, and 1999 stuff
|
||||||
|
!value.hidden && // Exclude the index
|
||||||
|
!value.darkSectorData && // Exclude dark sectors
|
||||||
value.missionIndex != 10 && // Exclude MT_PVP (for relays)
|
value.missionIndex != 10 && // Exclude MT_PVP (for relays)
|
||||||
value.missionIndex != 23 && // no junctions
|
value.missionIndex != 23 && // no junctions
|
||||||
value.missionIndex <= 28 // no railjack or some such
|
value.missionIndex < 28 // no open worlds, railjack, etc
|
||||||
) {
|
) {
|
||||||
nodeOptions.push(key);
|
nodeOptions.push(key);
|
||||||
}
|
}
|
||||||
@ -206,7 +209,7 @@ const pushSyndicateMissions = (
|
|||||||
const dayStart = getSortieTime(day);
|
const dayStart = getSortieTime(day);
|
||||||
const dayEnd = getSortieTime(day + 1);
|
const dayEnd = getSortieTime(day + 1);
|
||||||
worldState.SyndicateMissions.push({
|
worldState.SyndicateMissions.push({
|
||||||
_id: { $oid: Math.trunc(dayStart / 1000).toString(16) + idSuffix },
|
_id: { $oid: ((dayStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + idSuffix },
|
||||||
Activation: { $date: { $numberLong: dayStart.toString() } },
|
Activation: { $date: { $numberLong: dayStart.toString() } },
|
||||||
Expiry: { $date: { $numberLong: dayEnd.toString() } },
|
Expiry: { $date: { $numberLong: dayEnd.toString() } },
|
||||||
Tag: syndicateTag,
|
Tag: syndicateTag,
|
||||||
@ -225,7 +228,8 @@ const pushSortieIfRelevant = (worldState: IWorldState, day: number): void => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rng = new CRng(day);
|
const seed = new CRng(day).randomInt(0, 0xffff);
|
||||||
|
const rng = new CRng(seed);
|
||||||
|
|
||||||
const boss = rng.randomElement(sortieBosses);
|
const boss = rng.randomElement(sortieBosses);
|
||||||
|
|
||||||
@ -350,11 +354,11 @@ const pushSortieIfRelevant = (worldState: IWorldState, day: number): void => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
worldState.Sorties.push({
|
worldState.Sorties.push({
|
||||||
_id: { $oid: Math.trunc(dayStart / 1000).toString(16) + "d4d932c97c0a3acd" },
|
_id: { $oid: ((dayStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "d4d932c97c0a3acd" },
|
||||||
Activation: { $date: { $numberLong: dayStart.toString() } },
|
Activation: { $date: { $numberLong: dayStart.toString() } },
|
||||||
Expiry: { $date: { $numberLong: dayEnd.toString() } },
|
Expiry: { $date: { $numberLong: dayEnd.toString() } },
|
||||||
Reward: "/Lotus/Types/Game/MissionDecks/SortieRewards",
|
Reward: "/Lotus/Types/Game/MissionDecks/SortieRewards",
|
||||||
Seed: day,
|
Seed: seed,
|
||||||
Boss: boss,
|
Boss: boss,
|
||||||
Variants: selectedNodes
|
Variants: selectedNodes
|
||||||
});
|
});
|
||||||
@ -374,7 +378,7 @@ const dailyChallenges = Object.keys(ExportNightwave.challenges).filter(x =>
|
|||||||
const getSeasonDailyChallenge = (day: number): ISeasonChallenge => {
|
const getSeasonDailyChallenge = (day: number): ISeasonChallenge => {
|
||||||
const dayStart = EPOCH + day * 86400000;
|
const dayStart = EPOCH + day * 86400000;
|
||||||
const dayEnd = EPOCH + (day + 3) * 86400000;
|
const dayEnd = EPOCH + (day + 3) * 86400000;
|
||||||
const rng = new CRng(day);
|
const rng = new CRng(new CRng(day).randomInt(0, 0xffff));
|
||||||
return {
|
return {
|
||||||
_id: { $oid: "67e1b5ca9d00cb47" + day.toString().padStart(8, "0") },
|
_id: { $oid: "67e1b5ca9d00cb47" + day.toString().padStart(8, "0") },
|
||||||
Daily: true,
|
Daily: true,
|
||||||
@ -394,7 +398,7 @@ const getSeasonWeeklyChallenge = (week: number, id: number): ISeasonChallenge =>
|
|||||||
const weekStart = EPOCH + week * 604800000;
|
const weekStart = EPOCH + week * 604800000;
|
||||||
const weekEnd = weekStart + 604800000;
|
const weekEnd = weekStart + 604800000;
|
||||||
const challengeId = week * 7 + id;
|
const challengeId = week * 7 + id;
|
||||||
const rng = new CRng(challengeId);
|
const rng = new CRng(new CRng(challengeId).randomInt(0, 0xffff));
|
||||||
return {
|
return {
|
||||||
_id: { $oid: "67e1bb2d9d00cb47" + challengeId.toString().padStart(8, "0") },
|
_id: { $oid: "67e1bb2d9d00cb47" + challengeId.toString().padStart(8, "0") },
|
||||||
Activation: { $date: { $numberLong: weekStart.toString() } },
|
Activation: { $date: { $numberLong: weekStart.toString() } },
|
||||||
@ -411,7 +415,7 @@ const getSeasonWeeklyHardChallenge = (week: number, id: number): ISeasonChalleng
|
|||||||
const weekStart = EPOCH + week * 604800000;
|
const weekStart = EPOCH + week * 604800000;
|
||||||
const weekEnd = weekStart + 604800000;
|
const weekEnd = weekStart + 604800000;
|
||||||
const challengeId = week * 7 + id;
|
const challengeId = week * 7 + id;
|
||||||
const rng = new CRng(challengeId);
|
const rng = new CRng(new CRng(challengeId).randomInt(0, 0xffff));
|
||||||
return {
|
return {
|
||||||
_id: { $oid: "67e1bb2d9d00cb47" + challengeId.toString().padStart(8, "0") },
|
_id: { $oid: "67e1bb2d9d00cb47" + challengeId.toString().padStart(8, "0") },
|
||||||
Activation: { $date: { $numberLong: weekStart.toString() } },
|
Activation: { $date: { $numberLong: weekStart.toString() } },
|
||||||
@ -463,8 +467,8 @@ const birthdays: number[] = [
|
|||||||
|
|
||||||
const getCalendarSeason = (week: number): ICalendarSeason => {
|
const getCalendarSeason = (week: number): ICalendarSeason => {
|
||||||
const seasonIndex = week % 4;
|
const seasonIndex = week % 4;
|
||||||
const seasonDay1 = seasonIndex * 90 + 1;
|
const seasonDay1 = [1, 91, 182, 274][seasonIndex];
|
||||||
const seasonDay91 = seasonIndex * 90 + 91;
|
const seasonDay91 = seasonDay1 + 90;
|
||||||
const eventDays: ICalendarDay[] = [];
|
const eventDays: ICalendarDay[] = [];
|
||||||
for (const day of birthdays) {
|
for (const day of birthdays) {
|
||||||
if (day < seasonDay1) {
|
if (day < seasonDay1) {
|
||||||
@ -476,7 +480,7 @@ const getCalendarSeason = (week: number): ICalendarSeason => {
|
|||||||
//logger.debug(`birthday on day ${day}`);
|
//logger.debug(`birthday on day ${day}`);
|
||||||
eventDays.push({ day, events: [] }); // This is how CET_PLOT looks in worldState as of around 38.5.0
|
eventDays.push({ day, events: [] }); // This is how CET_PLOT looks in worldState as of around 38.5.0
|
||||||
}
|
}
|
||||||
const rng = new CRng(week);
|
const rng = new CRng(new CRng(week).randomInt(0, 0xffff));
|
||||||
const challenges = [
|
const challenges = [
|
||||||
"/Lotus/Types/Challenges/Calendar1999/CalendarKillEnemiesEasy",
|
"/Lotus/Types/Challenges/Calendar1999/CalendarKillEnemiesEasy",
|
||||||
"/Lotus/Types/Challenges/Calendar1999/CalendarKillEnemiesMedium",
|
"/Lotus/Types/Challenges/Calendar1999/CalendarKillEnemiesMedium",
|
||||||
@ -523,8 +527,12 @@ const getCalendarSeason = (week: number): ICalendarSeason => {
|
|||||||
challengeDay = rng.randomInt(chunkDay1, chunkDay13);
|
challengeDay = rng.randomInt(chunkDay1, chunkDay13);
|
||||||
} while (birthdays.indexOf(challengeDay) != -1);
|
} while (birthdays.indexOf(challengeDay) != -1);
|
||||||
|
|
||||||
const challengeIndex = rng.randomInt(0, challenges.length - 1);
|
let challengeIndex;
|
||||||
const challenge = challenges[challengeIndex];
|
let challenge;
|
||||||
|
do {
|
||||||
|
challengeIndex = rng.randomInt(0, challenges.length - 1);
|
||||||
|
challenge = challenges[challengeIndex];
|
||||||
|
} while (i < 2 && !challenge.endsWith("Easy")); // First 2 challenges should be easy
|
||||||
challenges.splice(challengeIndex, 1);
|
challenges.splice(challengeIndex, 1);
|
||||||
|
|
||||||
//logger.debug(`challenge on day ${challengeDay}`);
|
//logger.debug(`challenge on day ${challengeDay}`);
|
||||||
@ -571,69 +579,100 @@ const getCalendarSeason = (week: number): ICalendarSeason => {
|
|||||||
"/Lotus/StoreItems/Types/Gameplay/NarmerSorties/ArchonCrystalViolet"
|
"/Lotus/StoreItems/Types/Gameplay/NarmerSorties/ArchonCrystalViolet"
|
||||||
];
|
];
|
||||||
for (let i = 0; i != rewardRanges.length - 1; ++i) {
|
for (let i = 0; i != rewardRanges.length - 1; ++i) {
|
||||||
|
const events: ICalendarEvent[] = [];
|
||||||
|
for (let j = 0; j != 2; ++j) {
|
||||||
const rewardIndex = rng.randomInt(0, rewards.length - 1);
|
const rewardIndex = rng.randomInt(0, rewards.length - 1);
|
||||||
const reward = rewards[rewardIndex];
|
events.push({ type: "CET_REWARD", reward: rewards[rewardIndex] });
|
||||||
rewards.splice(rewardIndex, 1);
|
rewards.splice(rewardIndex, 1);
|
||||||
|
}
|
||||||
|
|
||||||
//logger.debug(`trying to fit a reward between day ${rewardRanges[i]} and ${rewardRanges[i + 1]}`);
|
//logger.debug(`trying to fit rewards between day ${rewardRanges[i]} and ${rewardRanges[i + 1]}`);
|
||||||
let day: number;
|
let day: number;
|
||||||
do {
|
do {
|
||||||
day = rng.randomInt(rewardRanges[i] + 1, rewardRanges[i + 1] - 1);
|
day = rng.randomInt(rewardRanges[i] + 1, rewardRanges[i + 1] - 1);
|
||||||
} while (eventDays.find(x => x.day == day));
|
} while (eventDays.find(x => x.day == day));
|
||||||
eventDays.push({ day, events: [{ type: "CET_REWARD", reward }] });
|
eventDays.push({ day, events });
|
||||||
}
|
}
|
||||||
|
|
||||||
const upgrades = [
|
const upgradesByHexMember = [
|
||||||
"/Lotus/Upgrades/Calendar/MeleeCritChance",
|
[
|
||||||
"/Lotus/Upgrades/Calendar/MeleeAttackSpeed",
|
"/Lotus/Upgrades/Calendar/AttackAndMovementSpeedOnCritMelee",
|
||||||
"/Lotus/Upgrades/Calendar/EnergyOrbToAbilityRange",
|
"/Lotus/Upgrades/Calendar/ElectricalDamageOnBulletJump",
|
||||||
|
"/Lotus/Upgrades/Calendar/ElectricDamagePerDistance",
|
||||||
|
"/Lotus/Upgrades/Calendar/ElectricStatusDamageAndChance",
|
||||||
|
"/Lotus/Upgrades/Calendar/OvershieldCap",
|
||||||
|
"/Lotus/Upgrades/Calendar/SpeedBuffsWhenAirborne"
|
||||||
|
],
|
||||||
|
[
|
||||||
"/Lotus/Upgrades/Calendar/AbilityStrength",
|
"/Lotus/Upgrades/Calendar/AbilityStrength",
|
||||||
|
"/Lotus/Upgrades/Calendar/EnergyOrbToAbilityRange",
|
||||||
|
"/Lotus/Upgrades/Calendar/MagnetStatusPull",
|
||||||
|
"/Lotus/Upgrades/Calendar/MagnitizeWithinRangeEveryXCasts",
|
||||||
|
"/Lotus/Upgrades/Calendar/PowerStrengthAndEfficiencyPerEnergySpent",
|
||||||
|
"/Lotus/Upgrades/Calendar/SharedFreeAbilityEveryXCasts"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"/Lotus/Upgrades/Calendar/EnergyWavesOnCombo",
|
||||||
|
"/Lotus/Upgrades/Calendar/FinisherChancePerComboMultiplier",
|
||||||
|
"/Lotus/Upgrades/Calendar/MeleeAttackSpeed",
|
||||||
|
"/Lotus/Upgrades/Calendar/MeleeCritChance",
|
||||||
|
"/Lotus/Upgrades/Calendar/MeleeSlideFowardMomentumOnEnemyHit",
|
||||||
|
"/Lotus/Upgrades/Calendar/RadialJavelinOnHeavy"
|
||||||
|
],
|
||||||
|
[
|
||||||
"/Lotus/Upgrades/Calendar/Armor",
|
"/Lotus/Upgrades/Calendar/Armor",
|
||||||
"/Lotus/Upgrades/Calendar/RadiationProcOnTakeDamage",
|
"/Lotus/Upgrades/Calendar/CloneActiveCompanionForEnergySpent",
|
||||||
"/Lotus/Upgrades/Calendar/CompanionDamage",
|
"/Lotus/Upgrades/Calendar/CompanionDamage",
|
||||||
|
"/Lotus/Upgrades/Calendar/CompanionsBuffNearbyPlayer",
|
||||||
|
"/Lotus/Upgrades/Calendar/CompanionsRadiationChance",
|
||||||
|
"/Lotus/Upgrades/Calendar/RadiationProcOnTakeDamage",
|
||||||
|
"/Lotus/Upgrades/Calendar/ReviveEnemyAsSpectreOnKill"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"/Lotus/Upgrades/Calendar/EnergyOrbsGrantShield",
|
||||||
|
"/Lotus/Upgrades/Calendar/EnergyRestoration",
|
||||||
|
"/Lotus/Upgrades/Calendar/ExplodingHealthOrbs",
|
||||||
|
"/Lotus/Upgrades/Calendar/GenerateOmniOrbsOnWeakKill",
|
||||||
|
"/Lotus/Upgrades/Calendar/HealingEffects",
|
||||||
|
"/Lotus/Upgrades/Calendar/OrbsDuplicateOnPickup"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"/Lotus/Upgrades/Calendar/BlastEveryXShots",
|
||||||
"/Lotus/Upgrades/Calendar/GasChanceToPrimaryAndSecondary",
|
"/Lotus/Upgrades/Calendar/GasChanceToPrimaryAndSecondary",
|
||||||
|
"/Lotus/Upgrades/Calendar/GuidingMissilesChance",
|
||||||
"/Lotus/Upgrades/Calendar/MagazineCapacity",
|
"/Lotus/Upgrades/Calendar/MagazineCapacity",
|
||||||
"/Lotus/Upgrades/Calendar/PunchToPrimary",
|
"/Lotus/Upgrades/Calendar/PunchToPrimary",
|
||||||
"/Lotus/Upgrades/Calendar/HealingEffects",
|
|
||||||
"/Lotus/Upgrades/Calendar/EnergyRestoration",
|
|
||||||
"/Lotus/Upgrades/Calendar/OvershieldCap",
|
|
||||||
"/Lotus/Upgrades/Calendar/ElectricStatusDamageAndChance",
|
|
||||||
"/Lotus/Upgrades/Calendar/FinisherChancePerComboMultiplier",
|
|
||||||
"/Lotus/Upgrades/Calendar/MagnetStatusPull",
|
|
||||||
"/Lotus/Upgrades/Calendar/CompanionsBuffNearbyPlayer",
|
|
||||||
"/Lotus/Upgrades/Calendar/StatusChancePerAmmoSpent",
|
|
||||||
"/Lotus/Upgrades/Calendar/OrbsDuplicateOnPickup",
|
|
||||||
"/Lotus/Upgrades/Calendar/AttackAndMovementSpeedOnCritMelee",
|
|
||||||
"/Lotus/Upgrades/Calendar/RadialJavelinOnHeavy",
|
|
||||||
"/Lotus/Upgrades/Calendar/MagnitizeWithinRangeEveryXCasts",
|
|
||||||
"/Lotus/Upgrades/Calendar/CompanionsRadiationChance",
|
|
||||||
"/Lotus/Upgrades/Calendar/BlastEveryXShots",
|
|
||||||
"/Lotus/Upgrades/Calendar/GenerateOmniOrbsOnWeakKill",
|
|
||||||
"/Lotus/Upgrades/Calendar/ElectricDamagePerDistance",
|
|
||||||
"/Lotus/Upgrades/Calendar/MeleeSlideFowardMomentumOnEnemyHit",
|
|
||||||
"/Lotus/Upgrades/Calendar/SharedFreeAbilityEveryXCasts",
|
|
||||||
"/Lotus/Upgrades/Calendar/ReviveEnemyAsSpectreOnKill",
|
|
||||||
"/Lotus/Upgrades/Calendar/RefundBulletOnStatusProc",
|
"/Lotus/Upgrades/Calendar/RefundBulletOnStatusProc",
|
||||||
"/Lotus/Upgrades/Calendar/ExplodingHealthOrbs",
|
"/Lotus/Upgrades/Calendar/StatusChancePerAmmoSpent"
|
||||||
"/Lotus/Upgrades/Calendar/SpeedBuffsWhenAirborne",
|
]
|
||||||
"/Lotus/Upgrades/Calendar/EnergyWavesOnCombo",
|
|
||||||
"/Lotus/Upgrades/Calendar/PowerStrengthAndEfficiencyPerEnergySpent",
|
|
||||||
"/Lotus/Upgrades/Calendar/CloneActiveCompanionForEnergySpent",
|
|
||||||
"/Lotus/Upgrades/Calendar/GuidingMissilesChance",
|
|
||||||
"/Lotus/Upgrades/Calendar/EnergyOrbsGrantShield",
|
|
||||||
"/Lotus/Upgrades/Calendar/ElectricalDamageOnBulletJump"
|
|
||||||
];
|
];
|
||||||
for (let i = 0; i != upgradeRanges.length - 1; ++i) {
|
for (let i = 0; i != upgradeRanges.length - 1; ++i) {
|
||||||
const upgradeIndex = rng.randomInt(0, upgrades.length - 1);
|
// Pick 3 unique hex members
|
||||||
const upgrade = upgrades[upgradeIndex];
|
const hexMembersPickedForThisDay: number[] = [];
|
||||||
upgrades.splice(upgradeIndex, 1);
|
for (let j = 0; j != 3; ++j) {
|
||||||
|
let hexMemberIndex: number;
|
||||||
|
do {
|
||||||
|
hexMemberIndex = rng.randomInt(0, upgradesByHexMember.length - 1);
|
||||||
|
} while (hexMembersPickedForThisDay.indexOf(hexMemberIndex) != -1);
|
||||||
|
hexMembersPickedForThisDay.push(hexMemberIndex);
|
||||||
|
}
|
||||||
|
hexMembersPickedForThisDay.sort(); // Always present them in the same order
|
||||||
|
|
||||||
//logger.debug(`trying to fit an upgrade between day ${upgradeRanges[i]} and ${upgradeRanges[i + 1]}`);
|
// For each hex member, pick an upgrade that was not yet picked this season.
|
||||||
|
const events: ICalendarEvent[] = [];
|
||||||
|
for (const hexMemberIndex of hexMembersPickedForThisDay) {
|
||||||
|
const upgrades = upgradesByHexMember[hexMemberIndex];
|
||||||
|
const upgradeIndex = rng.randomInt(0, upgrades.length - 1);
|
||||||
|
events.push({ type: "CET_UPGRADE", upgrade: upgrades[upgradeIndex] });
|
||||||
|
upgrades.splice(upgradeIndex, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//logger.debug(`trying to fit upgrades between day ${upgradeRanges[i]} and ${upgradeRanges[i + 1]}`);
|
||||||
let day: number;
|
let day: number;
|
||||||
do {
|
do {
|
||||||
day = rng.randomInt(upgradeRanges[i] + 1, upgradeRanges[i + 1] - 1);
|
day = rng.randomInt(upgradeRanges[i] + 1, upgradeRanges[i + 1] - 1);
|
||||||
} while (eventDays.find(x => x.day == day));
|
} while (eventDays.find(x => x.day == day));
|
||||||
eventDays.push({ day, events: [{ type: "CET_UPGRADE", upgrade }] });
|
eventDays.push({ day, events });
|
||||||
}
|
}
|
||||||
|
|
||||||
eventDays.sort((a, b) => a.day - b.day);
|
eventDays.sort((a, b) => a.day - b.day);
|
||||||
@ -644,7 +683,7 @@ const getCalendarSeason = (week: number): ICalendarSeason => {
|
|||||||
Activation: { $date: { $numberLong: weekStart.toString() } },
|
Activation: { $date: { $numberLong: weekStart.toString() } },
|
||||||
Expiry: { $date: { $numberLong: weekEnd.toString() } },
|
Expiry: { $date: { $numberLong: weekEnd.toString() } },
|
||||||
Days: eventDays,
|
Days: eventDays,
|
||||||
Season: ["CST_WINTER", "CST_SPRING", "CST_SUMMER", "CST_FALL"][seasonIndex],
|
Season: (["CST_WINTER", "CST_SPRING", "CST_SUMMER", "CST_FALL"] as const)[seasonIndex],
|
||||||
YearIteration: Math.trunc(week / 4),
|
YearIteration: Math.trunc(week / 4),
|
||||||
Version: 19,
|
Version: 19,
|
||||||
UpgradeAvaliabilityRequirements: ["/Lotus/Upgrades/Calendar/1999UpgradeApplicationRequirement"]
|
UpgradeAvaliabilityRequirements: ["/Lotus/Upgrades/Calendar/1999UpgradeApplicationRequirement"]
|
||||||
@ -710,7 +749,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Elite Sanctuary Onslaught cycling every week
|
// Elite Sanctuary Onslaught cycling every week
|
||||||
worldState.NodeOverrides.find(x => x.Node == "SolNode802")!.Seed = week; // unfaithful
|
worldState.NodeOverrides.find(x => x.Node == "SolNode802")!.Seed = new CRng(week).randomInt(0, 0xffff);
|
||||||
|
|
||||||
// Holdfast, Cavia, & Hex bounties cycling every 2.5 hours; unfaithful implementation
|
// Holdfast, Cavia, & Hex bounties cycling every 2.5 hours; unfaithful implementation
|
||||||
let bountyCycle = Math.trunc(Date.now() / 9000000);
|
let bountyCycle = Math.trunc(Date.now() / 9000000);
|
||||||
@ -719,7 +758,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
const bountyCycleStart = bountyCycle * 9000000;
|
const bountyCycleStart = bountyCycle * 9000000;
|
||||||
bountyCycleEnd = bountyCycleStart + 9000000;
|
bountyCycleEnd = bountyCycleStart + 9000000;
|
||||||
worldState.SyndicateMissions.push({
|
worldState.SyndicateMissions.push({
|
||||||
_id: { $oid: Math.trunc(bountyCycleStart / 1000).toString(16) + "0000000000000029" },
|
_id: { $oid: ((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000029" },
|
||||||
Activation: { $date: { $numberLong: bountyCycleStart.toString() } },
|
Activation: { $date: { $numberLong: bountyCycleStart.toString() } },
|
||||||
Expiry: { $date: { $numberLong: bountyCycleEnd.toString() } },
|
Expiry: { $date: { $numberLong: bountyCycleEnd.toString() } },
|
||||||
Tag: "ZarimanSyndicate",
|
Tag: "ZarimanSyndicate",
|
||||||
@ -727,7 +766,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
Nodes: []
|
Nodes: []
|
||||||
});
|
});
|
||||||
worldState.SyndicateMissions.push({
|
worldState.SyndicateMissions.push({
|
||||||
_id: { $oid: Math.trunc(bountyCycleStart / 1000).toString(16) + "0000000000000004" },
|
_id: { $oid: ((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000004" },
|
||||||
Activation: { $date: { $numberLong: bountyCycleStart.toString() } },
|
Activation: { $date: { $numberLong: bountyCycleStart.toString() } },
|
||||||
Expiry: { $date: { $numberLong: bountyCycleEnd.toString() } },
|
Expiry: { $date: { $numberLong: bountyCycleEnd.toString() } },
|
||||||
Tag: "EntratiLabSyndicate",
|
Tag: "EntratiLabSyndicate",
|
||||||
@ -735,7 +774,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
Nodes: []
|
Nodes: []
|
||||||
});
|
});
|
||||||
worldState.SyndicateMissions.push({
|
worldState.SyndicateMissions.push({
|
||||||
_id: { $oid: Math.trunc(bountyCycleStart / 1000).toString(16) + "0000000000000006" },
|
_id: { $oid: ((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000006" },
|
||||||
Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
|
Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
|
||||||
Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
|
Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
|
||||||
Tag: "HexSyndicate",
|
Tag: "HexSyndicate",
|
||||||
@ -749,14 +788,18 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
|
|
||||||
// TODO: xpAmounts need to be calculated based on the jobType somehow?
|
// TODO: xpAmounts need to be calculated based on the jobType somehow?
|
||||||
|
|
||||||
|
const seed = new CRng(bountyCycle).randomInt(0, 0xffff);
|
||||||
|
|
||||||
{
|
{
|
||||||
const rng = new CRng(bountyCycle);
|
const rng = new CRng(seed);
|
||||||
worldState.SyndicateMissions.push({
|
worldState.SyndicateMissions.push({
|
||||||
_id: { $oid: Math.trunc(bountyCycleStart / 1000).toString(16) + "0000000000000008" },
|
_id: {
|
||||||
|
$oid: ((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000008"
|
||||||
|
},
|
||||||
Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
|
Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
|
||||||
Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
|
Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
|
||||||
Tag: "CetusSyndicate",
|
Tag: "CetusSyndicate",
|
||||||
Seed: bountyCycle,
|
Seed: seed,
|
||||||
Nodes: [],
|
Nodes: [],
|
||||||
Jobs: [
|
Jobs: [
|
||||||
{
|
{
|
||||||
@ -820,13 +863,15 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const rng = new CRng(bountyCycle);
|
const rng = new CRng(seed);
|
||||||
worldState.SyndicateMissions.push({
|
worldState.SyndicateMissions.push({
|
||||||
_id: { $oid: Math.trunc(bountyCycleStart / 1000).toString(16) + "0000000000000025" },
|
_id: {
|
||||||
|
$oid: ((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000025"
|
||||||
|
},
|
||||||
Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
|
Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
|
||||||
Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
|
Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
|
||||||
Tag: "SolarisSyndicate",
|
Tag: "SolarisSyndicate",
|
||||||
Seed: bountyCycle,
|
Seed: seed,
|
||||||
Nodes: [],
|
Nodes: [],
|
||||||
Jobs: [
|
Jobs: [
|
||||||
{
|
{
|
||||||
@ -890,13 +935,15 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const rng = new CRng(bountyCycle);
|
const rng = new CRng(seed);
|
||||||
worldState.SyndicateMissions.push({
|
worldState.SyndicateMissions.push({
|
||||||
_id: { $oid: Math.trunc(bountyCycleStart / 1000).toString(16) + "0000000000000002" },
|
_id: {
|
||||||
|
$oid: ((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000002"
|
||||||
|
},
|
||||||
Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
|
Activation: { $date: { $numberLong: bountyCycleStart.toString(10) } },
|
||||||
Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
|
Expiry: { $date: { $numberLong: bountyCycleEnd.toString(10) } },
|
||||||
Tag: "EntratiSyndicate",
|
Tag: "EntratiSyndicate",
|
||||||
Seed: bountyCycle,
|
Seed: seed,
|
||||||
Nodes: [],
|
Nodes: [],
|
||||||
Jobs: [
|
Jobs: [
|
||||||
{
|
{
|
||||||
@ -1119,7 +1166,8 @@ export const getLiteSortie = (week: number): ILiteSortie => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const rng = new CRng(week);
|
const seed = new CRng(week).randomInt(0, 0xffff);
|
||||||
|
const rng = new CRng(seed);
|
||||||
const firstNodeIndex = rng.randomInt(0, nodes.length - 1);
|
const firstNodeIndex = rng.randomInt(0, nodes.length - 1);
|
||||||
const firstNode = nodes[firstNodeIndex];
|
const firstNode = nodes[firstNodeIndex];
|
||||||
nodes.splice(firstNodeIndex, 1);
|
nodes.splice(firstNodeIndex, 1);
|
||||||
@ -1128,12 +1176,12 @@ export const getLiteSortie = (week: number): ILiteSortie => {
|
|||||||
const weekEnd = weekStart + 604800000;
|
const weekEnd = weekStart + 604800000;
|
||||||
return {
|
return {
|
||||||
_id: {
|
_id: {
|
||||||
$oid: Math.trunc(weekStart / 1000).toString(16) + "5e23a244740a190c"
|
$oid: ((weekStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "5e23a244740a190c"
|
||||||
},
|
},
|
||||||
Activation: { $date: { $numberLong: weekStart.toString() } },
|
Activation: { $date: { $numberLong: weekStart.toString() } },
|
||||||
Expiry: { $date: { $numberLong: weekEnd.toString() } },
|
Expiry: { $date: { $numberLong: weekEnd.toString() } },
|
||||||
Reward: "/Lotus/Types/Game/MissionDecks/ArchonSortieRewards",
|
Reward: "/Lotus/Types/Game/MissionDecks/ArchonSortieRewards",
|
||||||
Seed: week,
|
Seed: seed,
|
||||||
Boss: boss,
|
Boss: boss,
|
||||||
Missions: [
|
Missions: [
|
||||||
{
|
{
|
||||||
|
@ -11,6 +11,7 @@ export interface IGuildClient {
|
|||||||
Members: IGuildMemberClient[];
|
Members: IGuildMemberClient[];
|
||||||
Ranks: IGuildRank[];
|
Ranks: IGuildRank[];
|
||||||
Tier: number;
|
Tier: number;
|
||||||
|
Emblem?: boolean;
|
||||||
Vault: IGuildVault;
|
Vault: IGuildVault;
|
||||||
ActiveDojoColorResearch: string;
|
ActiveDojoColorResearch: string;
|
||||||
Class: number;
|
Class: number;
|
||||||
|
@ -134,7 +134,7 @@ export const equipmentKeys = [
|
|||||||
export type TEquipmentKey = (typeof equipmentKeys)[number];
|
export type TEquipmentKey = (typeof equipmentKeys)[number];
|
||||||
|
|
||||||
export interface IDuviriInfo {
|
export interface IDuviriInfo {
|
||||||
Seed: number;
|
Seed: bigint;
|
||||||
NumCompletions: number;
|
NumCompletions: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,7 +202,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
|
|||||||
Mailbox?: IMailboxClient;
|
Mailbox?: IMailboxClient;
|
||||||
SubscribedToEmails: number;
|
SubscribedToEmails: number;
|
||||||
Created: IMongoDate;
|
Created: IMongoDate;
|
||||||
RewardSeed: number | bigint;
|
RewardSeed: bigint;
|
||||||
RegularCredits: number;
|
RegularCredits: number;
|
||||||
PremiumCredits: number;
|
PremiumCredits: number;
|
||||||
PremiumCreditsFree: number;
|
PremiumCreditsFree: number;
|
||||||
@ -353,7 +353,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
|
|||||||
DeathSquadable: boolean;
|
DeathSquadable: boolean;
|
||||||
EndlessXP?: IEndlessXpProgress[];
|
EndlessXP?: IEndlessXpProgress[];
|
||||||
DialogueHistory?: IDialogueHistoryClient;
|
DialogueHistory?: IDialogueHistoryClient;
|
||||||
CalendarProgress: ICalendarProgress;
|
CalendarProgress?: ICalendarProgress;
|
||||||
SongChallenges?: ISongChallenge[];
|
SongChallenges?: ISongChallenge[];
|
||||||
EntratiVaultCountLastPeriod?: number;
|
EntratiVaultCountLastPeriod?: number;
|
||||||
EntratiVaultCountResetDate?: IMongoDate;
|
EntratiVaultCountResetDate?: IMongoDate;
|
||||||
@ -845,7 +845,7 @@ export interface IMission extends IMissionDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface INemesisBaseClient {
|
export interface INemesisBaseClient {
|
||||||
fp: bigint;
|
fp: bigint | number;
|
||||||
manifest: string;
|
manifest: string;
|
||||||
KillingSuit: string;
|
KillingSuit: string;
|
||||||
killingDamageType: number;
|
killingDamageType: number;
|
||||||
@ -863,7 +863,8 @@ export interface INemesisBaseClient {
|
|||||||
Weakened: boolean;
|
Weakened: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface INemesisBaseDatabase extends Omit<INemesisBaseClient, "d"> {
|
export interface INemesisBaseDatabase extends Omit<INemesisBaseClient, "fp" | "d"> {
|
||||||
|
fp: bigint;
|
||||||
d: Date;
|
d: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -877,7 +878,8 @@ export interface INemesisClient extends INemesisBaseClient {
|
|||||||
LastEnc: number;
|
LastEnc: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface INemesisDatabase extends Omit<INemesisClient, "d"> {
|
export interface INemesisDatabase extends Omit<INemesisClient, "fp" | "d"> {
|
||||||
|
fp: bigint;
|
||||||
d: Date;
|
d: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1193,17 +1195,18 @@ export interface IMarker {
|
|||||||
z: number;
|
z: number;
|
||||||
showInHud: boolean;
|
showInHud: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ISeasonProgress {
|
export interface ISeasonProgress {
|
||||||
SeasonType: "CST_UNDEFINED" | "CST_WINTER" | "CST_SPRING" | "CST_SUMMER" | "CST_FALL";
|
SeasonType: "CST_WINTER" | "CST_SPRING" | "CST_SUMMER" | "CST_FALL";
|
||||||
LastCompletedDayIdx: number;
|
LastCompletedDayIdx: number;
|
||||||
LastCompletedChallengeDayIdx: number;
|
LastCompletedChallengeDayIdx: number;
|
||||||
ActivatedChallenges: unknown[];
|
ActivatedChallenges: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICalendarProgress {
|
export interface ICalendarProgress {
|
||||||
Version: number;
|
Version: number;
|
||||||
Iteration: number;
|
Iteration: number;
|
||||||
YearProgress: { Upgrades: unknown[] };
|
YearProgress: { Upgrades: string[] };
|
||||||
SeasonProgress: ISeasonProgress;
|
SeasonProgress: ISeasonProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ export type IMissionInventoryUpdateRequest = {
|
|||||||
|
|
||||||
SyndicateId?: string;
|
SyndicateId?: string;
|
||||||
SortieId?: string;
|
SortieId?: string;
|
||||||
|
CalendarProgress?: { challenge: string }[];
|
||||||
SeasonChallengeCompletions?: ISeasonChallenge[];
|
SeasonChallengeCompletions?: ISeasonChallenge[];
|
||||||
AffiliationChanges?: IAffiliationChange[];
|
AffiliationChanges?: IAffiliationChange[];
|
||||||
crossPlaySetting?: string;
|
crossPlaySetting?: string;
|
||||||
@ -126,6 +127,15 @@ export type IMissionInventoryUpdateRequest = {
|
|||||||
creditsFee?: number; // the index
|
creditsFee?: number; // the index
|
||||||
InvasionProgress?: IInvasionProgressClient[];
|
InvasionProgress?: IInvasionProgressClient[];
|
||||||
ConquestMissionsCompleted?: number;
|
ConquestMissionsCompleted?: number;
|
||||||
|
duviriSuitSelection?: string;
|
||||||
|
duviriPistolSelection?: string;
|
||||||
|
duviriLongGunSelection?: string;
|
||||||
|
duviriMeleeSelection?: string;
|
||||||
|
duviriCaveOffers?: {
|
||||||
|
Seed: number | bigint;
|
||||||
|
Warframes: string[];
|
||||||
|
Weapons: string[];
|
||||||
|
};
|
||||||
} & {
|
} & {
|
||||||
[K in TEquipmentKey]?: IEquipmentClient[];
|
[K in TEquipmentKey]?: IEquipmentClient[];
|
||||||
};
|
};
|
||||||
@ -135,7 +145,7 @@ export interface IRewardInfo {
|
|||||||
invasionId?: string;
|
invasionId?: string;
|
||||||
invasionAllyFaction?: "FC_GRINEER" | "FC_CORPUS";
|
invasionAllyFaction?: "FC_GRINEER" | "FC_CORPUS";
|
||||||
sortieId?: string;
|
sortieId?: string;
|
||||||
sortieTag?: string;
|
sortieTag?: "Mission1" | "Mission2" | "Final";
|
||||||
sortiePrereqs?: string[];
|
sortiePrereqs?: string[];
|
||||||
VaultsCracked?: number; // for Spy missions
|
VaultsCracked?: number; // for Spy missions
|
||||||
rewardTier?: number;
|
rewardTier?: number;
|
||||||
|
@ -1,18 +1,15 @@
|
|||||||
import { IMongoDate, IOid } from "./commonTypes";
|
import { IMongoDate, IOid } from "./commonTypes";
|
||||||
|
|
||||||
export interface IItemPrice {
|
export interface IItemPrice {
|
||||||
ItemType: string | string[]; // If string[], preprocessing will use RNG to pick one for the current period.
|
ItemType: string;
|
||||||
ItemCount: number;
|
ItemCount: number;
|
||||||
ProductCategory: string;
|
ProductCategory: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IItemPricePreprocessed extends Omit<IItemPrice, "ItemType"> {
|
|
||||||
ItemType: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IItemManifest {
|
export interface IItemManifest {
|
||||||
StoreItem: string;
|
StoreItem: string;
|
||||||
ItemPrices?: IItemPrice[];
|
ItemPrices?: IItemPrice[];
|
||||||
|
RegularPrice?: number[];
|
||||||
Bin: string;
|
Bin: string;
|
||||||
QuantityMultiplier: number;
|
QuantityMultiplier: number;
|
||||||
Expiry: IMongoDate; // Either a date in the distant future or a period in milliseconds for preprocessing.
|
Expiry: IMongoDate; // Either a date in the distant future or a period in milliseconds for preprocessing.
|
||||||
@ -23,10 +20,6 @@ export interface IItemManifest {
|
|||||||
Id: IOid;
|
Id: IOid;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IItemManifestPreprocessed extends Omit<IItemManifest, "ItemPrices"> {
|
|
||||||
ItemPrices?: IItemPricePreprocessed[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IVendorInfo {
|
export interface IVendorInfo {
|
||||||
_id: IOid;
|
_id: IOid;
|
||||||
TypeName: string;
|
TypeName: string;
|
||||||
@ -38,14 +31,6 @@ export interface IVendorInfo {
|
|||||||
Expiry: IMongoDate; // Either a date in the distant future or a period in milliseconds for preprocessing.
|
Expiry: IMongoDate; // Either a date in the distant future or a period in milliseconds for preprocessing.
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IVendorInfoPreprocessed extends Omit<IVendorInfo, "ItemManifest"> {
|
export interface IVendorManifest {
|
||||||
ItemManifest: IItemManifestPreprocessed[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IRawVendorManifest {
|
|
||||||
VendorInfo: IVendorInfo;
|
VendorInfo: IVendorInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IVendorManifestPreprocessed {
|
|
||||||
VendorInfo: IVendorInfoPreprocessed;
|
|
||||||
}
|
|
||||||
|
@ -133,7 +133,7 @@ export interface ISeasonChallenge {
|
|||||||
export interface ICalendarSeason {
|
export interface ICalendarSeason {
|
||||||
Activation: IMongoDate;
|
Activation: IMongoDate;
|
||||||
Expiry: IMongoDate;
|
Expiry: IMongoDate;
|
||||||
Season: string; // "CST_UNDEFINED" | "CST_WINTER" | "CST_SPRING" | "CST_SUMMER" | "CST_FALL"
|
Season: "CST_WINTER" | "CST_SPRING" | "CST_SUMMER" | "CST_FALL";
|
||||||
Days: ICalendarDay[];
|
Days: ICalendarDay[];
|
||||||
YearIteration: number;
|
YearIteration: number;
|
||||||
Version: number;
|
Version: number;
|
||||||
|
49
static/fixed_responses/allIncarnonList.json
Normal file
49
static/fixed_responses/allIncarnonList.json
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
[
|
||||||
|
"/Lotus/Weapons/ClanTech/Bio/BioWeapon",
|
||||||
|
"/Lotus/Weapons/ClanTech/Energy/EnergyRifle",
|
||||||
|
"/Lotus/Weapons/Corpus/Pistols/CorpusMinigun/CorpusMinigun",
|
||||||
|
"/Lotus/Weapons/Corpus/Pistols/CrpHandRL/CorpusHandRocketLauncher",
|
||||||
|
"/Lotus/Weapons/Grineer/LongGuns/GrineerSawbladeGun/SawBladeGun",
|
||||||
|
"/Lotus/Weapons/Grineer/Melee/GrineerTylAxeAndBoar/RegorAxeShield",
|
||||||
|
"/Lotus/Weapons/Grineer/Pistols/HeatGun/GrnHeatGun",
|
||||||
|
"/Lotus/Weapons/Infested/Pistols/InfVomitGun/InfVomitGunWep",
|
||||||
|
"/Lotus/Weapons/Syndicates/CephalonSuda/Pistols/CSDroidArray",
|
||||||
|
"/Lotus/Weapons/Tenno/Bows/HuntingBow",
|
||||||
|
"/Lotus/Weapons/Tenno/Bows/StalkerBow",
|
||||||
|
"/Lotus/Weapons/Tenno/LongGuns/TnoLeverAction/TnoLeverActionRifle",
|
||||||
|
"/Lotus/Weapons/Tenno/Melee/Axe/DualInfestedAxesWeapon",
|
||||||
|
"/Lotus/Weapons/Tenno/Melee/Dagger/CeramicDagger",
|
||||||
|
"/Lotus/Weapons/Tenno/Melee/Fist/Fist",
|
||||||
|
"/Lotus/Weapons/Tenno/Melee/Hammer/IceHammer/IceHammer",
|
||||||
|
"/Lotus/Weapons/Tenno/Melee/LongSword/LongSword",
|
||||||
|
"/Lotus/Weapons/Tenno/Melee/Maces/PaladinMace/PaladinMaceWeapon",
|
||||||
|
"/Lotus/Weapons/Tenno/Melee/Scythe/StalkerScytheWeapon",
|
||||||
|
"/Lotus/Weapons/Tenno/Melee/Scythe/ParisScythe/ParisScythe",
|
||||||
|
"/Lotus/Weapons/Tenno/Melee/Staff/Staff",
|
||||||
|
"/Lotus/Weapons/Tenno/Melee/Swords/CutlassAndPoignard/TennoCutlass",
|
||||||
|
"/Lotus/Weapons/Tenno/Melee/Swords/TennoSai/TennoSais",
|
||||||
|
"/Lotus/Weapons/Tenno/Pistol/AutoPistol",
|
||||||
|
"/Lotus/Weapons/Tenno/Pistol/BurstPistol",
|
||||||
|
"/Lotus/Weapons/Tenno/Pistol/HandShotGun",
|
||||||
|
"/Lotus/Weapons/Tenno/Pistol/HeavyPistol",
|
||||||
|
"/Lotus/Weapons/Tenno/Pistol/Pistol",
|
||||||
|
"/Lotus/Weapons/Tenno/Pistol/RevolverPistol",
|
||||||
|
"/Lotus/Weapons/Tenno/Pistols/ConclaveLeverPistol/ConclaveLeverPistol",
|
||||||
|
"/Lotus/Weapons/Tenno/Rifle/BoltoRifle",
|
||||||
|
"/Lotus/Weapons/Tenno/Rifle/BurstRifle",
|
||||||
|
"/Lotus/Weapons/Tenno/Rifle/HeavyRifle",
|
||||||
|
"/Lotus/Weapons/Tenno/Rifle/Rifle",
|
||||||
|
"/Lotus/Weapons/Tenno/Rifle/SemiAutoRifle",
|
||||||
|
"/Lotus/Weapons/Tenno/Rifle/TennoAR",
|
||||||
|
"/Lotus/Weapons/Tenno/Shotgun/FullAutoShotgun",
|
||||||
|
"/Lotus/Weapons/Tenno/Shotgun/Shotgun",
|
||||||
|
"/Lotus/Weapons/Tenno/ThrowingWeapons/Kunai",
|
||||||
|
"/Lotus/Weapons/Tenno/ThrowingWeapons/StalkerKunai",
|
||||||
|
"/Lotus/Weapons/Tenno/Zariman/LongGuns/PumpShotgun/ZarimanPumpShotgun",
|
||||||
|
"/Lotus/Weapons/Tenno/Zariman/LongGuns/SemiAutoRifle/ZarimanSemiAutoRifle",
|
||||||
|
"/Lotus/Weapons/Tenno/Zariman/Melee/Dagger/ZarimanDaggerWeapon",
|
||||||
|
"/Lotus/Weapons/Tenno/Zariman/Melee/Tonfas/ZarimanTonfaWeapon",
|
||||||
|
"/Lotus/Weapons/Tenno/Zariman/Pistols/HeavyPistol/ZarimanHeavyPistol",
|
||||||
|
"/Lotus/Weapons/Thanotech/EntFistIncarnon/EntFistIncarnon",
|
||||||
|
"/Lotus/Weapons/Thanotech/EntratiWristGun/EntratiWristGunWeapon"
|
||||||
|
]
|
@ -1098,5 +1098,6 @@
|
|||||||
"/Lotus/Types/LevelObjects/InfestedPumpkinCocoonLampLarge",
|
"/Lotus/Types/LevelObjects/InfestedPumpkinCocoonLampLarge",
|
||||||
"/Lotus/Types/LevelObjects/InfestedPumpkinCocoonLampSmall",
|
"/Lotus/Types/LevelObjects/InfestedPumpkinCocoonLampSmall",
|
||||||
"/Lotus/Types/LevelObjects/InfestedPumpkinExplosiveTotem",
|
"/Lotus/Types/LevelObjects/InfestedPumpkinExplosiveTotem",
|
||||||
"/Lotus/Types/Enemies/Orokin/OrokinMoaBipedAvatar"
|
"/Lotus/Types/Enemies/Orokin/OrokinMoaBipedAvatar",
|
||||||
|
"/Lotus/Types/Enemies/Grineer/AIWeek/Avatars/BeastMasterAvatar"
|
||||||
]
|
]
|
||||||
|
@ -1,101 +0,0 @@
|
|||||||
{
|
|
||||||
"VendorInfo": {
|
|
||||||
"_id": { "$oid": "61ba123467e5d37975aeeb03" },
|
|
||||||
"TypeName": "/Lotus/Types/Game/VendorManifests/Hubs/GuildAdvertisementVendorManifest",
|
|
||||||
"ItemManifest": [
|
|
||||||
{
|
|
||||||
"StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementMoon",
|
|
||||||
"ItemPrices": [
|
|
||||||
{
|
|
||||||
"ItemType": ["/Lotus/Types/Items/Research/BioFragment", "/Lotus/Types/Items/Research/ChemComponent", "/Lotus/Types/Items/Research/EnergyFragment"],
|
|
||||||
"ItemCount": 12,
|
|
||||||
"ProductCategory": "MiscItems"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"RegularPrice": [1, 1],
|
|
||||||
"Bin": "BIN_4",
|
|
||||||
"QuantityMultiplier": 1,
|
|
||||||
"Expiry": { "$date": { "$numberLong": "604800000" } },
|
|
||||||
"PurchaseQuantityLimit": 1,
|
|
||||||
"AllowMultipurchase": false,
|
|
||||||
"LocTagRandSeed": 79554843,
|
|
||||||
"Id": { "$oid": "67bbb592e1534511d6c1c1e2" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementMountain",
|
|
||||||
"ItemPrices": [
|
|
||||||
{
|
|
||||||
"ItemType": ["/Lotus/Types/Items/Research/BioFragment", "/Lotus/Types/Items/Research/ChemComponent", "/Lotus/Types/Items/Research/EnergyFragment"],
|
|
||||||
"ItemCount": 7,
|
|
||||||
"ProductCategory": "MiscItems"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"RegularPrice": [1, 1],
|
|
||||||
"Bin": "BIN_3",
|
|
||||||
"QuantityMultiplier": 1,
|
|
||||||
"Expiry": { "$date": { "$numberLong": "604800000" } },
|
|
||||||
"PurchaseQuantityLimit": 1,
|
|
||||||
"AllowMultipurchase": false,
|
|
||||||
"LocTagRandSeed": 2413820225,
|
|
||||||
"Id": { "$oid": "67bbb592e1534511d6c1c1e3" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementStorm",
|
|
||||||
"ItemPrices": [
|
|
||||||
{
|
|
||||||
"ItemType": ["/Lotus/Types/Items/Research/BioFragment", "/Lotus/Types/Items/Research/ChemComponent", "/Lotus/Types/Items/Research/EnergyFragment"],
|
|
||||||
"ItemCount": 3,
|
|
||||||
"ProductCategory": "MiscItems"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"RegularPrice": [1, 1],
|
|
||||||
"Bin": "BIN_2",
|
|
||||||
"QuantityMultiplier": 1,
|
|
||||||
"Expiry": { "$date": { "$numberLong": "604800000" } },
|
|
||||||
"PurchaseQuantityLimit": 1,
|
|
||||||
"AllowMultipurchase": false,
|
|
||||||
"LocTagRandSeed": 3262300883,
|
|
||||||
"Id": { "$oid": "67bbb592e1534511d6c1c1e4" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementShadow",
|
|
||||||
"ItemPrices": [
|
|
||||||
{
|
|
||||||
"ItemType": ["/Lotus/Types/Items/Research/BioFragment", "/Lotus/Types/Items/Research/ChemComponent", "/Lotus/Types/Items/Research/EnergyFragment"],
|
|
||||||
"ItemCount": 20,
|
|
||||||
"ProductCategory": "MiscItems"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"RegularPrice": [1, 1],
|
|
||||||
"Bin": "BIN_1",
|
|
||||||
"QuantityMultiplier": 1,
|
|
||||||
"Expiry": { "$date": { "$numberLong": "604800000" } },
|
|
||||||
"PurchaseQuantityLimit": 1,
|
|
||||||
"AllowMultipurchase": false,
|
|
||||||
"LocTagRandSeed": 2797325750,
|
|
||||||
"Id": { "$oid": "67bbb592e1534511d6c1c1e5" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementGhost",
|
|
||||||
"ItemPrices": [
|
|
||||||
{
|
|
||||||
"ItemType": ["/Lotus/Types/Items/Research/BioFragment", "/Lotus/Types/Items/Research/ChemComponent", "/Lotus/Types/Items/Research/EnergyFragment"],
|
|
||||||
"ItemCount": 10,
|
|
||||||
"ProductCategory": "MiscItems"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"RegularPrice": [1, 1],
|
|
||||||
"Bin": "BIN_0",
|
|
||||||
"QuantityMultiplier": 1,
|
|
||||||
"Expiry": { "$date": { "$numberLong": "604800000" } },
|
|
||||||
"PurchaseQuantityLimit": 1,
|
|
||||||
"AllowMultipurchase": false,
|
|
||||||
"LocTagRandSeed": 554932310,
|
|
||||||
"Id": { "$oid": "67bbb592e1534511d6c1c1e6" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"PropertyTextHash": "255AFE2169BAE4130B4B20D7C55D14FA",
|
|
||||||
"RandomSeedType": "VRST_FLAVOUR_TEXT",
|
|
||||||
"Expiry": { "$date": { "$numberLong": "604800000" } }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,248 +0,0 @@
|
|||||||
{
|
|
||||||
"VendorInfo": {
|
|
||||||
"_id": {
|
|
||||||
"$oid": "5be4a159b144f3cdf1c22efa"
|
|
||||||
},
|
|
||||||
"TypeName": "/Lotus/Types/Game/VendorManifests/Solaris/DebtTokenVendorManifest",
|
|
||||||
"ItemManifest": [
|
|
||||||
{
|
|
||||||
"StoreItem": "/Lotus/Types/StoreItems/Packages/DebtTokenBundles/DebtTokenBundleUncommonD",
|
|
||||||
"ItemPrices": [
|
|
||||||
{
|
|
||||||
"ItemType": "/Lotus/Types/Gameplay/Venus/Resources/VenusCoconutItem",
|
|
||||||
"ItemCount": 5,
|
|
||||||
"ProductCategory": "MiscItems"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ItemType": "/Lotus/Types/Items/MiscItems/Circuits",
|
|
||||||
"ItemCount": 3664,
|
|
||||||
"ProductCategory": "MiscItems"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"RegularPrice": [87300, 87300],
|
|
||||||
"Bin": "BIN_1",
|
|
||||||
"QuantityMultiplier": 1,
|
|
||||||
"Expiry": {
|
|
||||||
"$date": {
|
|
||||||
"$numberLong": "9999999000000"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"PurchaseQuantityLimit": 1,
|
|
||||||
"AllowMultipurchase": true,
|
|
||||||
"LocTagRandSeed": 1881404827,
|
|
||||||
"Id": {
|
|
||||||
"$oid": "670daf92d21f34757a5e73b4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StoreItem": "/Lotus/Types/StoreItems/Packages/DebtTokenBundles/DebtTokenBundleRareC",
|
|
||||||
"ItemPrices": [
|
|
||||||
{
|
|
||||||
"ItemType": "/Lotus/Types/Items/MiscItems/NeuralSensor",
|
|
||||||
"ItemCount": 1,
|
|
||||||
"ProductCategory": "MiscItems"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"RegularPrice": [53300, 53300],
|
|
||||||
"Bin": "BIN_2",
|
|
||||||
"QuantityMultiplier": 1,
|
|
||||||
"Expiry": {
|
|
||||||
"$date": {
|
|
||||||
"$numberLong": "9999999000000"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"PurchaseQuantityLimit": 1,
|
|
||||||
"AllowMultipurchase": true,
|
|
||||||
"LocTagRandSeed": 1943984533,
|
|
||||||
"Id": {
|
|
||||||
"$oid": "6710b5029e1a3080a65e73a7"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StoreItem": "/Lotus/Types/StoreItems/Packages/DebtTokenBundles/DebtTokenBundleCommonG",
|
|
||||||
"ItemPrices": [
|
|
||||||
{
|
|
||||||
"ItemType": "/Lotus/Types/Items/MiscItems/Salvage",
|
|
||||||
"ItemCount": 11540,
|
|
||||||
"ProductCategory": "MiscItems"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"RegularPrice": [27300, 27300],
|
|
||||||
"Bin": "BIN_0",
|
|
||||||
"QuantityMultiplier": 1,
|
|
||||||
"Expiry": {
|
|
||||||
"$date": {
|
|
||||||
"$numberLong": "9999999000000"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"PurchaseQuantityLimit": 1,
|
|
||||||
"AllowMultipurchase": true,
|
|
||||||
"LocTagRandSeed": 744199559,
|
|
||||||
"Id": {
|
|
||||||
"$oid": "67112582cc115756985e73a4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StoreItem": "/Lotus/Types/StoreItems/Packages/DebtTokenBundles/DebtTokenBundleUncommonB",
|
|
||||||
"ItemPrices": [
|
|
||||||
{
|
|
||||||
"ItemType": "/Lotus/Types/Items/Fish/Solaris/FishParts/CorpusFishThermalLaserItem",
|
|
||||||
"ItemCount": 9,
|
|
||||||
"ProductCategory": "MiscItems"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"RegularPrice": [75800, 75800],
|
|
||||||
"Bin": "BIN_1",
|
|
||||||
"QuantityMultiplier": 1,
|
|
||||||
"Expiry": {
|
|
||||||
"$date": {
|
|
||||||
"$numberLong": "9999999000000"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"PurchaseQuantityLimit": 1,
|
|
||||||
"AllowMultipurchase": true,
|
|
||||||
"LocTagRandSeed": 3744711432,
|
|
||||||
"Id": {
|
|
||||||
"$oid": "670de7d28a6ec82cd25e73a2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StoreItem": "/Lotus/Types/StoreItems/Packages/DebtTokenBundles/DebtTokenBundleUncommonB",
|
|
||||||
"ItemPrices": [
|
|
||||||
{
|
|
||||||
"ItemType": "/Lotus/Types/Items/MiscItems/Rubedo",
|
|
||||||
"ItemCount": 3343,
|
|
||||||
"ProductCategory": "MiscItems"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"RegularPrice": [52200, 52200],
|
|
||||||
"Bin": "BIN_1",
|
|
||||||
"QuantityMultiplier": 1,
|
|
||||||
"Expiry": {
|
|
||||||
"$date": {
|
|
||||||
"$numberLong": "9999999000000"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"PurchaseQuantityLimit": 1,
|
|
||||||
"AllowMultipurchase": true,
|
|
||||||
"LocTagRandSeed": 1579000687,
|
|
||||||
"Id": {
|
|
||||||
"$oid": "670e58526171148e125e73ad"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StoreItem": "/Lotus/Types/StoreItems/Packages/DebtTokenBundles/DebtTokenBundleCommonA",
|
|
||||||
"ItemPrices": [
|
|
||||||
{
|
|
||||||
"ItemType": "/Lotus/Types/Gameplay/Venus/Resources/CoolantItem",
|
|
||||||
"ItemCount": 9,
|
|
||||||
"ProductCategory": "MiscItems"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ItemType": "/Lotus/Types/Items/Fish/Solaris/FishParts/CorpusFishAnoscopicSensorItem",
|
|
||||||
"ItemCount": 5,
|
|
||||||
"ProductCategory": "MiscItems"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"RegularPrice": [12400, 12400],
|
|
||||||
"Bin": "BIN_0",
|
|
||||||
"QuantityMultiplier": 1,
|
|
||||||
"Expiry": {
|
|
||||||
"$date": {
|
|
||||||
"$numberLong": "9999999000000"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"PurchaseQuantityLimit": 1,
|
|
||||||
"AllowMultipurchase": true,
|
|
||||||
"LocTagRandSeed": 3589081466,
|
|
||||||
"Id": {
|
|
||||||
"$oid": "67112582cc115756985e73a5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StoreItem": "/Lotus/Types/StoreItems/Packages/DebtTokenBundles/DebtTokenBundleUncommonC",
|
|
||||||
"ItemPrices": [
|
|
||||||
{
|
|
||||||
"ItemType": "/Lotus/Types/Items/Gems/Solaris/SolarisCommonOreBAlloyItem",
|
|
||||||
"ItemCount": 13,
|
|
||||||
"ProductCategory": "MiscItems"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"RegularPrice": [77500, 77500],
|
|
||||||
"Bin": "BIN_1",
|
|
||||||
"QuantityMultiplier": 1,
|
|
||||||
"Expiry": {
|
|
||||||
"$date": {
|
|
||||||
"$numberLong": "9999999000000"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"PurchaseQuantityLimit": 1,
|
|
||||||
"AllowMultipurchase": true,
|
|
||||||
"LocTagRandSeed": 1510234814,
|
|
||||||
"Id": {
|
|
||||||
"$oid": "670f0f21250ad046c35e73ee"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StoreItem": "/Lotus/Types/StoreItems/Packages/DebtTokenBundles/DebtTokenBundleUncommonD",
|
|
||||||
"ItemPrices": [
|
|
||||||
{
|
|
||||||
"ItemType": "/Lotus/Types/Items/Fish/Solaris/FishParts/CorpusFishParralelBiodeItem",
|
|
||||||
"ItemCount": 7,
|
|
||||||
"ProductCategory": "MiscItems"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ItemType": "/Lotus/Types/Items/Gems/Solaris/SolarisCommonGemBCutItem",
|
|
||||||
"ItemCount": 12,
|
|
||||||
"ProductCategory": "MiscItems"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"RegularPrice": [94600, 94600],
|
|
||||||
"Bin": "BIN_1",
|
|
||||||
"QuantityMultiplier": 1,
|
|
||||||
"Expiry": {
|
|
||||||
"$date": {
|
|
||||||
"$numberLong": "9999999000000"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"PurchaseQuantityLimit": 1,
|
|
||||||
"AllowMultipurchase": true,
|
|
||||||
"LocTagRandSeed": 4222095721,
|
|
||||||
"Id": {
|
|
||||||
"$oid": "670f63827be40254f95e739d"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StoreItem": "/Lotus/Types/StoreItems/Packages/DebtTokenBundles/DebtTokenBundleCommonJ",
|
|
||||||
"ItemPrices": [
|
|
||||||
{
|
|
||||||
"ItemType": "/Lotus/Types/Items/MiscItems/Nanospores",
|
|
||||||
"ItemCount": 14830,
|
|
||||||
"ProductCategory": "MiscItems"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"RegularPrice": [25600, 25600],
|
|
||||||
"Bin": "BIN_0",
|
|
||||||
"QuantityMultiplier": 1,
|
|
||||||
"Expiry": {
|
|
||||||
"$date": {
|
|
||||||
"$numberLong": "9999999000000"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"PurchaseQuantityLimit": 1,
|
|
||||||
"AllowMultipurchase": true,
|
|
||||||
"LocTagRandSeed": 2694388669,
|
|
||||||
"Id": {
|
|
||||||
"$oid": "67112582cc115756985e73a6"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"PropertyTextHash": "A39621049CA3CA13761028CD21C239EF",
|
|
||||||
"RandomSeedType": "VRST_FLAVOUR_TEXT",
|
|
||||||
"Expiry": {
|
|
||||||
"$date": {
|
|
||||||
"$numberLong": "9999999000000"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,459 @@
|
|||||||
|
{
|
||||||
|
"VendorInfo": {
|
||||||
|
"_id": {
|
||||||
|
"$oid": "67dadc30e4b6e0e5979c8d56"
|
||||||
|
},
|
||||||
|
"TypeName": "/Lotus/Types/Game/VendorManifests/TheHex/Temple1999VendorManifest",
|
||||||
|
"ItemManifest": [
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Recipes/WarframeRecipes/TempleBlueprint",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 195,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c18c"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Recipes/WarframeRecipes/TempleSystemsBlueprint",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 65,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c18d"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Recipes/WarframeRecipes/TempleChassisBlueprint",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 65,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c18e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Recipes/WarframeRecipes/TempleHelmetBlueprint",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 65,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c18f"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Recipes/Weapons/1999EntHybridPistolBlueprint",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 120,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c190"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Recipes/Weapons/WeaponParts/1999EntHybridPistolBarrelBlueprint",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 60,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c191"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Recipes/Weapons/WeaponParts/1999EntHybridPistolReceiverBlueprint",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 60,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c192"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Recipes/Weapons/WeaponParts/1999EntHybridPistolStockBlueprint",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 60,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c193"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumDrumCoreKitA",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 30,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c194"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumDrumCymbalA",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 30,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c195"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumDrumFloorTomA",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 30,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c196"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumDrumSnareA",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 30,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c197"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumEquipmentCaseA",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 30,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c198"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumEquipmentCaseB",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 30,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c199"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumEquipmentCaseC",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 30,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c19a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumEquipmentCaseD",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 30,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c19b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumEquipmentCaseE",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 30,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c19c"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumEquipmentCaseF",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 30,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c19d"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumSynthKeyboardA",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 30,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c19e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Items/PhotoBooth/Vania/PhotoboothTileVaniaObjTempleDefense",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 100,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 1,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowMultipurchase": false,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c19f"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StoreItem": "/Lotus/StoreItems/Types/Items/MiscItems/Kuva",
|
||||||
|
"ItemPrices": [
|
||||||
|
{
|
||||||
|
"ItemCount": 110,
|
||||||
|
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
|
||||||
|
"ProductCategory": "MiscItems"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Bin": "BIN_0",
|
||||||
|
"QuantityMultiplier": 6000,
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PurchaseQuantityLimit": 7,
|
||||||
|
"AllowMultipurchase": true,
|
||||||
|
"Id": {
|
||||||
|
"$oid": "67dadc30641da66dc5c1c1a5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"PropertyTextHash": "20B13D9EB78FEC80EA32D0687F5BA1AE",
|
||||||
|
"RequiredGoalTag": "",
|
||||||
|
"Expiry": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "2051240400000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -401,6 +401,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="card mb-3" style="height: 400px;">
|
||||||
|
<h5 class="card-header" data-loc="inventory_evolutionProgress"></h5>
|
||||||
|
<div class="card-body overflow-auto">
|
||||||
|
<form class="input-group mb-3" onsubmit="doAcquireEvolution();return false;">
|
||||||
|
<input class="form-control" id="acquire-type-EvolutionProgress" list="datalist-EvolutionProgress" />
|
||||||
|
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||||
|
</form>
|
||||||
|
<table class="table table-hover w-100">
|
||||||
|
<tbody id="EvolutionProgress-list"></tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="card mb-3">
|
<div class="card mb-3">
|
||||||
<h5 class="card-header" data-loc="general_bulkActions"></h5>
|
<h5 class="card-header" data-loc="general_bulkActions"></h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -411,6 +427,7 @@
|
|||||||
<button class="btn btn-primary" onclick="addMissingEquipment(['SpaceGuns', 'SpaceMelee']);" data-loc="inventory_bulkAddSpaceWeapons"></button>
|
<button class="btn btn-primary" onclick="addMissingEquipment(['SpaceGuns', 'SpaceMelee']);" data-loc="inventory_bulkAddSpaceWeapons"></button>
|
||||||
<button class="btn btn-primary" onclick="addMissingEquipment(['Sentinels']);" data-loc="inventory_bulkAddSentinels"></button>
|
<button class="btn btn-primary" onclick="addMissingEquipment(['Sentinels']);" data-loc="inventory_bulkAddSentinels"></button>
|
||||||
<button class="btn btn-primary" onclick="addMissingEquipment(['SentinelWeapons']);" data-loc="inventory_bulkAddSentinelWeapons"></button>
|
<button class="btn btn-primary" onclick="addMissingEquipment(['SentinelWeapons']);" data-loc="inventory_bulkAddSentinelWeapons"></button>
|
||||||
|
<button class="btn btn-primary" onclick="addMissingEvolutionProgress();" data-loc="inventory_bulkAddEvolutionProgress"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-2 d-flex flex-wrap gap-2">
|
<div class="mb-2 d-flex flex-wrap gap-2">
|
||||||
<button class="btn btn-success" onclick="maxRankAllEquipment(['Suits']);" data-loc="inventory_bulkRankUpSuits"></button>
|
<button class="btn btn-success" onclick="maxRankAllEquipment(['Suits']);" data-loc="inventory_bulkRankUpSuits"></button>
|
||||||
@ -419,6 +436,7 @@
|
|||||||
<button class="btn btn-success" onclick="maxRankAllEquipment(['SpaceGuns', 'SpaceMelee']);" data-loc="inventory_bulkRankUpSpaceWeapons"></button>
|
<button class="btn btn-success" onclick="maxRankAllEquipment(['SpaceGuns', 'SpaceMelee']);" data-loc="inventory_bulkRankUpSpaceWeapons"></button>
|
||||||
<button class="btn btn-success" onclick="maxRankAllEquipment(['Sentinels']);" data-loc="inventory_bulkRankUpSentinels"></button>
|
<button class="btn btn-success" onclick="maxRankAllEquipment(['Sentinels']);" data-loc="inventory_bulkRankUpSentinels"></button>
|
||||||
<button class="btn btn-success" onclick="maxRankAllEquipment(['SentinelWeapons']);" data-loc="inventory_bulkRankUpSentinelWeapons"></button>
|
<button class="btn btn-success" onclick="maxRankAllEquipment(['SentinelWeapons']);" data-loc="inventory_bulkRankUpSentinelWeapons"></button>
|
||||||
|
<button class="btn btn-success" onclick="maxRankAllEvolutions();" data-loc="inventory_bulkRankUpEvolutionProgress"></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -733,6 +751,7 @@
|
|||||||
</datalist>
|
</datalist>
|
||||||
<datalist id="datalist-archonCrystalUpgrades"></datalist>
|
<datalist id="datalist-archonCrystalUpgrades"></datalist>
|
||||||
<datalist id="datalist-OperatorAmps"></datalist>
|
<datalist id="datalist-OperatorAmps"></datalist>
|
||||||
|
<datalist id="datalist-EvolutionProgress"></datalist>
|
||||||
<datalist id="datalist-ModularParts"></datalist>
|
<datalist id="datalist-ModularParts"></datalist>
|
||||||
<datalist id="datalist-ModularParts-HB_DECK"></datalist>
|
<datalist id="datalist-ModularParts-HB_DECK"></datalist>
|
||||||
<datalist id="datalist-ModularParts-HB_ENGINE"></datalist>
|
<datalist id="datalist-ModularParts-HB_ENGINE"></datalist>
|
||||||
|
@ -78,19 +78,23 @@ function logout() {
|
|||||||
function renameAccount() {
|
function renameAccount() {
|
||||||
const newname = window.prompt(loc("code_changeNameConfirm"));
|
const newname = window.prompt(loc("code_changeNameConfirm"));
|
||||||
if (newname) {
|
if (newname) {
|
||||||
|
revalidateAuthz(() => {
|
||||||
fetch("/custom/renameAccount?" + window.authz + "&newname=" + newname).then(() => {
|
fetch("/custom/renameAccount?" + window.authz + "&newname=" + newname).then(() => {
|
||||||
$(".displayname").text(newname);
|
$(".displayname").text(newname);
|
||||||
updateLocElements();
|
updateLocElements();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteAccount() {
|
function deleteAccount() {
|
||||||
if (window.confirm(loc("code_deleteAccountConfirm"))) {
|
if (window.confirm(loc("code_deleteAccountConfirm"))) {
|
||||||
|
revalidateAuthz(() => {
|
||||||
fetch("/custom/deleteAccount?" + window.authz).then(() => {
|
fetch("/custom/deleteAccount?" + window.authz).then(() => {
|
||||||
logout();
|
logout();
|
||||||
single.loadRoute("/webui/"); // Show login screen
|
single.loadRoute("/webui/"); // Show login screen
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,6 +187,16 @@ const webUiModularWeapons = [
|
|||||||
"/Lotus/Types/Friendly/Pets/CreaturePets/MedjayPredatorKubrowPetPowerSuit"
|
"/Lotus/Types/Friendly/Pets/CreaturePets/MedjayPredatorKubrowPetPowerSuit"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const permanentEvolutionWeapons = new Set([
|
||||||
|
"/Lotus/Weapons/Tenno/Zariman/LongGuns/PumpShotgun/ZarimanPumpShotgun",
|
||||||
|
"/Lotus/Weapons/Tenno/Zariman/LongGuns/SemiAutoRifle/ZarimanSemiAutoRifle",
|
||||||
|
"/Lotus/Weapons/Tenno/Zariman/Melee/Dagger/ZarimanDaggerWeapon",
|
||||||
|
"/Lotus/Weapons/Tenno/Zariman/Melee/Tonfas/ZarimanTonfaWeapon",
|
||||||
|
"/Lotus/Weapons/Tenno/Zariman/Pistols/HeavyPistol/ZarimanHeavyPistol",
|
||||||
|
"/Lotus/Weapons/Thanotech/EntFistIncarnon/EntFistIncarnon",
|
||||||
|
"/Lotus/Weapons/Thanotech/EntratiWristGun/EntratiWristGunWeapon"
|
||||||
|
]);
|
||||||
|
|
||||||
let uniqueLevelCaps = {};
|
let uniqueLevelCaps = {};
|
||||||
function fetchItemList() {
|
function fetchItemList() {
|
||||||
window.itemListPromise = new Promise(resolve => {
|
window.itemListPromise = new Promise(resolve => {
|
||||||
@ -563,6 +577,82 @@ function updateInventory() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.getElementById("EvolutionProgress-list").innerHTML = "";
|
||||||
|
data.EvolutionProgress?.forEach(item => {
|
||||||
|
const datalist = document.getElementById("datalist-EvolutionProgress");
|
||||||
|
const optionToRemove = datalist.querySelector(`option[data-key="${item.ItemType}"]`);
|
||||||
|
if (optionToRemove) {
|
||||||
|
datalist.removeChild(optionToRemove);
|
||||||
|
}
|
||||||
|
const tr = document.createElement("tr");
|
||||||
|
tr.setAttribute("data-item-type", item.ItemType);
|
||||||
|
{
|
||||||
|
const td = document.createElement("td");
|
||||||
|
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
|
||||||
|
if (item.Rank != null) {
|
||||||
|
td.textContent += " | " + loc("code_rank") + ": [" + item.Rank + "/5]";
|
||||||
|
}
|
||||||
|
tr.appendChild(td);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const td = document.createElement("td");
|
||||||
|
td.classList = "text-end text-nowrap";
|
||||||
|
if (item.Rank < 5) {
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.href = "#";
|
||||||
|
a.onclick = function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
setEvolutionProgress([{ ItemType: item.ItemType, Rank: 5 }]);
|
||||||
|
};
|
||||||
|
a.title = loc("code_maxRank");
|
||||||
|
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M214.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-160 160c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 141.2V448c0 17.7 14.3 32 32 32s32-14.3 32-32V141.2L329.4 246.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z"/></svg>`;
|
||||||
|
|
||||||
|
td.appendChild(a);
|
||||||
|
}
|
||||||
|
if ((permanentEvolutionWeapons.has(item.ItemType) && item.Rank > 0) || item.Rank > 1) {
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.href = "#";
|
||||||
|
a.onclick = function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
setEvolutionProgress([{ ItemType: item.ItemType, Rank: item.Rank - 1 }]);
|
||||||
|
};
|
||||||
|
a.title = loc("code_rankDown");
|
||||||
|
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z"/></svg>`;
|
||||||
|
|
||||||
|
td.appendChild(a);
|
||||||
|
}
|
||||||
|
if (item.Rank < 5) {
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.href = "#";
|
||||||
|
a.onclick = function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
setEvolutionProgress([{ ItemType: item.ItemType, Rank: item.Rank + 1 }]);
|
||||||
|
};
|
||||||
|
a.title = loc("code_rankUp");
|
||||||
|
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M233.4 105.4c12.5-12.5 32.8-12.5 45.3 0l192 192c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L256 173.3 86.6 342.6c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3l192-192z"/></svg>`;
|
||||||
|
|
||||||
|
td.appendChild(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.appendChild(td);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("EvolutionProgress-list").appendChild(tr);
|
||||||
|
});
|
||||||
|
|
||||||
|
const datalistEvolutionProgress = document.querySelectorAll("#datalist-EvolutionProgress option");
|
||||||
|
const formEvolutionProgress = document.querySelector('form[onsubmit*="doAcquireEvolution()"]');
|
||||||
|
const giveAllQEvolutionProgress = document.querySelector(
|
||||||
|
'button[onclick*="addMissingEvolutionProgress()"]'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (datalistEvolutionProgress.length === 0) {
|
||||||
|
formEvolutionProgress.classList.add("disabled");
|
||||||
|
formEvolutionProgress.querySelector("input").disabled = true;
|
||||||
|
formEvolutionProgress.querySelector("button").disabled = true;
|
||||||
|
giveAllQEvolutionProgress.disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Populate quests route
|
// Populate quests route
|
||||||
document.getElementById("QuestKeys-list").innerHTML = "";
|
document.getElementById("QuestKeys-list").innerHTML = "";
|
||||||
data.QuestKeys.forEach(item => {
|
data.QuestKeys.forEach(item => {
|
||||||
@ -674,18 +764,18 @@ function updateInventory() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const datalistQuestKeys = document.querySelectorAll("#datalist-QuestKeys option");
|
const datalistQuestKeys = document.querySelectorAll("#datalist-QuestKeys option");
|
||||||
const form = document.querySelector("form[onsubmit*=\"doAcquireEquipment('QuestKeys')\"]");
|
const formQuestKeys = document.querySelector("form[onsubmit*=\"doAcquireEquipment('QuestKeys')\"]");
|
||||||
const giveAllQuestButton = document.querySelector("button[onclick*=\"doBulkQuestUpdate('giveAll')\"]");
|
const giveAllQuestButton = document.querySelector("button[onclick*=\"doBulkQuestUpdate('giveAll')\"]");
|
||||||
|
|
||||||
if (datalistQuestKeys.length === 0) {
|
if (datalistQuestKeys.length === 0) {
|
||||||
form.classList.add("disabled");
|
formQuestKeys.classList.add("disabled");
|
||||||
form.querySelector("input").disabled = true;
|
formQuestKeys.querySelector("input").disabled = true;
|
||||||
form.querySelector("button").disabled = true;
|
formQuestKeys.querySelector("button").disabled = true;
|
||||||
giveAllQuestButton.disabled = true;
|
giveAllQuestButton.disabled = true;
|
||||||
} else {
|
} else {
|
||||||
form.classList.remove("disabled");
|
formQuestKeys.classList.remove("disabled");
|
||||||
form.querySelector("input").disabled = false;
|
formQuestKeys.querySelector("input").disabled = false;
|
||||||
form.querySelector("button").disabled = false;
|
formQuestKeys.querySelector("button").disabled = false;
|
||||||
giveAllQuestButton.disabled = false;
|
giveAllQuestButton.disabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1080,6 +1170,16 @@ function doAcquireModularEquipment(category, WeaponType) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function doAcquireEvolution() {
|
||||||
|
const uniqueName = getKey(document.getElementById("acquire-type-EvolutionProgress"));
|
||||||
|
if (!uniqueName) {
|
||||||
|
$("#acquire-type-EvolutionProgress").addClass("is-invalid").focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setEvolutionProgress([{ ItemType: uniqueName, Rank: permanentEvolutionWeapons.has(uniqueName) ? 0 : 1 }]);
|
||||||
|
}
|
||||||
|
|
||||||
$("input[list]").on("input", function () {
|
$("input[list]").on("input", function () {
|
||||||
$(this).removeClass("is-invalid");
|
$(this).removeClass("is-invalid");
|
||||||
});
|
});
|
||||||
@ -1117,6 +1217,40 @@ function addMissingEquipment(categories) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addMissingEvolutionProgress() {
|
||||||
|
const requests = [];
|
||||||
|
document.querySelectorAll("#datalist-EvolutionProgress option").forEach(elm => {
|
||||||
|
const uniqueName = elm.getAttribute("data-key");
|
||||||
|
requests.push({ ItemType: uniqueName, Rank: permanentEvolutionWeapons.has(uniqueName) ? 0 : 1 });
|
||||||
|
});
|
||||||
|
if (requests.length != 0 && window.confirm(loc("code_addItemsConfirm").split("|COUNT|").join(requests.length))) {
|
||||||
|
setEvolutionProgress(requests);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function maxRankAllEvolutions() {
|
||||||
|
const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
|
||||||
|
|
||||||
|
req.done(data => {
|
||||||
|
const requests = [];
|
||||||
|
|
||||||
|
data.EvolutionProgress.forEach(item => {
|
||||||
|
if (item.Rank < 5) {
|
||||||
|
requests.push({
|
||||||
|
ItemType: item.ItemType,
|
||||||
|
Rank: 5
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Object.keys(requests).length > 0) {
|
||||||
|
return setEvolutionProgress(requests);
|
||||||
|
}
|
||||||
|
|
||||||
|
toast(loc("code_noEquipmentToRankUp"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function maxRankAllEquipment(categories) {
|
function maxRankAllEquipment(categories) {
|
||||||
const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
|
const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
|
||||||
|
|
||||||
@ -1304,6 +1438,19 @@ function maturePet(oid, revert) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setEvolutionProgress(requests) {
|
||||||
|
revalidateAuthz(() => {
|
||||||
|
const req = $.post({
|
||||||
|
url: "/custom/setEvolutionProgress?" + window.authz,
|
||||||
|
contentType: "application/json",
|
||||||
|
data: JSON.stringify(requests)
|
||||||
|
});
|
||||||
|
req.done(() => {
|
||||||
|
updateInventory();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function doAcquireMiscItems() {
|
function doAcquireMiscItems() {
|
||||||
const uniqueName = getKey(document.getElementById("miscitem-type"));
|
const uniqueName = getKey(document.getElementById("miscitem-type"));
|
||||||
if (!uniqueName) {
|
if (!uniqueName) {
|
||||||
|
@ -34,6 +34,8 @@ dict = {
|
|||||||
code_rerollsNumber: `Anzahl der Umrollversuche`,
|
code_rerollsNumber: `Anzahl der Umrollversuche`,
|
||||||
code_viewStats: `Statistiken anzeigen`,
|
code_viewStats: `Statistiken anzeigen`,
|
||||||
code_rank: `Rang`,
|
code_rank: `Rang`,
|
||||||
|
code_rankUp: `[UNTRANSLATED] Rank up`,
|
||||||
|
code_rankDown: `[UNTRANSLATED] Rank down`,
|
||||||
code_count: `Anzahl`,
|
code_count: `Anzahl`,
|
||||||
code_focusAllUnlocked: `Alle Fokus-Schulen sind bereits freigeschaltet.`,
|
code_focusAllUnlocked: `Alle Fokus-Schulen sind bereits freigeschaltet.`,
|
||||||
code_focusUnlocked: `|COUNT| neue Fokus-Schulen freigeschaltet! Ein Inventar-Update wird benötigt, damit die Änderungen im Spiel sichtbar werden. Die Sternenkarte zu besuchen, sollte der einfachste Weg sein, dies auszulösen.`,
|
code_focusUnlocked: `|COUNT| neue Fokus-Schulen freigeschaltet! Ein Inventar-Update wird benötigt, damit die Änderungen im Spiel sichtbar werden. Die Sternenkarte zu besuchen, sollte der einfachste Weg sein, dies auszulösen.`,
|
||||||
@ -84,18 +86,21 @@ dict = {
|
|||||||
inventory_hoverboards: `K-Drives`,
|
inventory_hoverboards: `K-Drives`,
|
||||||
inventory_moaPets: `Moa`,
|
inventory_moaPets: `Moa`,
|
||||||
inventory_kubrowPets: `Bestien`,
|
inventory_kubrowPets: `Bestien`,
|
||||||
|
inventory_evolutionProgress: `[UNTRANSLATED] Incarnon Evolution Progress`,
|
||||||
inventory_bulkAddSuits: `Fehlende Warframes hinzufügen`,
|
inventory_bulkAddSuits: `Fehlende Warframes hinzufügen`,
|
||||||
inventory_bulkAddWeapons: `Fehlende Waffen hinzufügen`,
|
inventory_bulkAddWeapons: `Fehlende Waffen hinzufügen`,
|
||||||
inventory_bulkAddSpaceSuits: `Fehlende Archwings hinzufügen`,
|
inventory_bulkAddSpaceSuits: `Fehlende Archwings hinzufügen`,
|
||||||
inventory_bulkAddSpaceWeapons: `Fehlende Archwing-Waffen hinzufügen`,
|
inventory_bulkAddSpaceWeapons: `Fehlende Archwing-Waffen hinzufügen`,
|
||||||
inventory_bulkAddSentinels: `Fehlende Wächter hinzufügen`,
|
inventory_bulkAddSentinels: `Fehlende Wächter hinzufügen`,
|
||||||
inventory_bulkAddSentinelWeapons: `Fehlende Wächter-Waffen hinzufügen`,
|
inventory_bulkAddSentinelWeapons: `Fehlende Wächter-Waffen hinzufügen`,
|
||||||
|
inventory_bulkAddEvolutionProgress: `[UNTRANSLATED] Add Missing Incarnon Evolution Progress`,
|
||||||
inventory_bulkRankUpSuits: `Alle Warframes auf Max. Rang`,
|
inventory_bulkRankUpSuits: `Alle Warframes auf Max. Rang`,
|
||||||
inventory_bulkRankUpWeapons: `Alle Waffen auf Max. Rang`,
|
inventory_bulkRankUpWeapons: `Alle Waffen auf Max. Rang`,
|
||||||
inventory_bulkRankUpSpaceSuits: `Alle Archwings auf Max. Rang`,
|
inventory_bulkRankUpSpaceSuits: `Alle Archwings auf Max. Rang`,
|
||||||
inventory_bulkRankUpSpaceWeapons: `Alle Archwing-Waffen auf Max. Rang`,
|
inventory_bulkRankUpSpaceWeapons: `Alle Archwing-Waffen auf Max. Rang`,
|
||||||
inventory_bulkRankUpSentinels: `Alle Wächter auf Max. Rang`,
|
inventory_bulkRankUpSentinels: `Alle Wächter auf Max. Rang`,
|
||||||
inventory_bulkRankUpSentinelWeapons: `Alle Wächter-Waffen auf Max. Rang`,
|
inventory_bulkRankUpSentinelWeapons: `Alle Wächter-Waffen auf Max. Rang`,
|
||||||
|
inventory_bulkRankUpEvolutionProgress: `[UNTRANSLATED] Max Rank All Incarnon Evolution Progress`,
|
||||||
|
|
||||||
quests_list: `Quests`,
|
quests_list: `Quests`,
|
||||||
quests_completeAll: `Alle Quests abschließen`,
|
quests_completeAll: `Alle Quests abschließen`,
|
||||||
|
@ -33,6 +33,8 @@ dict = {
|
|||||||
code_rerollsNumber: `Number of rerolls`,
|
code_rerollsNumber: `Number of rerolls`,
|
||||||
code_viewStats: `View Stats`,
|
code_viewStats: `View Stats`,
|
||||||
code_rank: `Rank`,
|
code_rank: `Rank`,
|
||||||
|
code_rankUp: `Rank up`,
|
||||||
|
code_rankDown: `Rank down`,
|
||||||
code_count: `Count`,
|
code_count: `Count`,
|
||||||
code_focusAllUnlocked: `All focus schools are already unlocked.`,
|
code_focusAllUnlocked: `All focus schools are already unlocked.`,
|
||||||
code_focusUnlocked: `Unlocked |COUNT| new focus schools! An inventory update will be needed for the changes to be reflected in-game. Visiting the navigation should be the easiest way to trigger that.`,
|
code_focusUnlocked: `Unlocked |COUNT| new focus schools! An inventory update will be needed for the changes to be reflected in-game. Visiting the navigation should be the easiest way to trigger that.`,
|
||||||
@ -83,18 +85,21 @@ dict = {
|
|||||||
inventory_hoverboards: `K-Drives`,
|
inventory_hoverboards: `K-Drives`,
|
||||||
inventory_moaPets: `Moa`,
|
inventory_moaPets: `Moa`,
|
||||||
inventory_kubrowPets: `Beasts`,
|
inventory_kubrowPets: `Beasts`,
|
||||||
|
inventory_evolutionProgress: `Incarnon Evolution Progress`,
|
||||||
inventory_bulkAddSuits: `Add Missing Warframes`,
|
inventory_bulkAddSuits: `Add Missing Warframes`,
|
||||||
inventory_bulkAddWeapons: `Add Missing Weapons`,
|
inventory_bulkAddWeapons: `Add Missing Weapons`,
|
||||||
inventory_bulkAddSpaceSuits: `Add Missing Archwings`,
|
inventory_bulkAddSpaceSuits: `Add Missing Archwings`,
|
||||||
inventory_bulkAddSpaceWeapons: `Add Missing Archwing Weapons`,
|
inventory_bulkAddSpaceWeapons: `Add Missing Archwing Weapons`,
|
||||||
inventory_bulkAddSentinels: `Add Missing Sentinels`,
|
inventory_bulkAddSentinels: `Add Missing Sentinels`,
|
||||||
inventory_bulkAddSentinelWeapons: `Add Missing Sentinel Weapons`,
|
inventory_bulkAddSentinelWeapons: `Add Missing Sentinel Weapons`,
|
||||||
|
inventory_bulkAddEvolutionProgress: `Add Missing Incarnon Evolution Progress`,
|
||||||
inventory_bulkRankUpSuits: `Max Rank All Warframes`,
|
inventory_bulkRankUpSuits: `Max Rank All Warframes`,
|
||||||
inventory_bulkRankUpWeapons: `Max Rank All Weapons`,
|
inventory_bulkRankUpWeapons: `Max Rank All Weapons`,
|
||||||
inventory_bulkRankUpSpaceSuits: `Max Rank All Archwings`,
|
inventory_bulkRankUpSpaceSuits: `Max Rank All Archwings`,
|
||||||
inventory_bulkRankUpSpaceWeapons: `Max Rank All Archwing Weapons`,
|
inventory_bulkRankUpSpaceWeapons: `Max Rank All Archwing Weapons`,
|
||||||
inventory_bulkRankUpSentinels: `Max Rank All Sentinels`,
|
inventory_bulkRankUpSentinels: `Max Rank All Sentinels`,
|
||||||
inventory_bulkRankUpSentinelWeapons: `Max Rank All Sentinel Weapons`,
|
inventory_bulkRankUpSentinelWeapons: `Max Rank All Sentinel Weapons`,
|
||||||
|
inventory_bulkRankUpEvolutionProgress: `Max Rank All Incarnon Evolution Progress`,
|
||||||
|
|
||||||
quests_list: `Quests`,
|
quests_list: `Quests`,
|
||||||
quests_completeAll: `Complete All Quests`,
|
quests_completeAll: `Complete All Quests`,
|
||||||
|
@ -34,6 +34,8 @@ dict = {
|
|||||||
code_rerollsNumber: `Cantidad de reintentos`,
|
code_rerollsNumber: `Cantidad de reintentos`,
|
||||||
code_viewStats: `Ver estadísticas`,
|
code_viewStats: `Ver estadísticas`,
|
||||||
code_rank: `Rango`,
|
code_rank: `Rango`,
|
||||||
|
code_rankUp: `[UNTRANSLATED] Rank up`,
|
||||||
|
code_rankDown: `[UNTRANSLATED] Rank down`,
|
||||||
code_count: `Cantidad`,
|
code_count: `Cantidad`,
|
||||||
code_focusAllUnlocked: `Todas las escuelas de enfoque ya están desbloqueadas.`,
|
code_focusAllUnlocked: `Todas las escuelas de enfoque ya están desbloqueadas.`,
|
||||||
code_focusUnlocked: `¡Desbloqueadas |COUNT| nuevas escuelas de enfoque! Se necesita una actualización del inventario para reflejar los cambios en el juego. Visitar la navegación debería ser la forma más sencilla de activarlo.`,
|
code_focusUnlocked: `¡Desbloqueadas |COUNT| nuevas escuelas de enfoque! Se necesita una actualización del inventario para reflejar los cambios en el juego. Visitar la navegación debería ser la forma más sencilla de activarlo.`,
|
||||||
@ -84,18 +86,21 @@ dict = {
|
|||||||
inventory_hoverboards: `K-Drives`,
|
inventory_hoverboards: `K-Drives`,
|
||||||
inventory_moaPets: `Moa`,
|
inventory_moaPets: `Moa`,
|
||||||
inventory_kubrowPets: `Bestias`,
|
inventory_kubrowPets: `Bestias`,
|
||||||
|
inventory_evolutionProgress: `[UNTRANSLATED] Incarnon Evolution Progress`,
|
||||||
inventory_bulkAddSuits: `Agregar Warframes faltantes`,
|
inventory_bulkAddSuits: `Agregar Warframes faltantes`,
|
||||||
inventory_bulkAddWeapons: `Agregar armas faltantes`,
|
inventory_bulkAddWeapons: `Agregar armas faltantes`,
|
||||||
inventory_bulkAddSpaceSuits: `Agregar Archwings faltantes`,
|
inventory_bulkAddSpaceSuits: `Agregar Archwings faltantes`,
|
||||||
inventory_bulkAddSpaceWeapons: `Agregar armas Archwing faltantes`,
|
inventory_bulkAddSpaceWeapons: `Agregar armas Archwing faltantes`,
|
||||||
inventory_bulkAddSentinels: `Agregar centinelas faltantes`,
|
inventory_bulkAddSentinels: `Agregar centinelas faltantes`,
|
||||||
inventory_bulkAddSentinelWeapons: `Agregar armas de centinela faltantes`,
|
inventory_bulkAddSentinelWeapons: `Agregar armas de centinela faltantes`,
|
||||||
|
inventory_bulkAddEvolutionProgress: `[UNTRANSLATED] Add Missing Incarnon Evolution Progress`,
|
||||||
inventory_bulkRankUpSuits: `Maximizar rango de todos los Warframes`,
|
inventory_bulkRankUpSuits: `Maximizar rango de todos los Warframes`,
|
||||||
inventory_bulkRankUpWeapons: `Maximizar rango de todas las armas`,
|
inventory_bulkRankUpWeapons: `Maximizar rango de todas las armas`,
|
||||||
inventory_bulkRankUpSpaceSuits: `Maximizar rango de todos los Archwings`,
|
inventory_bulkRankUpSpaceSuits: `Maximizar rango de todos los Archwings`,
|
||||||
inventory_bulkRankUpSpaceWeapons: `Maximizar rango de todas las armas Archwing`,
|
inventory_bulkRankUpSpaceWeapons: `Maximizar rango de todas las armas Archwing`,
|
||||||
inventory_bulkRankUpSentinels: `Maximizar rango de todos los centinelas`,
|
inventory_bulkRankUpSentinels: `Maximizar rango de todos los centinelas`,
|
||||||
inventory_bulkRankUpSentinelWeapons: `Maximizar rango de todas las armas de centinela`,
|
inventory_bulkRankUpSentinelWeapons: `Maximizar rango de todas las armas de centinela`,
|
||||||
|
inventory_bulkRankUpEvolutionProgress: `[UNTRANSLATED] Max Rank All Incarnon Evolution Progress`,
|
||||||
|
|
||||||
quests_list: `Misiones`,
|
quests_list: `Misiones`,
|
||||||
quests_completeAll: `Completar todas las misiones`,
|
quests_completeAll: `Completar todas las misiones`,
|
||||||
|
@ -34,6 +34,8 @@ dict = {
|
|||||||
code_rerollsNumber: `Nombre de rerolls`,
|
code_rerollsNumber: `Nombre de rerolls`,
|
||||||
code_viewStats: `Voir les stats`,
|
code_viewStats: `Voir les stats`,
|
||||||
code_rank: `Rang`,
|
code_rank: `Rang`,
|
||||||
|
code_rankUp: `[UNTRANSLATED] Rank up`,
|
||||||
|
code_rankDown: `[UNTRANSLATED] Rank down`,
|
||||||
code_count: `Quantité`,
|
code_count: `Quantité`,
|
||||||
code_focusAllUnlocked: `Les écoles de Focus sont déjà déverrouillées.`,
|
code_focusAllUnlocked: `Les écoles de Focus sont déjà déverrouillées.`,
|
||||||
code_focusUnlocked: `|COUNT| écoles de Focus déverrouillées ! Synchronisation de l'inventaire nécessaire.`,
|
code_focusUnlocked: `|COUNT| écoles de Focus déverrouillées ! Synchronisation de l'inventaire nécessaire.`,
|
||||||
@ -84,18 +86,21 @@ dict = {
|
|||||||
inventory_hoverboards: `K-Drives`,
|
inventory_hoverboards: `K-Drives`,
|
||||||
inventory_moaPets: `Moa`,
|
inventory_moaPets: `Moa`,
|
||||||
inventory_kubrowPets: `Bêtes`,
|
inventory_kubrowPets: `Bêtes`,
|
||||||
|
inventory_evolutionProgress: `[UNTRANSLATED] Incarnon Evolution Progress`,
|
||||||
inventory_bulkAddSuits: `Ajouter les Warframes manquantes`,
|
inventory_bulkAddSuits: `Ajouter les Warframes manquantes`,
|
||||||
inventory_bulkAddWeapons: `Ajouter les armes manquantes`,
|
inventory_bulkAddWeapons: `Ajouter les armes manquantes`,
|
||||||
inventory_bulkAddSpaceSuits: `Ajouter les Archwings manquants`,
|
inventory_bulkAddSpaceSuits: `Ajouter les Archwings manquants`,
|
||||||
inventory_bulkAddSpaceWeapons: `Ajouter les armes d'Archwing manquantes`,
|
inventory_bulkAddSpaceWeapons: `Ajouter les armes d'Archwing manquantes`,
|
||||||
inventory_bulkAddSentinels: `Ajouter les Sentinelles manquantes`,
|
inventory_bulkAddSentinels: `Ajouter les Sentinelles manquantes`,
|
||||||
inventory_bulkAddSentinelWeapons: `Ajouter les armes de Sentinelles manquantes`,
|
inventory_bulkAddSentinelWeapons: `Ajouter les armes de Sentinelles manquantes`,
|
||||||
|
inventory_bulkAddEvolutionProgress: `[UNTRANSLATED] Add Missing Incarnon Evolution Progress`,
|
||||||
inventory_bulkRankUpSuits: `Toutes les Warframes rang max`,
|
inventory_bulkRankUpSuits: `Toutes les Warframes rang max`,
|
||||||
inventory_bulkRankUpWeapons: `Toutes les armes rang max`,
|
inventory_bulkRankUpWeapons: `Toutes les armes rang max`,
|
||||||
inventory_bulkRankUpSpaceSuits: `Tous les Archwings rang max`,
|
inventory_bulkRankUpSpaceSuits: `Tous les Archwings rang max`,
|
||||||
inventory_bulkRankUpSpaceWeapons: `Toutes les armes d'Archwing rang max`,
|
inventory_bulkRankUpSpaceWeapons: `Toutes les armes d'Archwing rang max`,
|
||||||
inventory_bulkRankUpSentinels: `Toutes les Sentinelles rang max`,
|
inventory_bulkRankUpSentinels: `Toutes les Sentinelles rang max`,
|
||||||
inventory_bulkRankUpSentinelWeapons: `Toutes les armes de Sentinelles rang max`,
|
inventory_bulkRankUpSentinelWeapons: `Toutes les armes de Sentinelles rang max`,
|
||||||
|
inventory_bulkRankUpEvolutionProgress: `[UNTRANSLATED] Max Rank All Incarnon Evolution Progress`,
|
||||||
|
|
||||||
quests_list: `Quêtes`,
|
quests_list: `Quêtes`,
|
||||||
quests_completeAll: `Compléter toutes les quêtes`,
|
quests_completeAll: `Compléter toutes les quêtes`,
|
||||||
|
@ -34,6 +34,8 @@ dict = {
|
|||||||
code_rerollsNumber: `Количество циклов`,
|
code_rerollsNumber: `Количество циклов`,
|
||||||
code_viewStats: `Просмотр характеристики`,
|
code_viewStats: `Просмотр характеристики`,
|
||||||
code_rank: `Ранг`,
|
code_rank: `Ранг`,
|
||||||
|
code_rankUp: `Повысить Ранг`,
|
||||||
|
code_rankDown: `Понизить Ранг`,
|
||||||
code_count: `Количество`,
|
code_count: `Количество`,
|
||||||
code_focusAllUnlocked: `Все школы фокуса уже разблокированы.`,
|
code_focusAllUnlocked: `Все школы фокуса уже разблокированы.`,
|
||||||
code_focusUnlocked: `Разблокировано |COUNT| новых школ фокуса! Для отображения изменений в игре потребуется обновление инвентаря. Посещение навигации — самый простой способ этого добиться.`,
|
code_focusUnlocked: `Разблокировано |COUNT| новых школ фокуса! Для отображения изменений в игре потребуется обновление инвентаря. Посещение навигации — самый простой способ этого добиться.`,
|
||||||
@ -84,18 +86,21 @@ dict = {
|
|||||||
inventory_hoverboards: `К-Драйвы`,
|
inventory_hoverboards: `К-Драйвы`,
|
||||||
inventory_moaPets: `МОА`,
|
inventory_moaPets: `МОА`,
|
||||||
inventory_kubrowPets: `Звери`,
|
inventory_kubrowPets: `Звери`,
|
||||||
|
inventory_evolutionProgress: `Прогресс эволюции Инкарнонов`,
|
||||||
inventory_bulkAddSuits: `Добавить отсутствующие варфреймы`,
|
inventory_bulkAddSuits: `Добавить отсутствующие варфреймы`,
|
||||||
inventory_bulkAddWeapons: `Добавить отсутствующее оружие`,
|
inventory_bulkAddWeapons: `Добавить отсутствующее оружие`,
|
||||||
inventory_bulkAddSpaceSuits: `Добавить отсутствующие арчвинги`,
|
inventory_bulkAddSpaceSuits: `Добавить отсутствующие арчвинги`,
|
||||||
inventory_bulkAddSpaceWeapons: `Добавить отсутствующее оружие арчвингов`,
|
inventory_bulkAddSpaceWeapons: `Добавить отсутствующее оружие арчвингов`,
|
||||||
inventory_bulkAddSentinels: `Добавить отсутствующих стражей`,
|
inventory_bulkAddSentinels: `Добавить отсутствующих стражей`,
|
||||||
inventory_bulkAddSentinelWeapons: `Добавить отсутствующее оружие стражей`,
|
inventory_bulkAddSentinelWeapons: `Добавить отсутствующее оружие стражей`,
|
||||||
|
inventory_bulkAddEvolutionProgress: `Добавить отсуствующий прогресс эволюции Инкарнонов`,
|
||||||
inventory_bulkRankUpSuits: `Максимальный ранг всех варфреймов`,
|
inventory_bulkRankUpSuits: `Максимальный ранг всех варфреймов`,
|
||||||
inventory_bulkRankUpWeapons: `Максимальный ранг всего оружия`,
|
inventory_bulkRankUpWeapons: `Максимальный ранг всего оружия`,
|
||||||
inventory_bulkRankUpSpaceSuits: `Максимальный ранг всех арчвингов`,
|
inventory_bulkRankUpSpaceSuits: `Максимальный ранг всех арчвингов`,
|
||||||
inventory_bulkRankUpSpaceWeapons: `Максимальный ранг всего оружия арчвингов`,
|
inventory_bulkRankUpSpaceWeapons: `Максимальный ранг всего оружия арчвингов`,
|
||||||
inventory_bulkRankUpSentinels: `Максимальный ранг всех стражей`,
|
inventory_bulkRankUpSentinels: `Максимальный ранг всех стражей`,
|
||||||
inventory_bulkRankUpSentinelWeapons: `Максимальный ранг всего оружия стражей`,
|
inventory_bulkRankUpSentinelWeapons: `Максимальный ранг всего оружия стражей`,
|
||||||
|
inventory_bulkRankUpEvolutionProgress: `Максимальный ранг всех эволюций Инкарнонов`,
|
||||||
|
|
||||||
quests_list: `Квесты`,
|
quests_list: `Квесты`,
|
||||||
quests_completeAll: `Завершить все квесты`,
|
quests_completeAll: `Завершить все квесты`,
|
||||||
|
@ -34,6 +34,8 @@ dict = {
|
|||||||
code_rerollsNumber: `洗卡次数`,
|
code_rerollsNumber: `洗卡次数`,
|
||||||
code_viewStats: `查看属性`,
|
code_viewStats: `查看属性`,
|
||||||
code_rank: `等级`,
|
code_rank: `等级`,
|
||||||
|
code_rankUp: `[UNTRANSLATED] Rank up`,
|
||||||
|
code_rankDown: `[UNTRANSLATED] Rank down`,
|
||||||
code_count: `数量`,
|
code_count: `数量`,
|
||||||
code_focusAllUnlocked: `所有专精学派均已解锁。`,
|
code_focusAllUnlocked: `所有专精学派均已解锁。`,
|
||||||
code_focusUnlocked: `已解锁 |COUNT| 个新专精学派!需要游戏内仓库更新才能生效,您可以通过访问星图来触发仓库更新。`,
|
code_focusUnlocked: `已解锁 |COUNT| 个新专精学派!需要游戏内仓库更新才能生效,您可以通过访问星图来触发仓库更新。`,
|
||||||
@ -84,18 +86,21 @@ dict = {
|
|||||||
inventory_hoverboards: `K式悬浮板`,
|
inventory_hoverboards: `K式悬浮板`,
|
||||||
inventory_moaPets: `恐鸟`,
|
inventory_moaPets: `恐鸟`,
|
||||||
inventory_kubrowPets: `[UNTRANSLATED] Beasts`,
|
inventory_kubrowPets: `[UNTRANSLATED] Beasts`,
|
||||||
|
inventory_evolutionProgress: `[UNTRANSLATED] Incarnon Evolution Progress`,
|
||||||
inventory_bulkAddSuits: `添加缺失战甲`,
|
inventory_bulkAddSuits: `添加缺失战甲`,
|
||||||
inventory_bulkAddWeapons: `添加缺失武器`,
|
inventory_bulkAddWeapons: `添加缺失武器`,
|
||||||
inventory_bulkAddSpaceSuits: `添加缺失Archwing`,
|
inventory_bulkAddSpaceSuits: `添加缺失Archwing`,
|
||||||
inventory_bulkAddSpaceWeapons: `添加缺失Archwing武器`,
|
inventory_bulkAddSpaceWeapons: `添加缺失Archwing武器`,
|
||||||
inventory_bulkAddSentinels: `添加缺失守护`,
|
inventory_bulkAddSentinels: `添加缺失守护`,
|
||||||
inventory_bulkAddSentinelWeapons: `添加缺失守护武器`,
|
inventory_bulkAddSentinelWeapons: `添加缺失守护武器`,
|
||||||
|
inventory_bulkAddEvolutionProgress: `[UNTRANSLATED] Add Missing Incarnon Evolution Progress`,
|
||||||
inventory_bulkRankUpSuits: `所有战甲升满级`,
|
inventory_bulkRankUpSuits: `所有战甲升满级`,
|
||||||
inventory_bulkRankUpWeapons: `所有武器升满级`,
|
inventory_bulkRankUpWeapons: `所有武器升满级`,
|
||||||
inventory_bulkRankUpSpaceSuits: `所有Archwing升满级`,
|
inventory_bulkRankUpSpaceSuits: `所有Archwing升满级`,
|
||||||
inventory_bulkRankUpSpaceWeapons: `所有Archwing武器升满级`,
|
inventory_bulkRankUpSpaceWeapons: `所有Archwing武器升满级`,
|
||||||
inventory_bulkRankUpSentinels: `所有守护升满级`,
|
inventory_bulkRankUpSentinels: `所有守护升满级`,
|
||||||
inventory_bulkRankUpSentinelWeapons: `所有守护武器升满级`,
|
inventory_bulkRankUpSentinelWeapons: `所有守护武器升满级`,
|
||||||
|
inventory_bulkRankUpEvolutionProgress: `[UNTRANSLATED] Max Rank All Incarnon Evolution Progress`,
|
||||||
|
|
||||||
quests_list: `任务`,
|
quests_list: `任务`,
|
||||||
quests_completeAll: `完成所有任务`,
|
quests_completeAll: `完成所有任务`,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user