forked from OpenWF/SpaceNinjaServer
Compare commits
25 Commits
eb4698109e
...
62d7a0263b
Author | SHA1 | Date | |
---|---|---|---|
62d7a0263b | |||
3a6e4ac2e1 | |||
e234af098d | |||
4a434cea2b | |||
36f2828d37 | |||
ca3cfb5299 | |||
f242d9f873 | |||
9a034b1c8a | |||
122950034e | |||
636d3100f3 | |||
444c92f0c6 | |||
653798b987 | |||
7a88f6f486 | |||
82b203e00b | |||
271f5bd47a | |||
f61d15b496 | |||
cfd50e7402 | |||
2421a16b2c | |||
cee622d5e9 | |||
84f081312b | |||
7ca7147b78 | |||
558af66965 | |||
d7b9fb1ab5 | |||
bf12f90c88 | |||
6dd9b42f40 |
17
AGENTS.md
Normal file
17
AGENTS.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
## In General
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
Use `npm i` or `npm ci` to install all dependencies.
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
Use `npm run verify` to verify that your changes pass TypeScript's checks.
|
||||||
|
|
||||||
|
### Formatting
|
||||||
|
|
||||||
|
Use `npm run prettier` to ensure your formatting matches the expected format. Failing to do so will cause CI failure.
|
||||||
|
|
||||||
|
## WebUI Specific
|
||||||
|
|
||||||
|
The translation system is designed around additions being made to `static/webui/translations/en.js`. They are copied over for translation via `npm run update-translations`. DO NOT produce non-English strings; we want them to be translated by humans who can understand the full context.
|
@ -13,7 +13,6 @@
|
|||||||
"skipTutorial": false,
|
"skipTutorial": false,
|
||||||
"skipAllDialogue": false,
|
"skipAllDialogue": false,
|
||||||
"unlockAllScans": false,
|
"unlockAllScans": false,
|
||||||
"unlockAllMissions": false,
|
|
||||||
"infiniteCredits": false,
|
"infiniteCredits": false,
|
||||||
"infinitePlatinum": false,
|
"infinitePlatinum": false,
|
||||||
"infiniteEndo": false,
|
"infiniteEndo": false,
|
||||||
@ -42,6 +41,9 @@
|
|||||||
"noVendorPurchaseLimits": false,
|
"noVendorPurchaseLimits": false,
|
||||||
"noDeathMarks": false,
|
"noDeathMarks": false,
|
||||||
"noKimCooldowns": false,
|
"noKimCooldowns": false,
|
||||||
|
"fullyStockedVendors": false,
|
||||||
|
"baroAlwaysAvailable": false,
|
||||||
|
"baroFullyStocked": false,
|
||||||
"syndicateMissionsRepeatable": false,
|
"syndicateMissionsRepeatable": false,
|
||||||
"unlockAllProfitTakerStages": false,
|
"unlockAllProfitTakerStages": false,
|
||||||
"instantFinishRivenChallenge": false,
|
"instantFinishRivenChallenge": false,
|
||||||
@ -55,8 +57,13 @@
|
|||||||
"noDojoResearchTime": false,
|
"noDojoResearchTime": false,
|
||||||
"fastClanAscension": false,
|
"fastClanAscension": false,
|
||||||
"missionsCanGiveAllRelics": false,
|
"missionsCanGiveAllRelics": false,
|
||||||
|
"unlockAllSimarisResearchEntries": false,
|
||||||
"spoofMasteryRank": -1,
|
"spoofMasteryRank": -1,
|
||||||
"nightwaveStandingMultiplier": 1,
|
"nightwaveStandingMultiplier": 1,
|
||||||
|
"unfaithfulBugFixes": {
|
||||||
|
"ignore1999LastRegionPlayed": false,
|
||||||
|
"fixXtraCheeseTimer": false
|
||||||
|
},
|
||||||
"worldState": {
|
"worldState": {
|
||||||
"creditBoost": false,
|
"creditBoost": false,
|
||||||
"affinityBoost": false,
|
"affinityBoost": false,
|
||||||
|
71
package-lock.json
generated
71
package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/express": "^5",
|
"@types/express": "^5",
|
||||||
"@types/morgan": "^1.9.9",
|
"@types/morgan": "^1.9.9",
|
||||||
|
"@types/websocket": "^1.0.10",
|
||||||
"@types/ws": "^8.18.1",
|
"@types/ws": "^8.18.1",
|
||||||
"crc-32": "^1.2.2",
|
"crc-32": "^1.2.2",
|
||||||
"express": "^5",
|
"express": "^5",
|
||||||
@ -19,7 +20,8 @@
|
|||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
"ncp": "^2.0.0",
|
"ncp": "^2.0.0",
|
||||||
"typescript": "^5.5",
|
"typescript": "^5.5",
|
||||||
"warframe-public-export-plus": "^0.5.68",
|
"undici": "^7.10.0",
|
||||||
|
"warframe-public-export-plus": "^0.5.69",
|
||||||
"warframe-riven-info": "^0.1.2",
|
"warframe-riven-info": "^0.1.2",
|
||||||
"winston": "^3.17.0",
|
"winston": "^3.17.0",
|
||||||
"winston-daily-rotate-file": "^5.0.0",
|
"winston-daily-rotate-file": "^5.0.0",
|
||||||
@ -382,6 +384,15 @@
|
|||||||
"integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==",
|
"integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/websocket": {
|
||||||
|
"version": "1.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.10.tgz",
|
||||||
|
"integrity": "sha512-svjGZvPB7EzuYS94cI7a+qhwgGU1y89wUgjT6E2wVUfmAGIvRfT7obBvRtnhXCSsoMdlG4gBFGE7MfkIXZLoww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/whatwg-url": {
|
"node_modules/@types/whatwg-url": {
|
||||||
"version": "11.0.5",
|
"version": "11.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz",
|
||||||
@ -910,6 +921,21 @@
|
|||||||
"node": ">=16.20.1"
|
"node": ">=16.20.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/bufferutil": {
|
||||||
|
"version": "4.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.9.tgz",
|
||||||
|
"integrity": "sha512-WDtdLmJvAuNNPzByAYpRo2rF1Mmradw6gvWsQKf63476DDXmomT9zUiGypLcG4ibIM67vhAj8jJRdbmEws2Aqw==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"node-gyp-build": "^4.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.14.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bytes": {
|
"node_modules/bytes": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||||
@ -2449,6 +2475,19 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-gyp-build": {
|
||||||
|
"version": "4.8.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
|
||||||
|
"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"bin": {
|
||||||
|
"node-gyp-build": "bin.js",
|
||||||
|
"node-gyp-build-optional": "optional.js",
|
||||||
|
"node-gyp-build-test": "build-test.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/object-hash": {
|
"node_modules/object-hash": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
|
||||||
@ -3292,6 +3331,15 @@
|
|||||||
"node": ">=14.17"
|
"node": ">=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/undici": {
|
||||||
|
"version": "7.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici/-/undici-7.10.0.tgz",
|
||||||
|
"integrity": "sha512-u5otvFBOBZvmdjWLVW+5DAc9Nkq8f24g0O9oY7qw2JVIF1VocIFoyz9JFkuVOS2j41AufeO0xnlweJ2RLT8nGw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.18.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/undici-types": {
|
"node_modules/undici-types": {
|
||||||
"version": "6.21.0",
|
"version": "6.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||||
@ -3317,6 +3365,21 @@
|
|||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/utf-8-validate": {
|
||||||
|
"version": "5.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz",
|
||||||
|
"integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"node-gyp-build": "^4.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.14.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
@ -3333,9 +3396,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/warframe-public-export-plus": {
|
"node_modules/warframe-public-export-plus": {
|
||||||
"version": "0.5.68",
|
"version": "0.5.69",
|
||||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.68.tgz",
|
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.69.tgz",
|
||||||
"integrity": "sha512-KMmwCVeQ4k+EN73UZqxnM+qQdPsST8geWoJCP7US5LT6JcRxa8ptmqYXwCzaLtckBLZyVbamsxKZAxPPJckxsA=="
|
"integrity": "sha512-vTU1tUzqpihzpseUSJMrM82pYbCDZCfW40jXIi+Ol9B3a3Acz0DccfP7i4eoXf7Abahu4H/sjRt/nSHLNBvLHA=="
|
||||||
},
|
},
|
||||||
"node_modules/warframe-riven-info": {
|
"node_modules/warframe-riven-info": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
|
@ -8,8 +8,11 @@
|
|||||||
"build": "tsc --incremental --sourceMap && ncp static/webui build/static/webui",
|
"build": "tsc --incremental --sourceMap && ncp static/webui build/static/webui",
|
||||||
"build:dev": "tsc --incremental --sourceMap",
|
"build:dev": "tsc --incremental --sourceMap",
|
||||||
"build-and-start": "npm run build && npm run start",
|
"build-and-start": "npm run build && npm run start",
|
||||||
|
"build-and-start:bun": "npm run verify && npm run bun-run",
|
||||||
"dev": "node scripts/dev.js",
|
"dev": "node scripts/dev.js",
|
||||||
|
"dev:bun": "bun scripts/dev.js",
|
||||||
"verify": "tsgo --noEmit",
|
"verify": "tsgo --noEmit",
|
||||||
|
"bun-run": "bun src/index.ts",
|
||||||
"lint": "eslint --ext .ts .",
|
"lint": "eslint --ext .ts .",
|
||||||
"lint:ci": "eslint --ext .ts --rule \"prettier/prettier: off\" .",
|
"lint:ci": "eslint --ext .ts --rule \"prettier/prettier: off\" .",
|
||||||
"lint:fix": "eslint --fix --ext .ts .",
|
"lint:fix": "eslint --fix --ext .ts .",
|
||||||
@ -20,6 +23,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/express": "^5",
|
"@types/express": "^5",
|
||||||
"@types/morgan": "^1.9.9",
|
"@types/morgan": "^1.9.9",
|
||||||
|
"@types/websocket": "^1.0.10",
|
||||||
"@types/ws": "^8.18.1",
|
"@types/ws": "^8.18.1",
|
||||||
"crc-32": "^1.2.2",
|
"crc-32": "^1.2.2",
|
||||||
"express": "^5",
|
"express": "^5",
|
||||||
@ -28,7 +32,8 @@
|
|||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
"ncp": "^2.0.0",
|
"ncp": "^2.0.0",
|
||||||
"typescript": "^5.5",
|
"typescript": "^5.5",
|
||||||
"warframe-public-export-plus": "^0.5.68",
|
"undici": "^7.10.0",
|
||||||
|
"warframe-public-export-plus": "^0.5.69",
|
||||||
"warframe-riven-info": "^0.1.2",
|
"warframe-riven-info": "^0.1.2",
|
||||||
"winston": "^3.17.0",
|
"winston": "^3.17.0",
|
||||||
"winston-daily-rotate-file": "^5.0.0",
|
"winston-daily-rotate-file": "^5.0.0",
|
||||||
|
@ -14,6 +14,7 @@ args.push("--secret");
|
|||||||
args.push(secret);
|
args.push(secret);
|
||||||
|
|
||||||
let buildproc, runproc;
|
let buildproc, runproc;
|
||||||
|
const spawnopts = { stdio: "inherit", shell: true };
|
||||||
function run(changedFile) {
|
function run(changedFile) {
|
||||||
if (changedFile) {
|
if (changedFile) {
|
||||||
console.log(`Change to ${changedFile} detected`);
|
console.log(`Change to ${changedFile} detected`);
|
||||||
@ -28,7 +29,8 @@ function run(changedFile) {
|
|||||||
runproc = undefined;
|
runproc = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const thisbuildproc = spawn("npm", ["run", "build:dev"], { stdio: "inherit", shell: true });
|
const thisbuildproc = spawn("npm", ["run", process.versions.bun ? "verify" : "build:dev"], spawnopts);
|
||||||
|
const thisbuildstart = Date.now();
|
||||||
buildproc = thisbuildproc;
|
buildproc = thisbuildproc;
|
||||||
buildproc.on("exit", code => {
|
buildproc.on("exit", code => {
|
||||||
if (buildproc !== thisbuildproc) {
|
if (buildproc !== thisbuildproc) {
|
||||||
@ -36,7 +38,8 @@ function run(changedFile) {
|
|||||||
}
|
}
|
||||||
buildproc = undefined;
|
buildproc = undefined;
|
||||||
if (code === 0) {
|
if (code === 0) {
|
||||||
runproc = spawn("npm", ["run", "start", "--", ...args], { stdio: "inherit", shell: true });
|
console.log(`${process.versions.bun ? "Verified" : "Built"} in ${Date.now() - thisbuildstart} ms`);
|
||||||
|
runproc = spawn("npm", ["run", process.versions.bun ? "bun-run" : "start", "--", ...args], spawnopts);
|
||||||
runproc.on("exit", () => {
|
runproc.on("exit", () => {
|
||||||
runproc = undefined;
|
runproc = undefined;
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { getCalendarProgress, getInventory } from "@/src/services/inventoryService";
|
import { checkCalendarChallengeCompletion, getCalendarProgress, getInventory } from "@/src/services/inventoryService";
|
||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
||||||
import { getWorldState } from "@/src/services/worldStateService";
|
import { getWorldState } from "@/src/services/worldStateService";
|
||||||
@ -12,27 +12,23 @@ export const completeCalendarEventController: RequestHandler = async (req, res)
|
|||||||
const calendarProgress = getCalendarProgress(inventory);
|
const calendarProgress = getCalendarProgress(inventory);
|
||||||
const currentSeason = getWorldState().KnownCalendarSeasons[0];
|
const currentSeason = getWorldState().KnownCalendarSeasons[0];
|
||||||
let inventoryChanges: IInventoryChanges = {};
|
let inventoryChanges: IInventoryChanges = {};
|
||||||
let dayIndex = 0;
|
const dayIndex = calendarProgress.SeasonProgress.LastCompletedDayIdx + 1;
|
||||||
for (const day of currentSeason.Days) {
|
const day = currentSeason.Days[dayIndex];
|
||||||
if (day.events.length == 0 || day.events[0].type != "CET_CHALLENGE") {
|
|
||||||
if (dayIndex == calendarProgress.SeasonProgress.LastCompletedDayIdx) {
|
|
||||||
if (day.events.length != 0) {
|
if (day.events.length != 0) {
|
||||||
|
if (day.events[0].type == "CET_CHALLENGE") {
|
||||||
|
throw new Error(`completeCalendarEvent should not be used for challenges`);
|
||||||
|
}
|
||||||
const selection = day.events[parseInt(req.query.CompletedEventIdx as string)];
|
const selection = day.events[parseInt(req.query.CompletedEventIdx as string)];
|
||||||
if (selection.type == "CET_REWARD") {
|
if (selection.type == "CET_REWARD") {
|
||||||
inventoryChanges = (await handleStoreItemAcquisition(selection.reward!, inventory))
|
inventoryChanges = (await handleStoreItemAcquisition(selection.reward!, inventory)).InventoryChanges;
|
||||||
.InventoryChanges;
|
|
||||||
} else if (selection.type == "CET_UPGRADE") {
|
} else if (selection.type == "CET_UPGRADE") {
|
||||||
calendarProgress.YearProgress.Upgrades.push(selection.upgrade!);
|
calendarProgress.YearProgress.Upgrades.push(selection.upgrade!);
|
||||||
} else if (selection.type != "CET_PLOT") {
|
} else if (selection.type != "CET_PLOT") {
|
||||||
throw new Error(`unexpected selection type: ${selection.type}`);
|
throw new Error(`unexpected selection type: ${selection.type}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
calendarProgress.SeasonProgress.LastCompletedDayIdx = dayIndex;
|
||||||
}
|
checkCalendarChallengeCompletion(calendarProgress, currentSeason);
|
||||||
++dayIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
calendarProgress.SeasonProgress.LastCompletedDayIdx++;
|
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
res.json({
|
res.json({
|
||||||
InventoryChanges: inventoryChanges,
|
InventoryChanges: inventoryChanges,
|
||||||
|
@ -11,13 +11,13 @@ import {
|
|||||||
import { getAccountForRequest, getSuffixedName } from "@/src/services/loginService";
|
import { getAccountForRequest, getSuffixedName } from "@/src/services/loginService";
|
||||||
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
||||||
import { IOid } from "@/src/types/commonTypes";
|
import { IOid } from "@/src/types/commonTypes";
|
||||||
import { IInventoryChanges, IPurchaseParams } from "@/src/types/purchaseTypes";
|
import { IInventoryChanges, IPurchaseParams, PurchaseSource } from "@/src/types/purchaseTypes";
|
||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
import { ExportBundles, ExportFlavour } from "warframe-public-export-plus";
|
import { ExportBundles, ExportFlavour } from "warframe-public-export-plus";
|
||||||
|
|
||||||
export const giftingController: RequestHandler = async (req, res) => {
|
export const giftingController: RequestHandler = async (req, res) => {
|
||||||
const data = getJSONfromString<IGiftingRequest>(String(req.body));
|
const data = getJSONfromString<IGiftingRequest>(String(req.body));
|
||||||
if (data.PurchaseParams.Source != 0 || !data.PurchaseParams.UsePremium) {
|
if (data.PurchaseParams.Source != PurchaseSource.Market || !data.PurchaseParams.UsePremium) {
|
||||||
throw new Error(`unexpected purchase params in gifting request: ${String(req.body)}`);
|
throw new Error(`unexpected purchase params in gifting request: ${String(req.body)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,13 +6,7 @@ import allDialogue from "@/static/fixed_responses/allDialogue.json";
|
|||||||
import { ILoadoutDatabase } from "@/src/types/saveLoadoutTypes";
|
import { ILoadoutDatabase } from "@/src/types/saveLoadoutTypes";
|
||||||
import { IInventoryClient, IShipInventory, equipmentKeys } from "@/src/types/inventoryTypes/inventoryTypes";
|
import { IInventoryClient, IShipInventory, equipmentKeys } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
import { IPolarity, ArtifactPolarity, EquipmentFeatures } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
import { IPolarity, ArtifactPolarity, EquipmentFeatures } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||||
import {
|
import { ExportCustoms, ExportFlavour, ExportResources, ExportVirtuals } from "warframe-public-export-plus";
|
||||||
ExportCustoms,
|
|
||||||
ExportFlavour,
|
|
||||||
ExportRegions,
|
|
||||||
ExportResources,
|
|
||||||
ExportVirtuals
|
|
||||||
} from "warframe-public-export-plus";
|
|
||||||
import { applyCheatsToInfestedFoundry, handleSubsumeCompletion } from "@/src/services/infestedFoundryService";
|
import { applyCheatsToInfestedFoundry, handleSubsumeCompletion } from "@/src/services/infestedFoundryService";
|
||||||
import {
|
import {
|
||||||
addMiscItems,
|
addMiscItems,
|
||||||
@ -22,7 +16,7 @@ import {
|
|||||||
generateRewardSeed
|
generateRewardSeed
|
||||||
} from "@/src/services/inventoryService";
|
} from "@/src/services/inventoryService";
|
||||||
import { logger } from "@/src/utils/logger";
|
import { logger } from "@/src/utils/logger";
|
||||||
import { catBreadHash } from "@/src/helpers/stringHelpers";
|
import { addString, catBreadHash } from "@/src/helpers/stringHelpers";
|
||||||
import { Types } from "mongoose";
|
import { Types } from "mongoose";
|
||||||
import { getNemesisManifest } from "@/src/helpers/nemesisHelpers";
|
import { getNemesisManifest } from "@/src/helpers/nemesisHelpers";
|
||||||
import { getPersonalRooms } from "@/src/services/personalRoomsService";
|
import { getPersonalRooms } from "@/src/services/personalRoomsService";
|
||||||
@ -167,18 +161,6 @@ export const getInventoryResponse = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.unlockAllMissions) {
|
|
||||||
inventoryResponse.Missions = [];
|
|
||||||
for (const tag of Object.keys(ExportRegions)) {
|
|
||||||
inventoryResponse.Missions.push({
|
|
||||||
Completes: 1,
|
|
||||||
Tier: 1,
|
|
||||||
Tag: tag
|
|
||||||
});
|
|
||||||
}
|
|
||||||
addString(inventoryResponse.NodeIntrosCompleted, "TeshinHardModeUnlocked");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.unlockAllShipDecorations) {
|
if (config.unlockAllShipDecorations) {
|
||||||
inventoryResponse.ShipDecorations = [];
|
inventoryResponse.ShipDecorations = [];
|
||||||
for (const [uniqueName, item] of Object.entries(ExportResources)) {
|
for (const [uniqueName, item] of Object.entries(ExportResources)) {
|
||||||
@ -352,6 +334,19 @@ export const getInventoryResponse = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.unlockAllSimarisResearchEntries) {
|
||||||
|
inventoryResponse.LibraryPersonalTarget = undefined;
|
||||||
|
inventoryResponse.LibraryPersonalProgress = [
|
||||||
|
"/Lotus/Types/Game/Library/Targets/Research1Target",
|
||||||
|
"/Lotus/Types/Game/Library/Targets/Research2Target",
|
||||||
|
"/Lotus/Types/Game/Library/Targets/Research3Target",
|
||||||
|
"/Lotus/Types/Game/Library/Targets/Research4Target",
|
||||||
|
"/Lotus/Types/Game/Library/Targets/Research5Target",
|
||||||
|
"/Lotus/Types/Game/Library/Targets/Research6Target",
|
||||||
|
"/Lotus/Types/Game/Library/Targets/Research7Target"
|
||||||
|
].map(type => ({ TargetType: type, Scans: 10, Completed: true }));
|
||||||
|
}
|
||||||
|
|
||||||
return inventoryResponse;
|
return inventoryResponse;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -362,12 +357,6 @@ const allEudicoHeistJobs = [
|
|||||||
"/Lotus/Types/Gameplay/Venus/Jobs/Heists/HeistProfitTakerBountyFour"
|
"/Lotus/Types/Gameplay/Venus/Jobs/Heists/HeistProfitTakerBountyFour"
|
||||||
];
|
];
|
||||||
|
|
||||||
const addString = (arr: string[], str: string): void => {
|
|
||||||
if (arr.indexOf(str) == -1) {
|
|
||||||
arr.push(str);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getExpRequiredForMr = (rank: number): number => {
|
const getExpRequiredForMr = (rank: number): number => {
|
||||||
if (rank <= 30) {
|
if (rank <= 30) {
|
||||||
return 2500 * rank * rank;
|
return 2500 * rank * rank;
|
||||||
|
@ -7,6 +7,7 @@ import { generateRewardSeed, getInventory } from "@/src/services/inventoryServic
|
|||||||
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";
|
||||||
|
import { sendWsBroadcastTo } from "@/src/services/webService";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
**** INPUT ****
|
**** INPUT ****
|
||||||
@ -76,6 +77,7 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
|
|||||||
InventoryJson: JSON.stringify(inventoryResponse),
|
InventoryJson: JSON.stringify(inventoryResponse),
|
||||||
MissionRewards: []
|
MissionRewards: []
|
||||||
});
|
});
|
||||||
|
sendWsBroadcastTo(account._id.toString(), { update_inventory: true });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,6 +108,7 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
|
|||||||
AffiliationMods,
|
AffiliationMods,
|
||||||
ConquestCompletedMissionsCount
|
ConquestCompletedMissionsCount
|
||||||
} satisfies IMissionInventoryUpdateResponse);
|
} satisfies IMissionInventoryUpdateResponse);
|
||||||
|
sendWsBroadcastTo(account._id.toString(), { update_inventory: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3,6 +3,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
|
|||||||
import { getInventory, updateCurrency } from "@/src/services/inventoryService";
|
import { getInventory, updateCurrency } from "@/src/services/inventoryService";
|
||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
|
import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
|
import { sendWsBroadcastTo } from "@/src/services/webService";
|
||||||
|
|
||||||
interface INameWeaponRequest {
|
interface INameWeaponRequest {
|
||||||
ItemName: string;
|
ItemName: string;
|
||||||
@ -27,4 +28,5 @@ export const nameWeaponController: RequestHandler = async (req, res) => {
|
|||||||
res.json({
|
res.json({
|
||||||
InventoryChanges: currencyChanges
|
InventoryChanges: currencyChanges
|
||||||
});
|
});
|
||||||
|
sendWsBroadcastTo(accountId, { update_inventory: true });
|
||||||
};
|
};
|
||||||
|
@ -8,16 +8,15 @@ import {
|
|||||||
getKnifeUpgrade,
|
getKnifeUpgrade,
|
||||||
getNemesisManifest,
|
getNemesisManifest,
|
||||||
getNemesisPasscode,
|
getNemesisPasscode,
|
||||||
getNemesisPasscodeModTypes,
|
|
||||||
GUESS_CORRECT,
|
GUESS_CORRECT,
|
||||||
GUESS_INCORRECT,
|
GUESS_INCORRECT,
|
||||||
GUESS_NEUTRAL,
|
GUESS_NEUTRAL,
|
||||||
GUESS_NONE,
|
GUESS_NONE,
|
||||||
GUESS_WILDCARD,
|
GUESS_WILDCARD,
|
||||||
IKnifeResponse
|
IKnifeResponse,
|
||||||
|
parseUpgrade
|
||||||
} from "@/src/helpers/nemesisHelpers";
|
} from "@/src/helpers/nemesisHelpers";
|
||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
|
||||||
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
|
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
|
||||||
import { freeUpSlot, getInventory } from "@/src/services/inventoryService";
|
import { freeUpSlot, getInventory } from "@/src/services/inventoryService";
|
||||||
import { getAccountForRequest } from "@/src/services/loginService";
|
import { getAccountForRequest } from "@/src/services/loginService";
|
||||||
@ -215,7 +214,19 @@ export const nemesisController: RequestHandler = async (req, res) => {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
inventory.Nemesis!.Weakened = true;
|
inventory.Nemesis!.Weakened = true;
|
||||||
await consumePasscodeModCharges(inventory, response);
|
|
||||||
|
// Subtract a charge from all requiem mods installed on parazon
|
||||||
|
const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!;
|
||||||
|
const dataknifeLoadout = loadout.DATAKNIFE.id(
|
||||||
|
inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE].$oid
|
||||||
|
);
|
||||||
|
const dataknifeConfigIndex = dataknifeLoadout?.s?.mod ?? 0;
|
||||||
|
const dataknifeUpgrades = inventory.DataKnives[0].Configs[dataknifeConfigIndex].Upgrades!;
|
||||||
|
for (let i = 3; i != 6; ++i) {
|
||||||
|
//logger.debug(`subtracting a charge from ${dataknifeUpgrades[i]}`);
|
||||||
|
const upgrade = parseUpgrade(inventory, dataknifeUpgrades[i]);
|
||||||
|
consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Guess was incorrect, increase rank
|
// Guess was incorrect, increase rank
|
||||||
@ -380,18 +391,3 @@ interface IKnife {
|
|||||||
AttachedUpgrades: IUpgradeClient[];
|
AttachedUpgrades: IUpgradeClient[];
|
||||||
HiddenWhenHolstered: boolean;
|
HiddenWhenHolstered: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const consumePasscodeModCharges = async (
|
|
||||||
inventory: TInventoryDatabaseDocument,
|
|
||||||
response: IKnifeResponse
|
|
||||||
): Promise<void> => {
|
|
||||||
const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!;
|
|
||||||
const dataknifeLoadout = loadout.DATAKNIFE.id(inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE].$oid);
|
|
||||||
const dataknifeConfigIndex = dataknifeLoadout?.s?.mod ?? 0;
|
|
||||||
const dataknifeUpgrades = inventory.DataKnives[0].Configs[dataknifeConfigIndex].Upgrades!;
|
|
||||||
const modTypes = getNemesisPasscodeModTypes(inventory.Nemesis!);
|
|
||||||
for (const modType of modTypes) {
|
|
||||||
const upgrade = getKnifeUpgrade(inventory, dataknifeUpgrades, modType);
|
|
||||||
consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
@ -3,6 +3,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
|
|||||||
import { IPurchaseRequest } from "@/src/types/purchaseTypes";
|
import { IPurchaseRequest } from "@/src/types/purchaseTypes";
|
||||||
import { handlePurchase } from "@/src/services/purchaseService";
|
import { handlePurchase } from "@/src/services/purchaseService";
|
||||||
import { getInventory } from "@/src/services/inventoryService";
|
import { getInventory } from "@/src/services/inventoryService";
|
||||||
|
import { sendWsBroadcastTo } from "@/src/services/webService";
|
||||||
|
|
||||||
export const purchaseController: RequestHandler = async (req, res) => {
|
export const purchaseController: RequestHandler = async (req, res) => {
|
||||||
const purchaseRequest = JSON.parse(String(req.body)) as IPurchaseRequest;
|
const purchaseRequest = JSON.parse(String(req.body)) as IPurchaseRequest;
|
||||||
@ -11,4 +12,5 @@ export const purchaseController: RequestHandler = async (req, res) => {
|
|||||||
const response = await handlePurchase(purchaseRequest, inventory);
|
const response = await handlePurchase(purchaseRequest, inventory);
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
res.json(response);
|
res.json(response);
|
||||||
|
sendWsBroadcastTo(accountId, { update_inventory: true });
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
import { getInventory, updateCurrency } from "@/src/services/inventoryService";
|
import { getInventory, updateCurrency } from "@/src/services/inventoryService";
|
||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
import { sendWsBroadcastTo } from "@/src/services/webService";
|
||||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
@ -22,6 +23,7 @@ export const renamePetController: RequestHandler = async (req, res) => {
|
|||||||
...data,
|
...data,
|
||||||
inventoryChanges: inventoryChanges
|
inventoryChanges: inventoryChanges
|
||||||
});
|
});
|
||||||
|
sendWsBroadcastTo(accountId, { update_inventory: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IRenamePetRequest {
|
interface IRenamePetRequest {
|
||||||
|
@ -15,6 +15,7 @@ import { InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
|
|||||||
import { ExportDojoRecipes } from "warframe-public-export-plus";
|
import { ExportDojoRecipes } from "warframe-public-export-plus";
|
||||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
||||||
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
||||||
|
import { sendWsBroadcastTo } from "@/src/services/webService";
|
||||||
|
|
||||||
export const sellController: RequestHandler = async (req, res) => {
|
export const sellController: RequestHandler = async (req, res) => {
|
||||||
const payload = JSON.parse(String(req.body)) as ISellRequest;
|
const payload = JSON.parse(String(req.body)) as ISellRequest;
|
||||||
@ -279,6 +280,7 @@ export const sellController: RequestHandler = async (req, res) => {
|
|||||||
res.json({
|
res.json({
|
||||||
inventoryChanges: inventoryChanges // "inventoryChanges" for this response instead of the usual "InventoryChanges"
|
inventoryChanges: inventoryChanges // "inventoryChanges" for this response instead of the usual "InventoryChanges"
|
||||||
});
|
});
|
||||||
|
sendWsBroadcastTo(accountId, { update_inventory: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
interface ISellRequest {
|
interface ISellRequest {
|
||||||
|
@ -13,7 +13,7 @@ export const updateChallengeProgressController: RequestHandler = async (req, res
|
|||||||
|
|
||||||
const inventory = await getInventory(
|
const inventory = await getInventory(
|
||||||
account._id.toString(),
|
account._id.toString(),
|
||||||
"ChallengesFixVersion ChallengeProgress SeasonChallengeHistory Affiliations"
|
"ChallengesFixVersion ChallengeProgress SeasonChallengeHistory Affiliations CalendarProgress"
|
||||||
);
|
);
|
||||||
let affiliationMods: IAffiliationMods[] = [];
|
let affiliationMods: IAffiliationMods[] = [];
|
||||||
if (challenges.ChallengeProgress) {
|
if (challenges.ChallengeProgress) {
|
||||||
|
34
src/controllers/custom/completeAllMissionsController.ts
Normal file
34
src/controllers/custom/completeAllMissionsController.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { addString } from "@/src/helpers/stringHelpers";
|
||||||
|
import { getInventory } from "@/src/services/inventoryService";
|
||||||
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
import { addFixedLevelRewards } from "@/src/services/missionInventoryUpdateService";
|
||||||
|
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
||||||
|
import { IMissionReward } from "@/src/types/missionTypes";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
import { ExportRegions } from "warframe-public-export-plus";
|
||||||
|
|
||||||
|
export const completeAllMissionsController: RequestHandler = async (req, res) => {
|
||||||
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
const inventory = await getInventory(accountId);
|
||||||
|
const MissionRewards: IMissionReward[] = [];
|
||||||
|
for (const [tag, node] of Object.entries(ExportRegions)) {
|
||||||
|
if (!inventory.Missions.find(x => x.Tag == tag)) {
|
||||||
|
inventory.Missions.push({
|
||||||
|
Completes: 1,
|
||||||
|
Tier: 1,
|
||||||
|
Tag: tag
|
||||||
|
});
|
||||||
|
|
||||||
|
if (node.missionReward) {
|
||||||
|
console.log(node.missionReward);
|
||||||
|
addFixedLevelRewards(node.missionReward, inventory, MissionRewards);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const reward of MissionRewards) {
|
||||||
|
await handleStoreItemAcquisition(reward.StoreItem, inventory, reward.ItemCount, undefined, true);
|
||||||
|
}
|
||||||
|
addString(inventory.NodeIntrosCompleted, "TeshinHardModeUnlocked");
|
||||||
|
await inventory.save();
|
||||||
|
res.end();
|
||||||
|
};
|
@ -128,7 +128,7 @@ export const manageQuestsController: RequestHandler = async (req, res) => {
|
|||||||
await completeQuest(inventory, questKey.ItemType);
|
await completeQuest(inventory, questKey.ItemType);
|
||||||
} else {
|
} else {
|
||||||
const progress = {
|
const progress = {
|
||||||
c: questManifest.chainStages![currentStage].key ? -1 : 0,
|
c: 0,
|
||||||
i: false,
|
i: false,
|
||||||
m: false,
|
m: false,
|
||||||
b: []
|
b: []
|
||||||
|
@ -237,7 +237,7 @@ export const getNemesisPasscode = (nemesis: { fp: bigint; Faction: TNemesisFacti
|
|||||||
return passcode;
|
return passcode;
|
||||||
};
|
};
|
||||||
|
|
||||||
const requiemMods: readonly string[] = [
|
/*const requiemMods: readonly string[] = [
|
||||||
"/Lotus/Upgrades/Mods/Immortal/ImmortalOneMod",
|
"/Lotus/Upgrades/Mods/Immortal/ImmortalOneMod",
|
||||||
"/Lotus/Upgrades/Mods/Immortal/ImmortalTwoMod",
|
"/Lotus/Upgrades/Mods/Immortal/ImmortalTwoMod",
|
||||||
"/Lotus/Upgrades/Mods/Immortal/ImmortalThreeMod",
|
"/Lotus/Upgrades/Mods/Immortal/ImmortalThreeMod",
|
||||||
@ -246,7 +246,7 @@ const requiemMods: readonly string[] = [
|
|||||||
"/Lotus/Upgrades/Mods/Immortal/ImmortalSixMod",
|
"/Lotus/Upgrades/Mods/Immortal/ImmortalSixMod",
|
||||||
"/Lotus/Upgrades/Mods/Immortal/ImmortalSevenMod",
|
"/Lotus/Upgrades/Mods/Immortal/ImmortalSevenMod",
|
||||||
"/Lotus/Upgrades/Mods/Immortal/ImmortalEightMod"
|
"/Lotus/Upgrades/Mods/Immortal/ImmortalEightMod"
|
||||||
];
|
];*/
|
||||||
|
|
||||||
export const antivirusMods: readonly string[] = [
|
export const antivirusMods: readonly string[] = [
|
||||||
"/Lotus/Upgrades/Mods/Immortal/AntivirusOneMod",
|
"/Lotus/Upgrades/Mods/Immortal/AntivirusOneMod",
|
||||||
@ -259,12 +259,12 @@ export const antivirusMods: readonly string[] = [
|
|||||||
"/Lotus/Upgrades/Mods/Immortal/AntivirusEightMod"
|
"/Lotus/Upgrades/Mods/Immortal/AntivirusEightMod"
|
||||||
];
|
];
|
||||||
|
|
||||||
export const getNemesisPasscodeModTypes = (nemesis: { fp: bigint; Faction: TNemesisFaction }): string[] => {
|
/*export const getNemesisPasscodeModTypes = (nemesis: { fp: bigint; Faction: TNemesisFaction }): string[] => {
|
||||||
const passcode = getNemesisPasscode(nemesis);
|
const passcode = getNemesisPasscode(nemesis);
|
||||||
return nemesis.Faction == "FC_INFESTATION"
|
return nemesis.Faction == "FC_INFESTATION"
|
||||||
? passcode.map(i => antivirusMods[i])
|
? passcode.map(i => antivirusMods[i])
|
||||||
: passcode.map(i => requiemMods[i]);
|
: passcode.map(i => requiemMods[i]);
|
||||||
};
|
};*/
|
||||||
|
|
||||||
// Symbols; 0-7 are the normal requiem mods.
|
// Symbols; 0-7 are the normal requiem mods.
|
||||||
export const GUESS_NONE = 8;
|
export const GUESS_NONE = 8;
|
||||||
@ -343,6 +343,27 @@ export const getKnifeUpgrade = (
|
|||||||
throw new Error(`${type} does not seem to be installed on parazon?!`);
|
throw new Error(`${type} does not seem to be installed on parazon?!`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const parseUpgrade = (
|
||||||
|
inventory: TInventoryDatabaseDocument,
|
||||||
|
str: string
|
||||||
|
): { ItemId: IOid; ItemType: string } => {
|
||||||
|
if (str.length == 24) {
|
||||||
|
const upgrade = inventory.Upgrades.id(str);
|
||||||
|
if (upgrade) {
|
||||||
|
return {
|
||||||
|
ItemId: { $oid: str },
|
||||||
|
ItemType: upgrade.ItemType
|
||||||
|
};
|
||||||
|
}
|
||||||
|
throw new Error(`Could not resolve oid ${str}`);
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
ItemId: { $oid: "000000000000000000000000" },
|
||||||
|
ItemType: str
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const consumeModCharge = (
|
export const consumeModCharge = (
|
||||||
response: IKnifeResponse,
|
response: IKnifeResponse,
|
||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
|
@ -54,3 +54,9 @@ export const regexEscape = (str: string): string => {
|
|||||||
str = str.split("}").join("\\}");
|
str = str.split("}").join("\\}");
|
||||||
return str;
|
return str;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const addString = (arr: string[], str: string): void => {
|
||||||
|
if (arr.indexOf(str) == -1) {
|
||||||
|
arr.push(str);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -17,7 +17,6 @@ export interface IMessageDatabase extends IMessage {
|
|||||||
ownerId: Types.ObjectId;
|
ownerId: Types.ObjectId;
|
||||||
date: Date; //created at
|
date: Date; //created at
|
||||||
attVisualOnly?: boolean;
|
attVisualOnly?: boolean;
|
||||||
expiry?: Date;
|
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,6 +32,7 @@ export interface IMessage {
|
|||||||
att?: string[];
|
att?: string[];
|
||||||
countedAtt?: ITypeCount[];
|
countedAtt?: ITypeCount[];
|
||||||
transmission?: string;
|
transmission?: string;
|
||||||
|
CrossPlatform?: boolean;
|
||||||
arg?: Arg[];
|
arg?: Arg[];
|
||||||
gifts?: IGift[];
|
gifts?: IGift[];
|
||||||
r?: boolean;
|
r?: boolean;
|
||||||
@ -107,7 +107,9 @@ const messageSchema = new Schema<IMessageDatabase>(
|
|||||||
lowPrioNewPlayers: Boolean,
|
lowPrioNewPlayers: Boolean,
|
||||||
startDate: Date,
|
startDate: Date,
|
||||||
endDate: Date,
|
endDate: Date,
|
||||||
|
date: { type: Date, required: true },
|
||||||
r: Boolean,
|
r: Boolean,
|
||||||
|
CrossPlatform: Boolean,
|
||||||
att: { type: [String], default: undefined },
|
att: { type: [String], default: undefined },
|
||||||
gifts: { type: [giftSchema], default: undefined },
|
gifts: { type: [giftSchema], default: undefined },
|
||||||
countedAtt: { type: [typeCountSchema], default: undefined },
|
countedAtt: { type: [typeCountSchema], default: undefined },
|
||||||
@ -128,7 +130,7 @@ const messageSchema = new Schema<IMessageDatabase>(
|
|||||||
declineAction: String,
|
declineAction: String,
|
||||||
hasAccountAction: Boolean
|
hasAccountAction: Boolean
|
||||||
},
|
},
|
||||||
{ timestamps: { createdAt: "date", updatedAt: false }, id: false }
|
{ id: false }
|
||||||
);
|
);
|
||||||
|
|
||||||
messageSchema.virtual("messageId").get(function (this: IMessageDatabase) {
|
messageSchema.virtual("messageId").get(function (this: IMessageDatabase) {
|
||||||
@ -151,13 +153,15 @@ messageSchema.set("toJSON", {
|
|||||||
|
|
||||||
if (messageDatabase.startDate && messageDatabase.endDate) {
|
if (messageDatabase.startDate && messageDatabase.endDate) {
|
||||||
messageClient.startDate = toMongoDate(messageDatabase.startDate);
|
messageClient.startDate = toMongoDate(messageDatabase.startDate);
|
||||||
|
|
||||||
messageClient.endDate = toMongoDate(messageDatabase.endDate);
|
messageClient.endDate = toMongoDate(messageDatabase.endDate);
|
||||||
|
} else {
|
||||||
|
delete messageClient.startDate;
|
||||||
|
delete messageClient.endDate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
messageSchema.index({ ownerId: 1 });
|
messageSchema.index({ ownerId: 1 });
|
||||||
messageSchema.index({ expiry: 1 }, { expireAfterSeconds: 0 });
|
messageSchema.index({ endDate: 1 }, { expireAfterSeconds: 0 });
|
||||||
|
|
||||||
export const Inbox = model<IMessageDatabase>("Inbox", messageSchema, "inbox");
|
export const Inbox = model<IMessageDatabase>("Inbox", messageSchema, "inbox");
|
||||||
|
@ -12,6 +12,7 @@ import { ircDroppedController } from "@/src/controllers/custom/ircDroppedControl
|
|||||||
import { unlockAllIntrinsicsController } from "@/src/controllers/custom/unlockAllIntrinsicsController";
|
import { unlockAllIntrinsicsController } from "@/src/controllers/custom/unlockAllIntrinsicsController";
|
||||||
import { addMissingMaxRankModsController } from "@/src/controllers/custom/addMissingMaxRankModsController";
|
import { addMissingMaxRankModsController } from "@/src/controllers/custom/addMissingMaxRankModsController";
|
||||||
import { webuiFileChangeDetectedController } from "@/src/controllers/custom/webuiFileChangeDetectedController";
|
import { webuiFileChangeDetectedController } from "@/src/controllers/custom/webuiFileChangeDetectedController";
|
||||||
|
import { completeAllMissionsController } from "@/src/controllers/custom/completeAllMissionsController";
|
||||||
|
|
||||||
import { createAccountController } from "@/src/controllers/custom/createAccountController";
|
import { createAccountController } from "@/src/controllers/custom/createAccountController";
|
||||||
import { createMessageController } from "@/src/controllers/custom/createMessageController";
|
import { createMessageController } from "@/src/controllers/custom/createMessageController";
|
||||||
@ -40,6 +41,7 @@ customRouter.get("/ircDropped", ircDroppedController);
|
|||||||
customRouter.get("/unlockAllIntrinsics", unlockAllIntrinsicsController);
|
customRouter.get("/unlockAllIntrinsics", unlockAllIntrinsicsController);
|
||||||
customRouter.get("/addMissingMaxRankMods", addMissingMaxRankModsController);
|
customRouter.get("/addMissingMaxRankMods", addMissingMaxRankModsController);
|
||||||
customRouter.get("/webuiFileChangeDetected", webuiFileChangeDetectedController);
|
customRouter.get("/webuiFileChangeDetected", webuiFileChangeDetectedController);
|
||||||
|
customRouter.get("/completeAllMissions", completeAllMissionsController);
|
||||||
|
|
||||||
customRouter.post("/createAccount", createAccountController);
|
customRouter.post("/createAccount", createAccountController);
|
||||||
customRouter.post("/createMessage", createMessageController);
|
customRouter.post("/createMessage", createMessageController);
|
||||||
|
@ -19,7 +19,6 @@ export interface IConfig {
|
|||||||
skipTutorial?: boolean;
|
skipTutorial?: boolean;
|
||||||
skipAllDialogue?: boolean;
|
skipAllDialogue?: boolean;
|
||||||
unlockAllScans?: boolean;
|
unlockAllScans?: boolean;
|
||||||
unlockAllMissions?: boolean;
|
|
||||||
infiniteCredits?: boolean;
|
infiniteCredits?: boolean;
|
||||||
infinitePlatinum?: boolean;
|
infinitePlatinum?: boolean;
|
||||||
infiniteEndo?: boolean;
|
infiniteEndo?: boolean;
|
||||||
@ -49,6 +48,9 @@ export interface IConfig {
|
|||||||
noVendorPurchaseLimits?: boolean;
|
noVendorPurchaseLimits?: boolean;
|
||||||
noDeathMarks?: boolean;
|
noDeathMarks?: boolean;
|
||||||
noKimCooldowns?: boolean;
|
noKimCooldowns?: boolean;
|
||||||
|
fullyStockedVendors?: boolean;
|
||||||
|
baroAlwaysAvailable?: boolean;
|
||||||
|
baroFullyStocked?: boolean;
|
||||||
syndicateMissionsRepeatable?: boolean;
|
syndicateMissionsRepeatable?: boolean;
|
||||||
unlockAllProfitTakerStages?: boolean;
|
unlockAllProfitTakerStages?: boolean;
|
||||||
instantFinishRivenChallenge?: boolean;
|
instantFinishRivenChallenge?: boolean;
|
||||||
@ -62,8 +64,13 @@ export interface IConfig {
|
|||||||
noDojoResearchTime?: boolean;
|
noDojoResearchTime?: boolean;
|
||||||
fastClanAscension?: boolean;
|
fastClanAscension?: boolean;
|
||||||
missionsCanGiveAllRelics?: boolean;
|
missionsCanGiveAllRelics?: boolean;
|
||||||
|
unlockAllSimarisResearchEntries?: boolean;
|
||||||
spoofMasteryRank?: number;
|
spoofMasteryRank?: number;
|
||||||
nightwaveStandingMultiplier?: number;
|
nightwaveStandingMultiplier?: number;
|
||||||
|
unfaithfulBugFixes?: {
|
||||||
|
ignore1999LastRegionPlayed?: boolean;
|
||||||
|
fixXtraCheeseTimer?: boolean;
|
||||||
|
};
|
||||||
worldState?: {
|
worldState?: {
|
||||||
creditBoost?: boolean;
|
creditBoost?: boolean;
|
||||||
affinityBoost?: boolean;
|
affinityBoost?: boolean;
|
||||||
|
@ -5,7 +5,12 @@ import { config, configPath, loadConfig } from "./configService";
|
|||||||
import { getWebPorts, sendWsBroadcast, startWebServer, stopWebServer } from "./webService";
|
import { getWebPorts, sendWsBroadcast, startWebServer, stopWebServer } from "./webService";
|
||||||
|
|
||||||
let amnesia = false;
|
let amnesia = false;
|
||||||
fs.watchFile(configPath, () => {
|
fs.watchFile(configPath, (now, then) => {
|
||||||
|
// https://github.com/oven-sh/bun/issues/20542
|
||||||
|
if (process.versions.bun && now.mtimeMs == then.mtimeMs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (amnesia) {
|
if (amnesia) {
|
||||||
amnesia = false;
|
amnesia = false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2,8 +2,8 @@ import { IMessageDatabase, Inbox } from "@/src/models/inboxModel";
|
|||||||
import { getAccountForRequest } from "@/src/services/loginService";
|
import { getAccountForRequest } from "@/src/services/loginService";
|
||||||
import { HydratedDocument, Types } from "mongoose";
|
import { HydratedDocument, Types } from "mongoose";
|
||||||
import { Request } from "express";
|
import { Request } from "express";
|
||||||
import eventMessages from "@/static/fixed_responses/eventMessages.json";
|
import { unixTimesInMs } from "../constants/timeConstants";
|
||||||
import { logger } from "@/src/utils/logger";
|
import { config } from "./configService";
|
||||||
|
|
||||||
export const getAllMessagesSorted = async (accountId: string): Promise<HydratedDocument<IMessageDatabase>[]> => {
|
export const getAllMessagesSorted = async (accountId: string): Promise<HydratedDocument<IMessageDatabase>[]> => {
|
||||||
const inbox = await Inbox.find({ ownerId: accountId }).sort({ date: -1 });
|
const inbox = await Inbox.find({ ownerId: accountId }).sort({ date: -1 });
|
||||||
@ -29,40 +29,56 @@ export const deleteAllMessagesRead = async (accountId: string): Promise<void> =>
|
|||||||
|
|
||||||
export const createNewEventMessages = async (req: Request): Promise<void> => {
|
export const createNewEventMessages = async (req: Request): Promise<void> => {
|
||||||
const account = await getAccountForRequest(req);
|
const account = await getAccountForRequest(req);
|
||||||
const latestEventMessageDate = account.LatestEventMessageDate;
|
const newEventMessages: IMessageCreationTemplate[] = [];
|
||||||
|
|
||||||
//TODO: is baroo there? create these kind of messages too (periodical messages)
|
// Baro
|
||||||
const newEventMessages = eventMessages.Messages.filter(m => new Date(m.eventMessageDate) > latestEventMessageDate);
|
const baroIndex = Math.trunc((Date.now() - 910800000) / (unixTimesInMs.day * 14));
|
||||||
|
const baroStart = baroIndex * (unixTimesInMs.day * 14) + 910800000;
|
||||||
|
const baroActualStart = baroStart + unixTimesInMs.day * (config.baroAlwaysAvailable ? 0 : 12);
|
||||||
|
if (account.LatestEventMessageDate.getTime() < baroActualStart) {
|
||||||
|
newEventMessages.push({
|
||||||
|
sndr: "/Lotus/Language/G1Quests/VoidTraderName",
|
||||||
|
sub: "/Lotus/Language/CommunityMessages/VoidTraderAppearanceTitle",
|
||||||
|
msg: "/Lotus/Language/CommunityMessages/VoidTraderAppearanceMessage",
|
||||||
|
icon: "/Lotus/Interface/Icons/Npcs/BaroKiTeerPortrait.png",
|
||||||
|
startDate: new Date(baroActualStart),
|
||||||
|
endDate: new Date(baroStart + unixTimesInMs.day * 14),
|
||||||
|
CrossPlatform: true,
|
||||||
|
arg: [
|
||||||
|
{
|
||||||
|
Key: "NODE_NAME",
|
||||||
|
Tag: ["EarthHUB", "MercuryHUB", "SaturnHUB", "PlutoHUB"][baroIndex % 4]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
date: new Date(baroActualStart)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (newEventMessages.length === 0) {
|
if (newEventMessages.length === 0) {
|
||||||
logger.debug(`No new event messages. Latest event message date: ${latestEventMessageDate.toISOString()}`);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const savedEventMessages = await createMessage(account._id, newEventMessages);
|
await createMessage(account._id, newEventMessages);
|
||||||
logger.debug("created event messages", savedEventMessages);
|
|
||||||
|
|
||||||
const latestEventMessage = newEventMessages.reduce((prev, current) =>
|
const latestEventMessage = newEventMessages.reduce((prev, current) =>
|
||||||
prev.eventMessageDate > current.eventMessageDate ? prev : current
|
prev.startDate! > current.startDate! ? prev : current
|
||||||
);
|
);
|
||||||
|
account.LatestEventMessageDate = new Date(latestEventMessage.startDate!);
|
||||||
account.LatestEventMessageDate = new Date(latestEventMessage.eventMessageDate);
|
|
||||||
await account.save();
|
await account.save();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createMessage = async (
|
export const createMessage = async (
|
||||||
accountId: string | Types.ObjectId,
|
accountId: string | Types.ObjectId,
|
||||||
messages: IMessageCreationTemplate[]
|
messages: IMessageCreationTemplate[]
|
||||||
): Promise<HydratedDocument<IMessageDatabase>[]> => {
|
): Promise<void> => {
|
||||||
const ownerIdMessages = messages.map(m => ({
|
const ownerIdMessages = messages.map(m => ({
|
||||||
...m,
|
...m,
|
||||||
|
date: m.date ?? new Date(),
|
||||||
ownerId: accountId
|
ownerId: accountId
|
||||||
}));
|
}));
|
||||||
|
await Inbox.insertMany(ownerIdMessages);
|
||||||
const savedMessages = await Inbox.insertMany(ownerIdMessages);
|
|
||||||
return savedMessages as HydratedDocument<IMessageDatabase>[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface IMessageCreationTemplate extends Omit<IMessageDatabase, "_id" | "date" | "ownerId"> {
|
export interface IMessageCreationTemplate extends Omit<IMessageDatabase, "_id" | "date" | "ownerId"> {
|
||||||
ownerId?: string;
|
date?: Date;
|
||||||
}
|
}
|
||||||
|
@ -84,9 +84,11 @@ import { getRandomElement, getRandomInt, getRandomWeightedReward, SRng } from ".
|
|||||||
import { createMessage } from "./inboxService";
|
import { createMessage } from "./inboxService";
|
||||||
import { getMaxStanding, getMinStanding } from "@/src/helpers/syndicateStandingHelper";
|
import { getMaxStanding, getMinStanding } from "@/src/helpers/syndicateStandingHelper";
|
||||||
import { getNightwaveSyndicateTag, getWorldState } from "./worldStateService";
|
import { getNightwaveSyndicateTag, getWorldState } from "./worldStateService";
|
||||||
|
import { ICalendarSeason } from "@/src/types/worldStateTypes";
|
||||||
import { generateNemesisProfile, INemesisProfile } from "../helpers/nemesisHelpers";
|
import { generateNemesisProfile, INemesisProfile } from "../helpers/nemesisHelpers";
|
||||||
import { TAccountDocument } from "./loginService";
|
import { TAccountDocument } from "./loginService";
|
||||||
import { unixTimesInMs } from "../constants/timeConstants";
|
import { unixTimesInMs } from "../constants/timeConstants";
|
||||||
|
import { addString } from "../helpers/stringHelpers";
|
||||||
|
|
||||||
export const createInventory = async (
|
export const createInventory = async (
|
||||||
accountOwnerId: Types.ObjectId,
|
accountOwnerId: Types.ObjectId,
|
||||||
@ -1783,6 +1785,10 @@ export const addChallenges = (
|
|||||||
} else {
|
} else {
|
||||||
inventory.ChallengeProgress.push({ Name, Progress });
|
inventory.ChallengeProgress.push({ Name, Progress });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Name.startsWith("Calendar")) {
|
||||||
|
addString(getCalendarProgress(inventory).SeasonProgress.ActivatedChallenges, Name);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const affiliationMods: IAffiliationMods[] = [];
|
const affiliationMods: IAffiliationMods[] = [];
|
||||||
@ -2029,6 +2035,20 @@ export const getCalendarProgress = (inventory: TInventoryDatabaseDocument): ICal
|
|||||||
return inventory.CalendarProgress;
|
return inventory.CalendarProgress;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const checkCalendarChallengeCompletion = (
|
||||||
|
calendarProgress: ICalendarProgress,
|
||||||
|
currentSeason: ICalendarSeason
|
||||||
|
): void => {
|
||||||
|
const dayIndex = calendarProgress.SeasonProgress.LastCompletedDayIdx + 1;
|
||||||
|
if (calendarProgress.SeasonProgress.LastCompletedChallengeDayIdx >= dayIndex) {
|
||||||
|
const day = currentSeason.Days[dayIndex];
|
||||||
|
if (day.events.length != 0 && day.events[0].type == "CET_CHALLENGE") {
|
||||||
|
//logger.debug(`already completed the challenge, skipping ahead`);
|
||||||
|
calendarProgress.SeasonProgress.LastCompletedDayIdx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const giveNemesisWeaponRecipe = (
|
export const giveNemesisWeaponRecipe = (
|
||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
weaponType: string,
|
weaponType: string,
|
||||||
|
@ -33,6 +33,7 @@ import {
|
|||||||
addSkin,
|
addSkin,
|
||||||
addStanding,
|
addStanding,
|
||||||
applyClientEquipmentUpdates,
|
applyClientEquipmentUpdates,
|
||||||
|
checkCalendarChallengeCompletion,
|
||||||
combineInventoryChanges,
|
combineInventoryChanges,
|
||||||
generateRewardSeed,
|
generateRewardSeed,
|
||||||
getCalendarProgress,
|
getCalendarProgress,
|
||||||
@ -67,7 +68,15 @@ import {
|
|||||||
} from "@/src/helpers/nemesisHelpers";
|
} from "@/src/helpers/nemesisHelpers";
|
||||||
import { Loadout } from "../models/inventoryModels/loadoutModel";
|
import { Loadout } from "../models/inventoryModels/loadoutModel";
|
||||||
import { ILoadoutConfigDatabase } from "../types/saveLoadoutTypes";
|
import { ILoadoutConfigDatabase } from "../types/saveLoadoutTypes";
|
||||||
import { getLiteSortie, getSortie, idToBountyCycle, idToDay, idToWeek, pushClassicBounties } from "./worldStateService";
|
import {
|
||||||
|
getLiteSortie,
|
||||||
|
getSortie,
|
||||||
|
getWorldState,
|
||||||
|
idToBountyCycle,
|
||||||
|
idToDay,
|
||||||
|
idToWeek,
|
||||||
|
pushClassicBounties
|
||||||
|
} from "./worldStateService";
|
||||||
import { config } from "./configService";
|
import { config } from "./configService";
|
||||||
import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json";
|
import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json";
|
||||||
import { ISyndicateMissionInfo } from "../types/worldStateTypes";
|
import { ISyndicateMissionInfo } from "../types/worldStateTypes";
|
||||||
@ -79,7 +88,7 @@ const getRotations = (rewardInfo: IRewardInfo, tierOverride?: number): number[]
|
|||||||
if (rewardInfo.VaultsCracked) {
|
if (rewardInfo.VaultsCracked) {
|
||||||
const rotations: number[] = [];
|
const rotations: number[] = [];
|
||||||
for (let i = 0; i != rewardInfo.VaultsCracked; ++i) {
|
for (let i = 0; i != rewardInfo.VaultsCracked; ++i) {
|
||||||
rotations.push(i);
|
rotations.push(Math.min(i, 2));
|
||||||
}
|
}
|
||||||
return rotations;
|
return rotations;
|
||||||
}
|
}
|
||||||
@ -259,7 +268,9 @@ export const addMissionInventoryUpdates = async (
|
|||||||
addMissionComplete(inventory, value);
|
addMissionComplete(inventory, value);
|
||||||
break;
|
break;
|
||||||
case "LastRegionPlayed":
|
case "LastRegionPlayed":
|
||||||
|
if (!(config.unfaithfulBugFixes?.ignore1999LastRegionPlayed && value === "1999MapName")) {
|
||||||
inventory.LastRegionPlayed = value;
|
inventory.LastRegionPlayed = value;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "RawUpgrades":
|
case "RawUpgrades":
|
||||||
addMods(inventory, value);
|
addMods(inventory, value);
|
||||||
@ -471,7 +482,7 @@ export const addMissionInventoryUpdates = async (
|
|||||||
msg: "/Lotus/Language/G1Quests/DeathMarkMessage",
|
msg: "/Lotus/Language/G1Quests/DeathMarkMessage",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Stalker_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Stalker_d.png",
|
||||||
highPriority: true,
|
highPriority: true,
|
||||||
expiry: new Date(Date.now() + 86400_000) // TOVERIFY: This type of inbox message seems to automatically delete itself. We'll just delete it after 24 hours, but it's clear if this is correct.
|
endDate: new Date(Date.now() + 86400_000) // TOVERIFY: This type of inbox message seems to automatically delete itself. We'll just delete it after 24 hours, but it's not clear if this is correct.
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -620,11 +631,11 @@ export const addMissionInventoryUpdates = async (
|
|||||||
}
|
}
|
||||||
case "CalendarProgress": {
|
case "CalendarProgress": {
|
||||||
const calendarProgress = getCalendarProgress(inventory);
|
const calendarProgress = getCalendarProgress(inventory);
|
||||||
for (const progress of value) {
|
const currentSeason = getWorldState().KnownCalendarSeasons[0];
|
||||||
const challengeName = progress.challenge.substring(progress.challenge.lastIndexOf("/") + 1);
|
calendarProgress.SeasonProgress.LastCompletedChallengeDayIdx = currentSeason.Days.findIndex(
|
||||||
calendarProgress.SeasonProgress.LastCompletedChallengeDayIdx++;
|
x => x.events[0].challenge == value[value.length - 1].challenge
|
||||||
calendarProgress.SeasonProgress.ActivatedChallenges.push(challengeName);
|
);
|
||||||
}
|
checkCalendarChallengeCompletion(calendarProgress, currentSeason);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "duviriCaveOffers": {
|
case "duviriCaveOffers": {
|
||||||
@ -1196,7 +1207,7 @@ export const addMissionRewards = async (
|
|||||||
|
|
||||||
if (rewardInfo.JobStage != undefined && rewardInfo.jobId) {
|
if (rewardInfo.JobStage != undefined && rewardInfo.jobId) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const [jobType, unkIndex, hubNode, syndicateMissionId, locationTag] = rewardInfo.jobId.split("_");
|
const [jobType, unkIndex, hubNode, syndicateMissionId] = rewardInfo.jobId.split("_");
|
||||||
const syndicateMissions: ISyndicateMissionInfo[] = [];
|
const syndicateMissions: ISyndicateMissionInfo[] = [];
|
||||||
if (syndicateMissionId) {
|
if (syndicateMissionId) {
|
||||||
pushClassicBounties(syndicateMissions, idToBountyCycle(syndicateMissionId));
|
pushClassicBounties(syndicateMissions, idToBountyCycle(syndicateMissionId));
|
||||||
@ -1205,12 +1216,27 @@ export const addMissionRewards = async (
|
|||||||
if (syndicateEntry && syndicateEntry.Jobs) {
|
if (syndicateEntry && syndicateEntry.Jobs) {
|
||||||
let currentJob = syndicateEntry.Jobs[rewardInfo.JobTier!];
|
let currentJob = syndicateEntry.Jobs[rewardInfo.JobTier!];
|
||||||
if (syndicateEntry.Tag === "EntratiSyndicate") {
|
if (syndicateEntry.Tag === "EntratiSyndicate") {
|
||||||
|
if (
|
||||||
|
[
|
||||||
|
"DeimosRuinsExterminateBounty",
|
||||||
|
"DeimosRuinsEscortBounty",
|
||||||
|
"DeimosRuinsMistBounty",
|
||||||
|
"DeimosRuinsPurifyBounty",
|
||||||
|
"DeimosRuinsSacBounty",
|
||||||
|
"VaultBounty"
|
||||||
|
].some(ending => jobType.endsWith(ending))
|
||||||
|
) {
|
||||||
|
const vault = syndicateEntry.Jobs.find(j => j.locationTag == rewardInfo.jobId!.split("_").at(-1));
|
||||||
|
if (vault) {
|
||||||
|
currentJob = vault;
|
||||||
if (jobType.endsWith("VaultBounty")) {
|
if (jobType.endsWith("VaultBounty")) {
|
||||||
const vault = syndicateEntry.Jobs.find(j => j.locationTag === locationTag);
|
currentJob.xpAmounts = [currentJob.xpAmounts.reduce((partialSum, a) => partialSum + a, 0)];
|
||||||
if (vault) currentJob = vault;
|
|
||||||
}
|
}
|
||||||
let medallionAmount = Math.floor(currentJob.xpAmounts[rewardInfo.JobStage] / (rewardInfo.Q ? 0.8 : 1));
|
}
|
||||||
|
}
|
||||||
|
let medallionAmount = Math.floor(
|
||||||
|
Math.min(rewardInfo.JobStage, currentJob.xpAmounts.length - 1) / (rewardInfo.Q ? 0.8 : 1)
|
||||||
|
);
|
||||||
if (
|
if (
|
||||||
["DeimosEndlessAreaDefenseBounty", "DeimosEndlessExcavateBounty", "DeimosEndlessPurifyBounty"].some(
|
["DeimosEndlessAreaDefenseBounty", "DeimosEndlessExcavateBounty", "DeimosEndlessPurifyBounty"].some(
|
||||||
ending => jobType.endsWith(ending)
|
ending => jobType.endsWith(ending)
|
||||||
@ -1367,7 +1393,7 @@ export const addFixedLevelRewards = (
|
|||||||
if (rewards.countedItems) {
|
if (rewards.countedItems) {
|
||||||
for (const item of rewards.countedItems) {
|
for (const item of rewards.countedItems) {
|
||||||
MissionRewards.push({
|
MissionRewards.push({
|
||||||
StoreItem: `/Lotus/StoreItems${item.ItemType.substring("Lotus/".length)}`,
|
StoreItem: toStoreItem(item.ItemType),
|
||||||
ItemCount: item.ItemCount
|
ItemCount: item.ItemCount
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1543,7 +1569,7 @@ function getRandomMissionDrops(
|
|||||||
if (RewardInfo.jobId) {
|
if (RewardInfo.jobId) {
|
||||||
if (RewardInfo.JobStage! >= 0) {
|
if (RewardInfo.JobStage! >= 0) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const [jobType, unkIndex, hubNode, syndicateMissionId, locationTag] = RewardInfo.jobId.split("_");
|
const [jobType, unkIndex, hubNode, syndicateMissionId] = RewardInfo.jobId.split("_");
|
||||||
let isEndlessJob = false;
|
let isEndlessJob = false;
|
||||||
if (syndicateMissionId) {
|
if (syndicateMissionId) {
|
||||||
const syndicateMissions: ISyndicateMissionInfo[] = [];
|
const syndicateMissions: ISyndicateMissionInfo[] = [];
|
||||||
@ -1555,21 +1581,30 @@ function getRandomMissionDrops(
|
|||||||
let job = syndicateEntry.Jobs[RewardInfo.JobTier!];
|
let job = syndicateEntry.Jobs[RewardInfo.JobTier!];
|
||||||
|
|
||||||
if (syndicateEntry.Tag === "EntratiSyndicate") {
|
if (syndicateEntry.Tag === "EntratiSyndicate") {
|
||||||
|
if (
|
||||||
|
[
|
||||||
|
"DeimosRuinsExterminateBounty",
|
||||||
|
"DeimosRuinsEscortBounty",
|
||||||
|
"DeimosRuinsMistBounty",
|
||||||
|
"DeimosRuinsPurifyBounty",
|
||||||
|
"DeimosRuinsSacBounty",
|
||||||
|
"VaultBounty"
|
||||||
|
].some(ending => jobType.endsWith(ending))
|
||||||
|
) {
|
||||||
|
const vault = syndicateEntry.Jobs.find(
|
||||||
|
j => j.locationTag === RewardInfo.jobId!.split("_").at(-1)
|
||||||
|
);
|
||||||
|
if (vault) {
|
||||||
|
job = vault;
|
||||||
if (jobType.endsWith("VaultBounty")) {
|
if (jobType.endsWith("VaultBounty")) {
|
||||||
const vault = syndicateEntry.Jobs.find(j => j.locationTag === locationTag);
|
job.rewards = job.rewards.replace(
|
||||||
if (vault) job = vault;
|
"/Lotus/Types/Game/MissionDecks/",
|
||||||
|
"/Supplementals/"
|
||||||
|
);
|
||||||
|
job.xpAmounts = [job.xpAmounts.reduce((partialSum, a) => partialSum + a, 0)];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// if (
|
|
||||||
// [
|
|
||||||
// "DeimosRuinsExterminateBounty",
|
|
||||||
// "DeimosRuinsEscortBounty",
|
|
||||||
// "DeimosRuinsMistBounty",
|
|
||||||
// "DeimosRuinsPurifyBounty",
|
|
||||||
// "DeimosRuinsSacBounty"
|
|
||||||
// ].some(ending => jobType.endsWith(ending))
|
|
||||||
// ) {
|
|
||||||
// job.rewards = "TODO"; // Droptable for Arcana Isolation Vault
|
|
||||||
// }
|
|
||||||
if (
|
if (
|
||||||
[
|
[
|
||||||
"DeimosEndlessAreaDefenseBounty",
|
"DeimosEndlessAreaDefenseBounty",
|
||||||
@ -1628,24 +1663,32 @@ function getRandomMissionDrops(
|
|||||||
}
|
}
|
||||||
rewardManifests = [job.rewards];
|
rewardManifests = [job.rewards];
|
||||||
if (job.xpAmounts.length > 1) {
|
if (job.xpAmounts.length > 1) {
|
||||||
rotations = [RewardInfo.JobStage! % (job.xpAmounts.length - 1)];
|
const curentStage = RewardInfo.JobStage! + 1;
|
||||||
|
const totalStage = job.xpAmounts.length;
|
||||||
|
let tableIndex = 1; // Stage 2, Stage 3 of 4, and Stage 3 of 5
|
||||||
|
|
||||||
|
if (curentStage == 1) {
|
||||||
|
tableIndex = 0;
|
||||||
|
} else if (curentStage == totalStage) {
|
||||||
|
tableIndex = 3;
|
||||||
|
} else if (totalStage == 5 && curentStage == 4) {
|
||||||
|
tableIndex = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
rotations = [tableIndex];
|
||||||
} else {
|
} else {
|
||||||
rotations = [0];
|
rotations = [0];
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
RewardInfo.Q &&
|
RewardInfo.Q &&
|
||||||
(RewardInfo.JobStage === job.xpAmounts.length - 1 || job.isVault) &&
|
(RewardInfo.JobStage === job.xpAmounts.length - 1 || jobType.endsWith("VaultBounty")) &&
|
||||||
!isEndlessJob
|
!isEndlessJob
|
||||||
) {
|
) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
||||||
if (ExportRewards[job.rewards]) {
|
|
||||||
rewardManifests.push(job.rewards);
|
|
||||||
rotations.push(ExportRewards[job.rewards].length - 1);
|
rotations.push(ExportRewards[job.rewards].length - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else if (RewardInfo.challengeMissionId) {
|
} else if (RewardInfo.challengeMissionId) {
|
||||||
const rewardTables: Record<string, string[]> = {
|
const rewardTables: Record<string, string[]> = {
|
||||||
EntratiLabSyndicate: [
|
EntratiLabSyndicate: [
|
||||||
|
@ -11,9 +11,16 @@ import {
|
|||||||
import { getRandomWeightedRewardUc } from "@/src/services/rngService";
|
import { getRandomWeightedRewardUc } from "@/src/services/rngService";
|
||||||
import { applyStandingToVendorManifest, getVendorManifestByOid } from "@/src/services/serversideVendorsService";
|
import { applyStandingToVendorManifest, getVendorManifestByOid } from "@/src/services/serversideVendorsService";
|
||||||
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
|
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
import { IPurchaseRequest, IPurchaseResponse, SlotPurchase, IInventoryChanges } from "@/src/types/purchaseTypes";
|
import {
|
||||||
|
IPurchaseRequest,
|
||||||
|
IPurchaseResponse,
|
||||||
|
SlotPurchase,
|
||||||
|
IInventoryChanges,
|
||||||
|
PurchaseSource
|
||||||
|
} from "@/src/types/purchaseTypes";
|
||||||
import { logger } from "@/src/utils/logger";
|
import { logger } from "@/src/utils/logger";
|
||||||
import worldState from "@/static/fixed_responses/worldState/worldState.json";
|
import { getWorldState } from "./worldStateService";
|
||||||
|
import staticWorldState from "@/static/fixed_responses/worldState/worldState.json";
|
||||||
import {
|
import {
|
||||||
ExportBoosterPacks,
|
ExportBoosterPacks,
|
||||||
ExportBoosters,
|
ExportBoosters,
|
||||||
@ -52,7 +59,7 @@ export const handlePurchase = async (
|
|||||||
|
|
||||||
const prePurchaseInventoryChanges: IInventoryChanges = {};
|
const prePurchaseInventoryChanges: IInventoryChanges = {};
|
||||||
let seed: bigint | undefined;
|
let seed: bigint | undefined;
|
||||||
if (purchaseRequest.PurchaseParams.Source == 7) {
|
if (purchaseRequest.PurchaseParams.Source == PurchaseSource.Vendor) {
|
||||||
let manifest = getVendorManifestByOid(purchaseRequest.PurchaseParams.SourceId!);
|
let manifest = getVendorManifestByOid(purchaseRequest.PurchaseParams.SourceId!);
|
||||||
if (manifest) {
|
if (manifest) {
|
||||||
manifest = applyStandingToVendorManifest(inventory, manifest);
|
manifest = applyStandingToVendorManifest(inventory, manifest);
|
||||||
@ -69,18 +76,12 @@ export const handlePurchase = async (
|
|||||||
}
|
}
|
||||||
if (!config.dontSubtractPurchaseCreditCost) {
|
if (!config.dontSubtractPurchaseCreditCost) {
|
||||||
if (offer.RegularPrice) {
|
if (offer.RegularPrice) {
|
||||||
combineInventoryChanges(
|
updateCurrency(inventory, offer.RegularPrice[0], false, prePurchaseInventoryChanges);
|
||||||
prePurchaseInventoryChanges,
|
|
||||||
updateCurrency(inventory, offer.RegularPrice[0], false)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!config.dontSubtractPurchasePlatinumCost) {
|
if (!config.dontSubtractPurchasePlatinumCost) {
|
||||||
if (offer.PremiumPrice) {
|
if (offer.PremiumPrice) {
|
||||||
combineInventoryChanges(
|
updateCurrency(inventory, offer.PremiumPrice[0], true, prePurchaseInventoryChanges);
|
||||||
prePurchaseInventoryChanges,
|
|
||||||
updateCurrency(inventory, offer.PremiumPrice[0], true)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!config.dontSubtractPurchaseItemCost) {
|
if (!config.dontSubtractPurchaseItemCost) {
|
||||||
@ -166,18 +167,16 @@ export const handlePurchase = async (
|
|||||||
);
|
);
|
||||||
combineInventoryChanges(purchaseResponse.InventoryChanges, prePurchaseInventoryChanges);
|
combineInventoryChanges(purchaseResponse.InventoryChanges, prePurchaseInventoryChanges);
|
||||||
|
|
||||||
const currencyChanges = updateCurrency(
|
updateCurrency(
|
||||||
inventory,
|
inventory,
|
||||||
purchaseRequest.PurchaseParams.ExpectedPrice,
|
purchaseRequest.PurchaseParams.ExpectedPrice,
|
||||||
purchaseRequest.PurchaseParams.UsePremium
|
purchaseRequest.PurchaseParams.UsePremium,
|
||||||
|
prePurchaseInventoryChanges
|
||||||
);
|
);
|
||||||
purchaseResponse.InventoryChanges = {
|
|
||||||
...currencyChanges,
|
|
||||||
...purchaseResponse.InventoryChanges
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (purchaseRequest.PurchaseParams.Source) {
|
switch (purchaseRequest.PurchaseParams.Source) {
|
||||||
case 1: {
|
case PurchaseSource.VoidTrader: {
|
||||||
|
const worldState = getWorldState();
|
||||||
if (purchaseRequest.PurchaseParams.SourceId! != worldState.VoidTraders[0]._id.$oid) {
|
if (purchaseRequest.PurchaseParams.SourceId! != worldState.VoidTraders[0]._id.$oid) {
|
||||||
throw new Error("invalid request source");
|
throw new Error("invalid request source");
|
||||||
}
|
}
|
||||||
@ -186,10 +185,7 @@ export const handlePurchase = async (
|
|||||||
);
|
);
|
||||||
if (offer) {
|
if (offer) {
|
||||||
if (!config.dontSubtractPurchaseCreditCost) {
|
if (!config.dontSubtractPurchaseCreditCost) {
|
||||||
combineInventoryChanges(
|
updateCurrency(inventory, offer.RegularPrice, false, purchaseResponse.InventoryChanges);
|
||||||
purchaseResponse.InventoryChanges,
|
|
||||||
updateCurrency(inventory, offer.RegularPrice, false)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (purchaseRequest.PurchaseParams.ExpectedPrice) {
|
if (purchaseRequest.PurchaseParams.ExpectedPrice) {
|
||||||
throw new Error(`vendor purchase should not have an expected price`);
|
throw new Error(`vendor purchase should not have an expected price`);
|
||||||
@ -207,7 +203,7 @@ export const handlePurchase = async (
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2:
|
case PurchaseSource.SyndicateFavor:
|
||||||
{
|
{
|
||||||
const syndicateTag = purchaseRequest.PurchaseParams.SyndicateTag!;
|
const syndicateTag = purchaseRequest.PurchaseParams.SyndicateTag!;
|
||||||
if (purchaseRequest.PurchaseParams.UseFreeFavor!) {
|
if (purchaseRequest.PurchaseParams.UseFreeFavor!) {
|
||||||
@ -244,22 +240,16 @@ export const handlePurchase = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7:
|
case PurchaseSource.Vendor:
|
||||||
if (purchaseRequest.PurchaseParams.SourceId! in ExportVendors) {
|
if (purchaseRequest.PurchaseParams.SourceId! in ExportVendors) {
|
||||||
const vendor = ExportVendors[purchaseRequest.PurchaseParams.SourceId!];
|
const vendor = ExportVendors[purchaseRequest.PurchaseParams.SourceId!];
|
||||||
const offer = vendor.items.find(x => x.storeItem == purchaseRequest.PurchaseParams.StoreItem);
|
const offer = vendor.items.find(x => x.storeItem == purchaseRequest.PurchaseParams.StoreItem);
|
||||||
if (offer) {
|
if (offer) {
|
||||||
if (typeof offer.credits == "number" && !config.dontSubtractPurchaseCreditCost) {
|
if (typeof offer.credits == "number" && !config.dontSubtractPurchaseCreditCost) {
|
||||||
combineInventoryChanges(
|
updateCurrency(inventory, offer.credits, false, purchaseResponse.InventoryChanges);
|
||||||
purchaseResponse.InventoryChanges,
|
|
||||||
updateCurrency(inventory, offer.credits, false)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (typeof offer.platinum == "number" && !config.dontSubtractPurchasePlatinumCost) {
|
if (typeof offer.platinum == "number" && !config.dontSubtractPurchasePlatinumCost) {
|
||||||
combineInventoryChanges(
|
updateCurrency(inventory, offer.platinum, true, purchaseResponse.InventoryChanges);
|
||||||
purchaseResponse.InventoryChanges,
|
|
||||||
updateCurrency(inventory, offer.platinum, true)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (offer.itemPrices && !config.dontSubtractPurchaseItemCost) {
|
if (offer.itemPrices && !config.dontSubtractPurchaseItemCost) {
|
||||||
handleItemPrices(
|
handleItemPrices(
|
||||||
@ -275,15 +265,15 @@ export const handlePurchase = async (
|
|||||||
throw new Error(`vendor purchase should not have an expected price`);
|
throw new Error(`vendor purchase should not have an expected price`);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 18: {
|
case PurchaseSource.PrimeVaultTrader: {
|
||||||
if (purchaseRequest.PurchaseParams.SourceId! != worldState.PrimeVaultTraders[0]._id.$oid) {
|
if (purchaseRequest.PurchaseParams.SourceId! != staticWorldState.PrimeVaultTraders[0]._id.$oid) {
|
||||||
throw new Error("invalid request source");
|
throw new Error("invalid request source");
|
||||||
}
|
}
|
||||||
const offer =
|
const offer =
|
||||||
worldState.PrimeVaultTraders[0].Manifest.find(
|
staticWorldState.PrimeVaultTraders[0].Manifest.find(
|
||||||
x => x.ItemType == purchaseRequest.PurchaseParams.StoreItem
|
x => x.ItemType == purchaseRequest.PurchaseParams.StoreItem
|
||||||
) ??
|
) ??
|
||||||
worldState.PrimeVaultTraders[0].EvergreenManifest.find(
|
staticWorldState.PrimeVaultTraders[0].EvergreenManifest.find(
|
||||||
x => x.ItemType == purchaseRequest.PurchaseParams.StoreItem
|
x => x.ItemType == purchaseRequest.PurchaseParams.StoreItem
|
||||||
);
|
);
|
||||||
if (offer) {
|
if (offer) {
|
||||||
|
@ -6,6 +6,7 @@ import { mixSeeds, SRng } from "@/src/services/rngService";
|
|||||||
import { IItemManifest, IVendorInfo, IVendorManifest } from "@/src/types/vendorTypes";
|
import { IItemManifest, IVendorInfo, IVendorManifest } from "@/src/types/vendorTypes";
|
||||||
import { logger } from "@/src/utils/logger";
|
import { logger } from "@/src/utils/logger";
|
||||||
import { ExportVendors, IRange, IVendor, IVendorOffer } from "warframe-public-export-plus";
|
import { ExportVendors, IRange, IVendor, IVendorOffer } from "warframe-public-export-plus";
|
||||||
|
import { config } from "./configService";
|
||||||
|
|
||||||
interface IGeneratableVendorInfo extends Omit<IVendorInfo, "ItemManifest" | "Expiry"> {
|
interface IGeneratableVendorInfo extends Omit<IVendorInfo, "ItemManifest" | "Expiry"> {
|
||||||
cycleOffset?: number;
|
cycleOffset?: number;
|
||||||
@ -59,20 +60,23 @@ const getCycleDuration = (manifest: IVendor): number => {
|
|||||||
return dur * unixTimesInMs.hour;
|
return dur * unixTimesInMs.hour;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getVendorManifestByTypeName = (typeName: string): IVendorManifest | undefined => {
|
export const getVendorManifestByTypeName = (typeName: string, fullStock?: boolean): IVendorManifest | undefined => {
|
||||||
for (const vendorInfo of generatableVendors) {
|
for (const vendorInfo of generatableVendors) {
|
||||||
if (vendorInfo.TypeName == typeName) {
|
if (vendorInfo.TypeName == typeName) {
|
||||||
return generateVendorManifest(vendorInfo);
|
return generateVendorManifest(vendorInfo, fullStock ?? config.fullyStockedVendors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typeName in ExportVendors) {
|
if (typeName in ExportVendors) {
|
||||||
const manifest = ExportVendors[typeName];
|
const manifest = ExportVendors[typeName];
|
||||||
return generateVendorManifest({
|
return generateVendorManifest(
|
||||||
|
{
|
||||||
_id: { $oid: getVendorOid(typeName) },
|
_id: { $oid: getVendorOid(typeName) },
|
||||||
TypeName: typeName,
|
TypeName: typeName,
|
||||||
RandomSeedType: manifest.randomSeedType,
|
RandomSeedType: manifest.randomSeedType,
|
||||||
cycleDuration: getCycleDuration(manifest)
|
cycleDuration: getCycleDuration(manifest)
|
||||||
});
|
},
|
||||||
|
fullStock ?? config.fullyStockedVendors
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
@ -80,18 +84,21 @@ export const getVendorManifestByTypeName = (typeName: string): IVendorManifest |
|
|||||||
export const getVendorManifestByOid = (oid: string): IVendorManifest | undefined => {
|
export const getVendorManifestByOid = (oid: string): IVendorManifest | undefined => {
|
||||||
for (const vendorInfo of generatableVendors) {
|
for (const vendorInfo of generatableVendors) {
|
||||||
if (vendorInfo._id.$oid == oid) {
|
if (vendorInfo._id.$oid == oid) {
|
||||||
return generateVendorManifest(vendorInfo);
|
return generateVendorManifest(vendorInfo, config.fullyStockedVendors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const [typeName, manifest] of Object.entries(ExportVendors)) {
|
for (const [typeName, manifest] of Object.entries(ExportVendors)) {
|
||||||
const typeNameOid = getVendorOid(typeName);
|
const typeNameOid = getVendorOid(typeName);
|
||||||
if (typeNameOid == oid) {
|
if (typeNameOid == oid) {
|
||||||
return generateVendorManifest({
|
return generateVendorManifest(
|
||||||
|
{
|
||||||
_id: { $oid: typeNameOid },
|
_id: { $oid: typeNameOid },
|
||||||
TypeName: typeName,
|
TypeName: typeName,
|
||||||
RandomSeedType: manifest.randomSeedType,
|
RandomSeedType: manifest.randomSeedType,
|
||||||
cycleDuration: getCycleDuration(manifest)
|
cycleDuration: getCycleDuration(manifest)
|
||||||
});
|
},
|
||||||
|
config.fullyStockedVendors
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -169,9 +176,26 @@ const getOfferId = (offer: IVendorOffer | IItemManifest): TOfferId => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let vendorManifestsUsingFullStock = false;
|
||||||
const vendorManifestCache: Record<string, IVendorManifest> = {};
|
const vendorManifestCache: Record<string, IVendorManifest> = {};
|
||||||
|
|
||||||
const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorManifest => {
|
const clearVendorCache = (): void => {
|
||||||
|
for (const k of Object.keys(vendorManifestCache)) {
|
||||||
|
delete vendorManifestCache[k];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateVendorManifest = (
|
||||||
|
vendorInfo: IGeneratableVendorInfo,
|
||||||
|
fullStock: boolean | undefined
|
||||||
|
): IVendorManifest => {
|
||||||
|
fullStock ??= config.fullyStockedVendors;
|
||||||
|
fullStock ??= false;
|
||||||
|
if (vendorManifestsUsingFullStock != fullStock) {
|
||||||
|
vendorManifestsUsingFullStock = fullStock;
|
||||||
|
clearVendorCache();
|
||||||
|
}
|
||||||
|
|
||||||
if (!(vendorInfo.TypeName in vendorManifestCache)) {
|
if (!(vendorInfo.TypeName in vendorManifestCache)) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const { cycleOffset, cycleDuration, ...clientVendorInfo } = vendorInfo;
|
const { cycleOffset, cycleDuration, ...clientVendorInfo } = vendorInfo;
|
||||||
@ -208,7 +232,20 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
|
|||||||
const cycleIndex = Math.trunc((now - cycleOffset) / cycleDuration);
|
const cycleIndex = Math.trunc((now - cycleOffset) / cycleDuration);
|
||||||
const rng = new SRng(mixSeeds(vendorSeed, cycleIndex));
|
const rng = new SRng(mixSeeds(vendorSeed, cycleIndex));
|
||||||
const offersToAdd: IVendorOffer[] = [];
|
const offersToAdd: IVendorOffer[] = [];
|
||||||
if (!manifest.isOneBinPerCycle) {
|
if (manifest.isOneBinPerCycle) {
|
||||||
|
if (fullStock) {
|
||||||
|
for (const rawItem of manifest.items) {
|
||||||
|
offersToAdd.push(rawItem);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const binThisCycle = cycleIndex % 2; // Note: May want to check the actual number of bins, but this is only used for coda weapons right now.
|
||||||
|
for (const rawItem of manifest.items) {
|
||||||
|
if (rawItem.bin == binThisCycle) {
|
||||||
|
offersToAdd.push(rawItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// Compute vendor requirements, subtracting existing offers
|
// Compute vendor requirements, subtracting existing offers
|
||||||
const remainingItemCapacity: Record<TOfferId, number> = {};
|
const remainingItemCapacity: Record<TOfferId, number> = {};
|
||||||
const missingItemsPerBin: Record<number, number> = {};
|
const missingItemsPerBin: Record<number, number> = {};
|
||||||
@ -254,7 +291,9 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
|
|||||||
manifest.numItems &&
|
manifest.numItems &&
|
||||||
(manifest.numItems.minValue != manifest.numItems.maxValue ||
|
(manifest.numItems.minValue != manifest.numItems.maxValue ||
|
||||||
manifest.numItems.minValue != numCountedOffers);
|
manifest.numItems.minValue != numCountedOffers);
|
||||||
const numItemsTarget = manifest.numItems
|
const numItemsTarget = fullStock
|
||||||
|
? numUncountedOffers + numCountedOffers
|
||||||
|
: manifest.numItems
|
||||||
? numUncountedOffers +
|
? numUncountedOffers +
|
||||||
(useRng
|
(useRng
|
||||||
? rng.randomInt(manifest.numItems.minValue, manifest.numItems.maxValue)
|
? rng.randomInt(manifest.numItems.minValue, manifest.numItems.maxValue)
|
||||||
@ -282,13 +321,6 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
|
|||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
const binThisCycle = cycleIndex % 2; // Note: May want to auto-compute the bin size, but this is only used for coda weapons right now.
|
|
||||||
for (const rawItem of manifest.items) {
|
|
||||||
if (rawItem.bin == binThisCycle) {
|
|
||||||
offersToAdd.push(rawItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const cycleStart = cycleOffset + cycleIndex * cycleDuration;
|
const cycleStart = cycleOffset + cycleIndex * cycleDuration;
|
||||||
for (const rawItem of offersToAdd) {
|
for (const rawItem of offersToAdd) {
|
||||||
@ -387,8 +419,13 @@ if (args.dev) {
|
|||||||
logger.warn(`getCycleDuration self test failed`);
|
logger.warn(`getCycleDuration self test failed`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ads = getVendorManifestByTypeName("/Lotus/Types/Game/VendorManifests/Hubs/GuildAdvertisementVendorManifest")!
|
for (let i = 0; i != 2; ++i) {
|
||||||
.VendorInfo.ItemManifest;
|
const fullStock = !!i;
|
||||||
|
|
||||||
|
const ads = getVendorManifestByTypeName(
|
||||||
|
"/Lotus/Types/Game/VendorManifests/Hubs/GuildAdvertisementVendorManifest",
|
||||||
|
fullStock
|
||||||
|
)!.VendorInfo.ItemManifest;
|
||||||
if (
|
if (
|
||||||
ads.length != 5 ||
|
ads.length != 5 ||
|
||||||
ads[0].Bin != "BIN_4" ||
|
ads[0].Bin != "BIN_4" ||
|
||||||
@ -400,8 +437,10 @@ if (args.dev) {
|
|||||||
logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Hubs/GuildAdvertisementVendorManifest`);
|
logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Hubs/GuildAdvertisementVendorManifest`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const pall = getVendorManifestByTypeName("/Lotus/Types/Game/VendorManifests/Hubs/IronwakeDondaVendorManifest")!
|
const pall = getVendorManifestByTypeName(
|
||||||
.VendorInfo.ItemManifest;
|
"/Lotus/Types/Game/VendorManifests/Hubs/IronwakeDondaVendorManifest",
|
||||||
|
fullStock
|
||||||
|
)!.VendorInfo.ItemManifest;
|
||||||
if (
|
if (
|
||||||
pall.length != 5 ||
|
pall.length != 5 ||
|
||||||
pall[0].StoreItem != "/Lotus/StoreItems/Types/Items/ShipDecos/HarrowQuestKeyOrnament" ||
|
pall[0].StoreItem != "/Lotus/StoreItems/Types/Items/ShipDecos/HarrowQuestKeyOrnament" ||
|
||||||
@ -412,9 +451,12 @@ if (args.dev) {
|
|||||||
) {
|
) {
|
||||||
logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Hubs/IronwakeDondaVendorManifest`);
|
logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Hubs/IronwakeDondaVendorManifest`);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const cms = getVendorManifestByTypeName("/Lotus/Types/Game/VendorManifests/Hubs/RailjackCrewMemberVendorManifest")!
|
const cms = getVendorManifestByTypeName(
|
||||||
.VendorInfo.ItemManifest;
|
"/Lotus/Types/Game/VendorManifests/Hubs/RailjackCrewMemberVendorManifest",
|
||||||
|
false
|
||||||
|
)!.VendorInfo.ItemManifest;
|
||||||
if (
|
if (
|
||||||
cms.length != 9 ||
|
cms.length != 9 ||
|
||||||
cms[0].Bin != "BIN_2" ||
|
cms[0].Bin != "BIN_2" ||
|
||||||
@ -426,13 +468,15 @@ if (args.dev) {
|
|||||||
logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Hubs/RailjackCrewMemberVendorManifest`);
|
logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Hubs/RailjackCrewMemberVendorManifest`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const temple = getVendorManifestByTypeName("/Lotus/Types/Game/VendorManifests/TheHex/Temple1999VendorManifest")!
|
const temple = getVendorManifestByTypeName(
|
||||||
.VendorInfo.ItemManifest;
|
"/Lotus/Types/Game/VendorManifests/TheHex/Temple1999VendorManifest",
|
||||||
|
false
|
||||||
|
)!.VendorInfo.ItemManifest;
|
||||||
if (!temple.find(x => x.StoreItem == "/Lotus/StoreItems/Types/Items/MiscItems/Kuva")) {
|
if (!temple.find(x => x.StoreItem == "/Lotus/StoreItems/Types/Items/MiscItems/Kuva")) {
|
||||||
logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/TheHex/Temple1999VendorManifest`);
|
logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/TheHex/Temple1999VendorManifest`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const nakak = getVendorManifestByTypeName("/Lotus/Types/Game/VendorManifests/Ostron/MaskSalesmanManifest")!
|
const nakak = getVendorManifestByTypeName("/Lotus/Types/Game/VendorManifests/Ostron/MaskSalesmanManifest", false)!
|
||||||
.VendorInfo.ItemManifest;
|
.VendorInfo.ItemManifest;
|
||||||
if (
|
if (
|
||||||
nakak.length != 10 ||
|
nakak.length != 10 ||
|
||||||
|
@ -10,6 +10,7 @@ import { Account } from "../models/loginModel";
|
|||||||
import { createAccount, createNonce, getUsernameFromEmail, isCorrectPassword } from "./loginService";
|
import { createAccount, createNonce, getUsernameFromEmail, isCorrectPassword } from "./loginService";
|
||||||
import { IDatabaseAccountJson } from "../types/loginTypes";
|
import { IDatabaseAccountJson } from "../types/loginTypes";
|
||||||
import { HydratedDocument } from "mongoose";
|
import { HydratedDocument } from "mongoose";
|
||||||
|
import { Agent, WebSocket as UnidiciWebSocket } from "undici";
|
||||||
|
|
||||||
let httpServer: http.Server | undefined;
|
let httpServer: http.Server | undefined;
|
||||||
let httpsServer: https.Server | undefined;
|
let httpsServer: https.Server | undefined;
|
||||||
@ -44,8 +45,47 @@ export const startWebServer = (): void => {
|
|||||||
logger.info(
|
logger.info(
|
||||||
"Access the WebUI in your browser at http://localhost" + (httpPort == 80 ? "" : ":" + httpPort)
|
"Access the WebUI in your browser at http://localhost" + (httpPort == 80 ? "" : ":" + httpPort)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void runWsSelfTest("wss", httpsPort).then(ok => {
|
||||||
|
if (!ok) {
|
||||||
|
logger.warn(`WSS self-test failed. The server may not actually be reachable at port ${httpsPort}.`);
|
||||||
|
if (process.platform == "win32") {
|
||||||
|
logger.warn(
|
||||||
|
`You can check who actually has that port via powershell: Get-Process -Id (Get-NetTCPConnection -LocalPort ${httpsPort}).OwningProcess`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const runWsSelfTest = (protocol: "ws" | "wss", port: number): Promise<boolean> => {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
// https://github.com/oven-sh/bun/issues/20547
|
||||||
|
if (process.versions.bun) {
|
||||||
|
const client = new WebSocket(`${protocol}://localhost:${port}/custom/selftest`, {
|
||||||
|
tls: { rejectUnauthorized: false }
|
||||||
|
} as unknown as string);
|
||||||
|
client.onmessage = (e): void => {
|
||||||
|
resolve(e.data == "SpaceNinjaServer");
|
||||||
|
};
|
||||||
|
client.onerror = client.onclose = (): void => {
|
||||||
|
resolve(false);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const agent = new Agent({ connect: { rejectUnauthorized: false } });
|
||||||
|
const client = new UnidiciWebSocket(`${protocol}://localhost:${port}/custom/selftest`, {
|
||||||
|
dispatcher: agent
|
||||||
|
});
|
||||||
|
client.onmessage = (e): void => {
|
||||||
|
resolve(e.data == "SpaceNinjaServer");
|
||||||
|
};
|
||||||
|
client.onerror = client.onclose = (): void => {
|
||||||
|
resolve(false);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getWebPorts = (): Record<"http" | "https", number | undefined> => {
|
export const getWebPorts = (): Record<"http" | "https", number | undefined> => {
|
||||||
@ -125,9 +165,15 @@ interface IWsMsgToClient {
|
|||||||
isRegister: boolean;
|
isRegister: boolean;
|
||||||
};
|
};
|
||||||
logged_out?: boolean;
|
logged_out?: boolean;
|
||||||
|
update_inventory?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wsOnConnect = (ws: ws, _req: http.IncomingMessage): void => {
|
const wsOnConnect = (ws: ws, req: http.IncomingMessage): void => {
|
||||||
|
if (req.url == "/custom/selftest") {
|
||||||
|
ws.send("SpaceNinjaServer");
|
||||||
|
ws.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||||
ws.on("message", async msg => {
|
ws.on("message", async msg => {
|
||||||
const data = JSON.parse(String(msg)) as IWsMsgFromClient;
|
const data = JSON.parse(String(msg)) as IWsMsgFromClient;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import staticWorldState from "@/static/fixed_responses/worldState/worldState.json";
|
import staticWorldState from "@/static/fixed_responses/worldState/worldState.json";
|
||||||
|
import baro from "@/static/fixed_responses/worldState/baro.json";
|
||||||
import fissureMissions from "@/static/fixed_responses/worldState/fissureMissions.json";
|
import fissureMissions from "@/static/fixed_responses/worldState/fissureMissions.json";
|
||||||
import sortieTilesets from "@/static/fixed_responses/worldState/sortieTilesets.json";
|
import sortieTilesets from "@/static/fixed_responses/worldState/sortieTilesets.json";
|
||||||
import sortieTilesetMissions from "@/static/fixed_responses/worldState/sortieTilesetMissions.json";
|
import sortieTilesetMissions from "@/static/fixed_responses/worldState/sortieTilesetMissions.json";
|
||||||
@ -19,6 +20,8 @@ import {
|
|||||||
ISyndicateMissionInfo,
|
ISyndicateMissionInfo,
|
||||||
ITmp,
|
ITmp,
|
||||||
IVoidStorm,
|
IVoidStorm,
|
||||||
|
IVoidTrader,
|
||||||
|
IVoidTraderOffer,
|
||||||
IWorldState,
|
IWorldState,
|
||||||
TCircuitGameMode
|
TCircuitGameMode
|
||||||
} from "../types/worldStateTypes";
|
} from "../types/worldStateTypes";
|
||||||
@ -1114,6 +1117,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
LiteSorties: [],
|
LiteSorties: [],
|
||||||
ActiveMissions: [],
|
ActiveMissions: [],
|
||||||
GlobalUpgrades: [],
|
GlobalUpgrades: [],
|
||||||
|
VoidTraders: [],
|
||||||
VoidStorms: [],
|
VoidStorms: [],
|
||||||
EndlessXpChoices: [],
|
EndlessXpChoices: [],
|
||||||
KnownCalendarSeasons: [],
|
KnownCalendarSeasons: [],
|
||||||
@ -1242,6 +1246,77 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Baro
|
||||||
|
{
|
||||||
|
const baroIndex = Math.trunc((Date.now() - 910800000) / (unixTimesInMs.day * 14));
|
||||||
|
const baroStart = baroIndex * (unixTimesInMs.day * 14) + 910800000;
|
||||||
|
const baroActualStart = baroStart + unixTimesInMs.day * (config.baroAlwaysAvailable ? 0 : 12);
|
||||||
|
const baroEnd = baroStart + unixTimesInMs.day * 14;
|
||||||
|
const baroNode = ["EarthHUB", "MercuryHUB", "SaturnHUB", "PlutoHUB"][baroIndex % 4];
|
||||||
|
const vt: IVoidTrader = {
|
||||||
|
_id: { $oid: ((baroStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "493c96d6067610bc" },
|
||||||
|
Activation: { $date: { $numberLong: baroActualStart.toString() } },
|
||||||
|
Expiry: { $date: { $numberLong: baroEnd.toString() } },
|
||||||
|
Character: "Baro'Ki Teel",
|
||||||
|
Node: baroNode,
|
||||||
|
Manifest: []
|
||||||
|
};
|
||||||
|
worldState.VoidTraders.push(vt);
|
||||||
|
if (isBeforeNextExpectedWorldStateRefresh(timeMs, baroActualStart)) {
|
||||||
|
vt.Manifest = [];
|
||||||
|
if (config.baroFullyStocked) {
|
||||||
|
for (const armorSet of baro.armorSets) {
|
||||||
|
if (Array.isArray(armorSet[0])) {
|
||||||
|
for (const set of armorSet as IVoidTraderOffer[][]) {
|
||||||
|
for (const item of set) {
|
||||||
|
vt.Manifest.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const item of armorSet as IVoidTraderOffer[]) {
|
||||||
|
vt.Manifest.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const item of baro.rest) {
|
||||||
|
vt.Manifest.push(item);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const rng = new SRng(new SRng(baroIndex).randomInt(0, 100_000));
|
||||||
|
// TOVERIFY: Constraint for upgrades amount?
|
||||||
|
// TOVERIFY: Constraint for weapon amount?
|
||||||
|
// TOVERIFY: Constraint for relics amount?
|
||||||
|
let armorSet = rng.randomElement(baro.armorSets)!;
|
||||||
|
if (Array.isArray(armorSet[0])) {
|
||||||
|
armorSet = rng.randomElement(baro.armorSets)!;
|
||||||
|
}
|
||||||
|
while (vt.Manifest.length + armorSet.length < 31) {
|
||||||
|
const item = rng.randomElement(baro.rest)!;
|
||||||
|
if (vt.Manifest.indexOf(item) == -1) {
|
||||||
|
const set = baro.allIfAny.find(set => set.indexOf(item.ItemType) != -1);
|
||||||
|
if (set) {
|
||||||
|
for (const itemType of set) {
|
||||||
|
vt.Manifest.push(baro.rest.find(x => x.ItemType == itemType)!);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vt.Manifest.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const overflow = 31 - (vt.Manifest.length + armorSet.length);
|
||||||
|
if (overflow > 0) {
|
||||||
|
vt.Manifest.splice(0, overflow);
|
||||||
|
}
|
||||||
|
for (const armor of armorSet) {
|
||||||
|
vt.Manifest.push(armor as IVoidTraderOffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const item of baro.evergreen) {
|
||||||
|
vt.Manifest.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Sortie & syndicate missions cycling every day (at 16:00 or 17:00 UTC depending on if London, OT is observing DST)
|
// Sortie & syndicate missions cycling every day (at 16:00 or 17:00 UTC depending on if London, OT is observing DST)
|
||||||
{
|
{
|
||||||
const rollover = getSortieTime(day);
|
const rollover = getSortieTime(day);
|
||||||
@ -1325,6 +1400,17 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
const cheeseInterval = hourInSeconds * 8;
|
const cheeseInterval = hourInSeconds * 8;
|
||||||
const cheeseDuration = hourInSeconds * 2;
|
const cheeseDuration = hourInSeconds * 2;
|
||||||
const cheeseIndex = Math.trunc(timeSecs / cheeseInterval);
|
const cheeseIndex = Math.trunc(timeSecs / cheeseInterval);
|
||||||
|
let cheeseStart = cheeseIndex * cheeseInterval;
|
||||||
|
let cheeseEnd = cheeseStart + cheeseDuration;
|
||||||
|
let cheeseNext = (cheeseIndex + 1) * cheeseInterval;
|
||||||
|
// Live servers only update the start time once it happens, which makes the
|
||||||
|
// client show a negative countdown during off-hours. Optionally adjust the
|
||||||
|
// times so the next activation is always in the future.
|
||||||
|
if (config.unfaithfulBugFixes?.fixXtraCheeseTimer && timeSecs >= cheeseEnd) {
|
||||||
|
cheeseStart = cheeseNext;
|
||||||
|
cheeseEnd = cheeseStart + cheeseDuration;
|
||||||
|
cheeseNext += cheeseInterval;
|
||||||
|
}
|
||||||
const tmp: ITmp = {
|
const tmp: ITmp = {
|
||||||
cavabegin: "1690761600",
|
cavabegin: "1690761600",
|
||||||
PurchasePlatformLockEnabled: true,
|
PurchasePlatformLockEnabled: true,
|
||||||
@ -1349,9 +1435,9 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
ennnd: true,
|
ennnd: true,
|
||||||
mbrt: true,
|
mbrt: true,
|
||||||
fbst: {
|
fbst: {
|
||||||
a: cheeseIndex * cheeseInterval, // This has a bug where the client shows a negative time for "Xtra cheese starts in ..." until it refreshes the world state. This is because we're only providing the new activation as soon as that time/date is reached. However, this is 100% faithful to live.
|
a: cheeseStart,
|
||||||
e: cheeseIndex * cheeseInterval + cheeseDuration,
|
e: cheeseEnd,
|
||||||
n: (cheeseIndex + 1) * cheeseInterval
|
n: cheeseNext
|
||||||
},
|
},
|
||||||
sfn: [550, 553, 554, 555][halfHour % 4]
|
sfn: [550, 553, 554, 555][halfHour % 4]
|
||||||
};
|
};
|
||||||
|
@ -10,14 +10,42 @@ import {
|
|||||||
ICrewMemberClient
|
ICrewMemberClient
|
||||||
} from "./inventoryTypes/inventoryTypes";
|
} from "./inventoryTypes/inventoryTypes";
|
||||||
|
|
||||||
|
export enum PurchaseSource {
|
||||||
|
Market = 0,
|
||||||
|
VoidTrader = 1,
|
||||||
|
SyndicateFavor = 2,
|
||||||
|
DailyDeal = 3,
|
||||||
|
Arsenal = 4,
|
||||||
|
Profile = 5,
|
||||||
|
Hub = 6,
|
||||||
|
Vendor = 7,
|
||||||
|
AppearancePreview = 8,
|
||||||
|
Museum = 9,
|
||||||
|
Operator = 10,
|
||||||
|
PlayerShip = 11,
|
||||||
|
Crewship = 12,
|
||||||
|
MenuStyle = 13,
|
||||||
|
MenuHud = 14,
|
||||||
|
Chat = 15,
|
||||||
|
Inventory = 16,
|
||||||
|
StarChart = 17,
|
||||||
|
PrimeVaultTrader = 18,
|
||||||
|
Incubator = 19,
|
||||||
|
Prompt = 20,
|
||||||
|
Kaithe = 21,
|
||||||
|
DuviriWeapon = 22,
|
||||||
|
UpdateScreen = 23,
|
||||||
|
Motorcycle = 24
|
||||||
|
}
|
||||||
|
|
||||||
export interface IPurchaseRequest {
|
export interface IPurchaseRequest {
|
||||||
PurchaseParams: IPurchaseParams;
|
PurchaseParams: IPurchaseParams;
|
||||||
buildLabel: string;
|
buildLabel: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPurchaseParams {
|
export interface IPurchaseParams {
|
||||||
Source: number;
|
Source: PurchaseSource;
|
||||||
SourceId?: string; // for Source 1, 7 & 18
|
SourceId?: string; // VoidTrader, Vendor, PrimeVaultTrader
|
||||||
StoreItem: string;
|
StoreItem: string;
|
||||||
StorePage: string;
|
StorePage: string;
|
||||||
SearchTerm: string;
|
SearchTerm: string;
|
||||||
@ -25,10 +53,10 @@ export interface IPurchaseParams {
|
|||||||
Quantity: number;
|
Quantity: number;
|
||||||
UsePremium: boolean;
|
UsePremium: boolean;
|
||||||
ExpectedPrice: number;
|
ExpectedPrice: number;
|
||||||
SyndicateTag?: string; // for Source 2
|
SyndicateTag?: string; // SyndicateFavor
|
||||||
UseFreeFavor?: boolean; // for Source 2
|
UseFreeFavor?: boolean; // SyndicateFavor
|
||||||
ExtraPurchaseInfoJson?: string; // for Source 7
|
ExtraPurchaseInfoJson?: string; // Vendor
|
||||||
IsWeekly?: boolean; // for Source 7
|
IsWeekly?: boolean; // Vendor
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IInventoryChanges = {
|
export type IInventoryChanges = {
|
||||||
|
@ -12,6 +12,7 @@ export interface IWorldState {
|
|||||||
ActiveMissions: IFissure[];
|
ActiveMissions: IFissure[];
|
||||||
GlobalUpgrades: IGlobalUpgrade[];
|
GlobalUpgrades: IGlobalUpgrade[];
|
||||||
NodeOverrides: INodeOverride[];
|
NodeOverrides: INodeOverride[];
|
||||||
|
VoidTraders: IVoidTrader[];
|
||||||
VoidStorms: IVoidStorm[];
|
VoidStorms: IVoidStorm[];
|
||||||
PVPChallengeInstances: IPVPChallengeInstance[];
|
PVPChallengeInstances: IPVPChallengeInstance[];
|
||||||
EndlessXpChoices: IEndlessXpChoice[];
|
EndlessXpChoices: IEndlessXpChoice[];
|
||||||
@ -140,6 +141,21 @@ export interface ILiteSortie {
|
|||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IVoidTrader {
|
||||||
|
_id: IOid;
|
||||||
|
Activation: IMongoDate;
|
||||||
|
Expiry: IMongoDate;
|
||||||
|
Character: string;
|
||||||
|
Node: string;
|
||||||
|
Manifest: IVoidTraderOffer[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IVoidTraderOffer {
|
||||||
|
ItemType: string;
|
||||||
|
PrimePrice: number;
|
||||||
|
RegularPrice: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IVoidStorm {
|
export interface IVoidStorm {
|
||||||
_id: IOid;
|
_id: IOid;
|
||||||
Node: string;
|
Node: string;
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"Messages": [
|
|
||||||
{
|
|
||||||
"sub": "Welcome to Space Ninja Server",
|
|
||||||
"sndr": "/Lotus/Language/Bosses/Ordis",
|
|
||||||
"msg": "Enjoy your Space Ninja Experience",
|
|
||||||
"icon": "/Lotus/Interface/Icons/Npcs/Ordis.png",
|
|
||||||
"eventMessageDate": "2025-01-30T13:00:00.000Z",
|
|
||||||
"r": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
413
static/fixed_responses/worldState/baro.json
Normal file
413
static/fixed_responses/worldState/baro.json
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
{
|
||||||
|
"evergreen": [
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Keys/MummyQuestKeyBlueprint", "PrimePrice": 100, "RegularPrice": 25000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Effects/FootstepsMaple", "PrimePrice": 15, "RegularPrice": 1000 }
|
||||||
|
],
|
||||||
|
"armorSets": [
|
||||||
|
[
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/BaroArmour/BaroArmourA", "PrimePrice": 350, "RegularPrice": 110000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/BaroArmour/BaroArmourC", "PrimePrice": 150, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/BaroArmour/BaroArmourL", "PrimePrice": 300, "RegularPrice": 150000 }
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/BaroArmourTwo/BaroArmourTwoA", "PrimePrice": 310, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/BaroArmourTwo/BaroArmourTwoC", "PrimePrice": 175, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/BaroArmourTwo/BaroArmourTwoL", "PrimePrice": 225, "RegularPrice": 150000 }
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/BaroArmourThree/BaroArmourThreeA", "PrimePrice": 400, "RegularPrice": 350000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/BaroArmourThree/BaroArmourThreeC", "PrimePrice": 350, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/BaroArmourThree/BaroArmourThreeL", "PrimePrice": 400, "RegularPrice": 350000 }
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/FurisArmor/PrismaFurisAArmor", "PrimePrice": 300, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/FurisArmor/PrismaFurisCArmor", "PrimePrice": 250, "RegularPrice": 220000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/FurisArmor/PrismaFurisLArmor", "PrimePrice": 225, "RegularPrice": 175000 }
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/GrineerTurbines/WraithTurbinesArmArmor", "PrimePrice": 350, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/GrineerTurbines/WraithTurbinesChestArmor", "PrimePrice": 300, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/GrineerTurbines/WraithTurbinesLegArmor", "PrimePrice": 350, "RegularPrice": 150000 }
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/NecraArmor/NecraArmorA", "PrimePrice": 315, "RegularPrice": 215000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/NecraArmor/NecraArmorC", "PrimePrice": 325, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/NecraArmor/NecraArmorL", "PrimePrice": 300, "RegularPrice": 200000 }
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/SetThreeWinged/VTSetThreeArmLeftArmor", "PrimePrice": 65, "RegularPrice": 75000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/SetThreeWinged/VTSetThreeArmRightArmor", "PrimePrice": 65, "RegularPrice": 75000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/SetThreeWinged/VTSetThreeChestArmor", "PrimePrice": 150, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/SetThreeWinged/VTSetThreeLegLeftArmor", "PrimePrice": 65, "RegularPrice": 75000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/SetThreeWinged/VTSetThreeLegRightArmor", "PrimePrice": 65, "RegularPrice": 75000 }
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/SetTwoSamurai/VTSetTwoArmLeftArmor", "PrimePrice": 100, "RegularPrice": 55000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/SetTwoSamurai/VTSetTwoArmRightArmor", "PrimePrice": 100, "RegularPrice": 55000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/SetTwoSamurai/VTSetTwoChestArmor", "PrimePrice": 225, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/SetTwoSamurai/VTSetTwoLegLeftArmor", "PrimePrice": 100, "RegularPrice": 55000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/SetTwoSamurai/VTSetTwoLegRightArmor", "PrimePrice": 100, "RegularPrice": 55000 }
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/TnLatronArmor/TnLatronArmArmorElixis", "PrimePrice": 325, "RegularPrice": 220000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/TnLatronArmor/TnLatronArmArmorPrisma", "PrimePrice": 325, "RegularPrice": 220000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/TnLatronArmor/TnLatronChestArmorElixis", "PrimePrice": 275, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/TnLatronArmor/TnLatronChestArmorPrisma", "PrimePrice": 275, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/TnLatronArmor/TnLatronLegArmorElixis", "PrimePrice": 300, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/TnLatronArmor/TnLatronLegArmorPrisma", "PrimePrice": 300, "RegularPrice": 175000 }
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/TnShinaiArmor/TnShinaiArmorA", "PrimePrice": 315, "RegularPrice": 125000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/TnShinaiArmor/TnShinaiArmorC", "PrimePrice": 300, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/TnShinaiArmor/TnShinaiArmorL", "PrimePrice": 275, "RegularPrice": 115000 }
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[{ "ItemType": "/Lotus/Types/StoreItems/Packages/VTEosArmourBundle", "PrimePrice": 285, "RegularPrice": 260000 }],
|
||||||
|
[
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/VTEos/VTEosALArmor", "PrimePrice": 50, "RegularPrice": 75000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/VTEos/VTEosARArmor", "PrimePrice": 50, "RegularPrice": 75000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/VTEos/VTEosChestArmor", "PrimePrice": 125, "RegularPrice": 75000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/VTEos/VTEosLLArmor", "PrimePrice": 65, "RegularPrice": 50000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/VTEos/VTEosLRArmor", "PrimePrice": 65, "RegularPrice": 50000 }
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"rest": [
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Armor/Halloween2014Wings/PrismaNaberusArmArmor", "PrimePrice": 220, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/StoreItems/AvatarImages/TennoCon2024GlyphAlt", "PrimePrice": 15, "RegularPrice": 1000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/Emotes/Tennocon2024EmoteAlt", "PrimePrice": 15, "RegularPrice": 1000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/HeartOfDeimosAlbumCoverPoster", "PrimePrice": 80, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/TarotCardTennoConC", "PrimePrice": 75, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/TarotCardTennoConJ", "PrimePrice": 75, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/TarotCardTennoConH", "PrimePrice": 75, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Game/Projections/T3VoidProjectionVoltOdonataPrimeBronze", "PrimePrice": 125, "RegularPrice": 55000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Game/Projections/T4VoidProjectionVoltOdonataPrimeBronze", "PrimePrice": 125, "RegularPrice": 55000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Game/Projections/T4VoidProjectionMagNovaVaultBBronze", "PrimePrice": 125, "RegularPrice": 55000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Scarves/SolsticeNelumboCape", "PrimePrice": 325, "RegularPrice": 275000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/SummerSolstice/SummerSolsticeTwinGrakatas", "PrimePrice": 300, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Weapons/Staff/TnRibbonStaffSkin", "PrimePrice": 350, "RegularPrice": 275000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Grineer/Melee/GunBlade/GrnGunBlade/GrnGunblade", "PrimePrice": 550, "RegularPrice": 325000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Corpus/LongGuns/CrpBFG/Vandal/VandalCrpBFG", "PrimePrice": 650, "RegularPrice": 550000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Pistol/Event/AmbulasEvent/Expert/SecondaryExplosionRadiusModExpert", "PrimePrice": 350, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Clan/Dragon2024BadgeItem", "PrimePrice": 55, "RegularPrice": 45000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Archwing/Rifle/PrimedArchwingDamageOnReloadMod", "PrimePrice": 375, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Archwing/Rifle/PrimedArchwingRifleFireIterationsMod", "PrimePrice": 400, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/StoreItems/AvatarImages/AvatarImageBaruukDoanStyle", "PrimePrice": 75, "RegularPrice": 60000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/OctaviaBobbleHead", "PrimePrice": 50, "RegularPrice": 275000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sentinels/Skins/GaussSentinelSkin", "PrimePrice": 500, "RegularPrice": 425000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sigils/PrismaLotusVinesSigil", "PrimePrice": 55, "RegularPrice": 60000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/StoreItems/AvatarImages/AvatarImageExcaliburActionProto", "PrimePrice": 75, "RegularPrice": 60000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/StoreItems/AvatarImages/AvatarImageIvaraAction", "PrimePrice": 75, "RegularPrice": 60000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Scarves/HornSkullScarf", "PrimePrice": 325, "RegularPrice": 350000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sigils/RhinoDeluxeSigil", "PrimePrice": 45, "RegularPrice": 55000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Events/InfQuantaInfestedAladV", "PrimePrice": 325, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/JavisExperimentsPosterD", "PrimePrice": 90, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/JavisExperimentsPosterB", "PrimePrice": 90, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/JavisExperimentsPosterC", "PrimePrice": 90, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Pistol/Expert/PrimedWeaponElectricityDamageMod", "PrimePrice": 350, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Warframe/Expert/AvatarShieldMaxModExpert", "PrimePrice": 350, "RegularPrice": 225000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/JavisExperimentsPosterA", "PrimePrice": 90, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sigils/EventSigilScarletSpear", "PrimePrice": 45, "RegularPrice": 45000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Grineer/LongGuns/GrnOrokinRifle/GrnOrokinRifleWeapon", "PrimePrice": 675, "RegularPrice": 625000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/VoidTrader/ElixisNikana", "PrimePrice": 375, "RegularPrice": 275000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sentinels/Wings/GaussSentinelWings", "PrimePrice": 400, "RegularPrice": 500000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sentinels/Tails/GaussSentinelTail", "PrimePrice": 400, "RegularPrice": 500000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sentinels/Masks/GaussSentinelMask", "PrimePrice": 450, "RegularPrice": 400000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/LisetPropGrineerCutter", "PrimePrice": 100, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Clan/CNY2023EmblemItem", "PrimePrice": 55, "RegularPrice": 45000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sigils/WeGameNewYearFreeTigerSigil", "PrimePrice": 55, "RegularPrice": 45000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Clan/CNY2022EmblemItem", "PrimePrice": 55, "RegularPrice": 45000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/Leverian/IvaraLeverianPovisRecordsDecoration", "PrimePrice": 75, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Operator/Hoods/HoodDuviriOperator", "PrimePrice": 550, "RegularPrice": 500000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Corpus/Melee/CrpTonfa/CrpPrismaTonfa", "PrimePrice": 450, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/LisetPropCleaningDroneDuviri", "PrimePrice": 800, "RegularPrice": 650000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Operator/Accessories/AshLevarianTiara", "PrimePrice": 550, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Effects/BaroEphemeraB", "PrimePrice": 250, "RegularPrice": 350000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Promo/Warframe/PromoParis", "PrimePrice": 315, "RegularPrice": 275000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sigils/ThraxSigil", "PrimePrice": 50, "RegularPrice": 55000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Corpus/Bow/Longbow/PrismaLenz/PrismaLenzWeapon", "PrimePrice": 575, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/Vignettes/Warframes/ArchwingAFItem", "PrimePrice": 100, "RegularPrice": 330000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Game/QuartersWallpapers/LavosAlchemistWallpaper", "PrimePrice": 275, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/GrendelOrokinDishSet", "PrimePrice": 110, "RegularPrice": 130000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/StoreItems/SuitCustomizations/ColourPickerKiteerItemB", "PrimePrice": 200, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/NezhaEtchingsTablets", "PrimePrice": 100, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/GaussTowerOfAltraDeco", "PrimePrice": 110, "RegularPrice": 125000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/BaroPlanter", "PrimePrice": 125, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/BaroPedestal", "PrimePrice": 150, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Operator/Leggings/LeggingsNovaEngineer", "PrimePrice": 300, "RegularPrice": 275000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Operator/BodySuits/BodySuitNovaEngineer", "PrimePrice": 300, "RegularPrice": 275000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Operator/Sleeves/SleevesNovaEngineer", "PrimePrice": 300, "RegularPrice": 275000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Operator/Hoods/HoodNovaEngineer", "PrimePrice": 350, "RegularPrice": 375000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/BekranZaftBucketBroom", "PrimePrice": 100, "RegularPrice": 125000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Tenno/Melee/Warfan/TnMoonWarfan/MoonWarfanWeapon", "PrimePrice": 410, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/MeleeDangles/MoonWarfanSugatraMeleeDangle", "PrimePrice": 250, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/OstronHeadStatue", "PrimePrice": 125, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/DomsFinalDrink", "PrimePrice": 100, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Wisp/WispAlternateSkin", "PrimePrice": 550, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Pacifist/BaruukImmortalSkin", "PrimePrice": 550, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/ErraBobbleHead", "PrimePrice": 75, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/OwlOrdisStatue", "PrimePrice": 350, "RegularPrice": 275000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/TNWVesoBobbleHead", "PrimePrice": 75, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/TNWTeshinBobbleHead", "PrimePrice": 75, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Peculiars/EvilSpiritMod", "PrimePrice": 250, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Scarves/BaroCape3Scarf", "PrimePrice": 500, "RegularPrice": 500000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/VoidTrader/ElixisTiberon", "PrimePrice": 315, "RegularPrice": 275000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Effects/LotusFlowers", "PrimePrice": 250, "RegularPrice": 450000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/UmbraPedestal", "PrimePrice": 0, "RegularPrice": 1000000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Dragon/ChromaAlternateSkin", "PrimePrice": 550, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Hoverboard/HoverboardStickerBaroB", "PrimePrice": 75, "RegularPrice": 75000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/VoidTrader/ElixisLatronPistol", "PrimePrice": 400, "RegularPrice": 215000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Melee/WeaponGlaiveOnKillBuffSecondary", "PrimePrice": 300, "RegularPrice": 115000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/TarotCardTennoConA", "PrimePrice": 75, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Melee/WeaponGlaiveSecondaryHeadshotKillMod", "PrimePrice": 300, "RegularPrice": 115000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/TarotCardTennoConD", "PrimePrice": 75, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/TarotCardTennoConB", "PrimePrice": 75, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Rifle/Expert/WeaponIncreaseRadialExplosionModExpert", "PrimePrice": 350, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Tenno/Archwing/Primary/ArchwingHeavyPistols/Prisma/PrismaArchHeavyPistols", "PrimePrice": 525, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/StoreItems/AvatarImages/TwinSnakesGlyph", "PrimePrice": 80, "RegularPrice": 50000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/TarotCardTennoConF", "PrimePrice": 75, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/TarotCardTennoConE", "PrimePrice": 75, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Melee/WeaponGlaiveOnSixKillsBuffSecondary", "PrimePrice": 300, "RegularPrice": 115000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sigils/WeGameNewYearOxSigil", "PrimePrice": 55, "RegularPrice": 45000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/TarotCardTennoConG", "PrimePrice": 75, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Shotgun/Expert/WeaponFreezeDamageModExpert", "PrimePrice": 350, "RegularPrice": 125000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/GarvLatroxPoster", "PrimePrice": 80, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Grineer/Melee/GrnBoomerang/HalikarWraithWeapon", "PrimePrice": 450, "RegularPrice": 350000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/TarotCardTennoConI", "PrimePrice": 75, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Shotgun/Expert/WeaponReloadSpeedModExpert", "PrimePrice": 300, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Grineer/Melee/GrineerMachetteAndCleaver/PrismaMachete", "PrimePrice": 400, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/MoaPet/BaroMoaPetSkin", "PrimePrice": 500, "RegularPrice": 325000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/Deimos/PlushySunMonsterCommon", "PrimePrice": 150, "RegularPrice": 125000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/Deimos/PlushyMoonMonsterCommon", "PrimePrice": 150, "RegularPrice": 125000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Rifle/Expert/WeaponClipMaxModExpert", "PrimePrice": 280, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Shotgun/Expert/WeaponClipMaxModExpert", "PrimePrice": 280, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Tenno/Melee/Swords/TnShinaiSword/TnShinaiSwordSkin", "PrimePrice": 375, "RegularPrice": 280000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Weapons/DualSword/DualRibbonKamasSkin", "PrimePrice": 350, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Infestation/NidusAlternateSkin", "PrimePrice": 550, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Game/ActionFigureDioramas/EmpyreanRegionADiorama", "PrimePrice": 155, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/LisetPropGrineerFlak", "PrimePrice": 100, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/LisetPropGrineerTaktis", "PrimePrice": 100, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/VoidTrader/AshLeverianLiosPistol", "PrimePrice": 400, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Glass/GaraAlternateSkin", "PrimePrice": 550, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Rifle/Expert/WeaponSnipersConvertAmmoModExpert", "PrimePrice": 400, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/EraHypnosisPoster", "PrimePrice": 100, "RegularPrice": 110000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Scarves/NezhaLeverianCape", "PrimePrice": 400, "RegularPrice": 350000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Leverian/NezhaLeverian/NezhaLeverianPolearm", "PrimePrice": 350, "RegularPrice": 325000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/BoredTennoPoster", "PrimePrice": 90, "RegularPrice": 120000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/LisetPropCorpusBasilisk", "PrimePrice": 100, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/LisetPropCorpusWeaver", "PrimePrice": 100, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/LisetPropCorpusHarpi", "PrimePrice": 100, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Archwing/GrendelArchwingSkin", "PrimePrice": 400, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Operator/Hoods/JaviExecutionHood", "PrimePrice": 450, "RegularPrice": 450000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Melee/DualStat/ElectEventMeleeMod", "PrimePrice": 300, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Melee/DualStat/FireEventMeleeMod", "PrimePrice": 300, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Tenno/Melee/MeleeTrees/ClawCmbTwoMeleeTree", "PrimePrice": 385, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Rifle/DualStat/FireEventRifleMod", "PrimePrice": 300, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Tenno/Melee/MeleeTrees/AxeCmbThreeMeleeTree", "PrimePrice": 385, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Shotgun/WeaponEventSlashDamageMod", "PrimePrice": 375, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Rifle/BowMultiShotOnHitMod", "PrimePrice": 300, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Shotgun/DualStat/ElectEventShotgunMod", "PrimePrice": 300, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Pistol/DualStat/FireEventPistolMod", "PrimePrice": 300, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Shotgun/DualStat/FireEventShotgunMod", "PrimePrice": 300, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Pistol/WeaponEventPistolImpactDamageMod", "PrimePrice": 300, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Pistol/Expert/PrimedWeaponCritDamageMod", "PrimePrice": 400, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Melee/Expert/WeaponMeleeFactionDamageInfestedExpert", "PrimePrice": 350, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Melee/Expert/WeaponMeleeFactionDamageGrineerExpert", "PrimePrice": 350, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Melee/Expert/WeaponMeleeFactionDamageCorruptedExpert", "PrimePrice": 350, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Melee/Expert/WeaponMeleeFactionDamageCorpusExpert", "PrimePrice": 350, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Pistol/Expert/WeaponClipMaxModExpert", "PrimePrice": 280, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Shotgun/Expert/WeaponShotgunConvertAmmoModExpert", "PrimePrice": 400, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Archwing/Rifle/Expert/ArchwingRifleDamageAmountModExpert", "PrimePrice": 350, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Rifle/Expert/WeaponRifleConvertAmmoModExpert", "PrimePrice": 400, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Sentinels/SentinelPrecepts/PrimedRegen", "PrimePrice": 300, "RegularPrice": 220000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Melee/Expert/WeaponMeleeRangeIncModExpert", "PrimePrice": 300, "RegularPrice": 220000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Shotgun/Expert/WeaponCritDamageModExpert", "PrimePrice": 280, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Pistol/Expert/WeaponReloadSpeedModExpert", "PrimePrice": 375, "RegularPrice": 120000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Melee/Expert/WeaponMeleeDamageModExpert", "PrimePrice": 385, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Shotgun/Expert/WeaponDamageAmountModExpert", "PrimePrice": 300, "RegularPrice": 110000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Pistol/Expert/WeaponCritChanceModBeginnerExpert", "PrimePrice": 400, "RegularPrice": 220000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Pistol/Expert/WeaponPistolConvertAmmoModExpert", "PrimePrice": 400, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Sentinel/Kubrow/Expert/KubrowPackLeaderExpertMod", "PrimePrice": 300, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Archwing/Expert/ArchwingSuitAbilityStrengthModExpert", "PrimePrice": 350, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Melee/Expert/WeaponImpactDamageModExpert", "PrimePrice": 350, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Pistol/Expert/WeaponFireDamageModExpert", "PrimePrice": 350, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Warframe/Expert/AvatarPowerMaxModExpert", "PrimePrice": 350, "RegularPrice": 110000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Melee/Expert/WeaponToxinDamageModExpert", "PrimePrice": 350, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Rifle/Expert/WeaponReloadSpeedModExpert", "PrimePrice": 375, "RegularPrice": 120000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Pistol/Expert/WeaponPistolFactionDamageInfestedExpert", "PrimePrice": 350, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Pistol/Expert/WeaponPistolFactionDamageGrineerExpert", "PrimePrice": 350, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Pistol/Expert/WeaponPistolFactionDamageCorruptedExpert", "PrimePrice": 350, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Pistol/Expert/WeaponPistolFactionDamageCorpusExpert", "PrimePrice": 350, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Rifle/Expert/WeaponFreezeDamageModExpert", "PrimePrice": 350, "RegularPrice": 110000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Warframe/Expert/AvatarAbilityDurationModExpert", "PrimePrice": 350, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Shotgun/Expert/WeaponShotgunFactionDamageInfestedExpert", "PrimePrice": 350, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Shotgun/Expert/WeaponShotgunFactionDamageGrineerExpert", "PrimePrice": 350, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Shotgun/Expert/WeaponShotgunFactionDamageCorruptedExpert", "PrimePrice": 350, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Shotgun/Expert/WeaponShotgunFactionDamageCorpusExpert", "PrimePrice": 350, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Shotgun/Expert/WeaponElectricityDamageModExpert", "PrimePrice": 350, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Rifle/Expert/PrimedWeaponFactionDamageInfested", "PrimePrice": 400, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Rifle/Expert/PrimedWeaponFactionDamageGrineer", "PrimePrice": 400, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Rifle/Expert/PrimedWeaponFactionDamageCorrupted", "PrimePrice": 400, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Rifle/Expert/PrimedWeaponFactionDamageCorpus", "PrimePrice": 400, "RegularPrice": 140000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Sentinel/SentinelLootRadarEnemyRadarExpertMod", "PrimePrice": 300, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Tenno/Melee/MeleeTrees/GlaiveCmbTwoMeleeTree", "PrimePrice": 385, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Melee/WeaponEventSlashDamageMod", "PrimePrice": 375, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Melee/WeaponEventMeleeImpactDamageMod", "PrimePrice": 400, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Rifle/WeaponEventRifleImpactDamageMod", "PrimePrice": 330, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Rifle/WeaponEventSlashDamageMod", "PrimePrice": 375, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Shotgun/WeaponEventShotgunImpactDamageMod", "PrimePrice": 365, "RegularPrice": 220000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Rifle/DualStat/ElectEventRifleMod", "PrimePrice": 300, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Pistol/DualStat/ElectEventPistolMod", "PrimePrice": 300, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Pistol/WeaponEventSlashDamageMod", "PrimePrice": 375, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/VoidTrader/VTDetron", "PrimePrice": 500, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Corpus/LongGuns/CrpFreezeRay/Vandal/CrpFreezeRayVandalRifle", "PrimePrice": 475, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/ClanTech/Chemical/FlameThrowerWraith", "PrimePrice": 550, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Grineer/Melee/GrineerMachetteAndCleaver/WraithMacheteWeapon", "PrimePrice": 410, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Corpus/Pistols/CrpHandRL/PrismaAngstrum", "PrimePrice": 475, "RegularPrice": 210000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Grineer/Melee/GrineerMachetteAndCleaver/PrismaDualCleavers", "PrimePrice": 490, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Grineer/LongGuns/VoidTraderGorgon/VTGorgon", "PrimePrice": 600, "RegularPrice": 50000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/VoidTrader/PrismaGrakata", "PrimePrice": 610, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Grineer/LongGuns/GrineerLeverActionRifle/PrismaGrinlokWeapon", "PrimePrice": 500, "RegularPrice": 220000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Corpus/Melee/KickAndPunch/PrismaObex", "PrimePrice": 500, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/VoidTrader/PrismaSkana", "PrimePrice": 510, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Corpus/LongGuns/CorpusUMP/PrismaCorpusUMP", "PrimePrice": 400, "RegularPrice": 50000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Grineer/Pistols/GrineerBulbousSMG/Prisma/PrismaTwinGremlinsWeapon", "PrimePrice": 500, "RegularPrice": 220000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Tenno/Archwing/Melee/VoidTraderArchsword/VTArchSwordWeapon", "PrimePrice": 550, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/ClanTech/Energy/VandalElectroProd", "PrimePrice": 410, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Corpus/LongGuns/CrpShockRifle/QuantaVandal", "PrimePrice": 450, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Corpus/LongGuns/Machinegun/SupraVandal", "PrimePrice": 500, "RegularPrice": 275000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Grineer/Pistols/WraithSingleViper/WraithSingleViper", "PrimePrice": 400, "RegularPrice": 75000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Grineer/LongGuns/GrineerSniperRifle/VulkarWraith", "PrimePrice": 450, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Weapons/Tenno/Pistols/ConclaveLeverPistol/ConclaveLeverPistol", "PrimePrice": 500, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/MeleeDangles/FireMeleeDangle", "PrimePrice": 100, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/VoidTrader/BaroInarosPolearmSkin", "PrimePrice": 325, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/MeleeDangles/BaroInarosMeleeDangle", "PrimePrice": 250, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/MeleeDangles/InfestedMeleeDangle", "PrimePrice": 250, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/VoidTrader/VTHalloweenDarkSword", "PrimePrice": 320, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/SummerSolstice/SummerSolsticeGorgon", "PrimePrice": 300, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/SummerSolstice/SummerIgnisSkin", "PrimePrice": 300, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/VoidTrader/BaroArrow", "PrimePrice": 375, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/MeleeDangles/BaroMeleeDangle", "PrimePrice": 250, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/VoidTrader/BaroScytheMacheteSkin", "PrimePrice": 375, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/VoidTrader/ElixisOdonataSkin", "PrimePrice": 350, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/VoidTrader/ElixisBallasSword", "PrimePrice": 350, "RegularPrice": 350000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/VoidTrader/PrismaArrow", "PrimePrice": 350, "RegularPrice": 75000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/VoidTrader/VTRedeemerSkin", "PrimePrice": 325, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/VoidTrader/ElixisSonicor", "PrimePrice": 380, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/VoidTrader/ElixisTigris", "PrimePrice": 300, "RegularPrice": 275000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/VoidTrader/VTQuanta", "PrimePrice": 300, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/VoidTrader/ElixisOpticor", "PrimePrice": 325, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Halloween/HalloweenDread", "PrimePrice": 300, "RegularPrice": 275000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/StoreItems/AvatarImages/ImageBaroKiteer", "PrimePrice": 80, "RegularPrice": 50000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/StoreItems/AvatarImages/Seasonal/AvatarImageGlyphCookieKavat", "PrimePrice": 80, "RegularPrice": 50000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/StoreItems/AvatarImages/Seasonal/AvatarImageGlyphCookieKubrow", "PrimePrice": 80, "RegularPrice": 50000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Scarves/LisetScarf", "PrimePrice": 600, "RegularPrice": 400000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/StoreItems/SuitCustomizations/ColourPickerTwitchBItemA", "PrimePrice": 220, "RegularPrice": 220000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Effects/FootstepsMaple", "PrimePrice": 15, "RegularPrice": 1000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Clan/BaroKavatBadgeItem", "PrimePrice": 50, "RegularPrice": 50000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sigils/BaroKavatSigil", "PrimePrice": 55, "RegularPrice": 45000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Scarves/WraithTurbinesScarf", "PrimePrice": 400, "RegularPrice": 500000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Pirate/HydroidAlternateSkin", "PrimePrice": 550, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/StoreItems/AvatarImages/Seasonal/Halloween2019GrendelTreat", "PrimePrice": 80, "RegularPrice": 50000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/StoreItems/SuitCustomizations/ColourPickerKiteerItemA", "PrimePrice": 150, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Scarves/KazBaroCape", "PrimePrice": 325, "RegularPrice": 450000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Effects/BaroEphemeraA", "PrimePrice": 100, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Scarves/BaroCape2Scarf", "PrimePrice": 400, "RegularPrice": 350000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Clan/BaroQuantumBadgeItem", "PrimePrice": 400, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Scarves/SolsticeBaroCape", "PrimePrice": 425, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Scarves/BaroCape", "PrimePrice": 500, "RegularPrice": 500000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/StoreItems/AvatarImages/AvatarImageBaroIcon", "PrimePrice": 80, "RegularPrice": 50000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Magician/LimboImmortalSkin", "PrimePrice": 550, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Cowgirl/MesaImmortallSkin", "PrimePrice": 550, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Harlequin/MirageAlternateSkin", "PrimePrice": 550, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Clan/BaroKubrowBadgeItem", "PrimePrice": 50, "RegularPrice": 50000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sigils/BaroKubrowSigil", "PrimePrice": 55, "RegularPrice": 45000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Scarves/VTHornSkullScarf", "PrimePrice": 250, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Clan/PrismaLotusEmblem", "PrimePrice": 80, "RegularPrice": 50000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/StoreItems/AvatarImages/AvatarImageBaroTwoIcon", "PrimePrice": 80, "RegularPrice": 50000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sigils/PrismaLotusSigil", "PrimePrice": 55, "RegularPrice": 45000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sigils/PrimeTraderSigil", "PrimePrice": 50, "RegularPrice": 50000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Scarves/PrismaRazorScarf", "PrimePrice": 350, "RegularPrice": 275000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Scarves/VTDinoSpikeScarf", "PrimePrice": 400, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/StoreItems/AvatarImages/AvatarImageLowPolyKavat", "PrimePrice": 80, "RegularPrice": 50000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/StoreItems/AvatarImages/AvatarImageLowPolyKubrow", "PrimePrice": 80, "RegularPrice": 50000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Tengu/ZephyrAlternateSkin", "PrimePrice": 550, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Game/KubrowPet/Patterns/KubrowPetPatternPrimeTraderA", "PrimePrice": 150, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Camo/DesertDirigaSkin", "PrimePrice": 225, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sentinels/Masks/KavatPetMask", "PrimePrice": 500, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sentinels/Tails/KavatPetTail", "PrimePrice": 400, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sentinels/Wings/KavatPetWings", "PrimePrice": 400, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Catbrows/Armor/CatbrowArmorVoidTraderA", "PrimePrice": 500, "RegularPrice": 275000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Kubrows/Armor/KubrowArmorBaro", "PrimePrice": 500, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sentinels/Masks/BaroPetMask", "PrimePrice": 500, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sentinels/Tails/BaroPetTail", "PrimePrice": 400, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sentinels/Wings/BaroPetWings", "PrimePrice": 400, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/Types/StoreItems/Packages/KavatColorPackNexus", "PrimePrice": 200, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sentinels/Wings/PrismaJetWings", "PrimePrice": 300, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sentinels/Tails/PrismaFishTail", "PrimePrice": 200, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sentinels/Masks/PrismaMechHeadMask", "PrimePrice": 175, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Kubrows/Armor/KubrowArmorPrisma", "PrimePrice": 400, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Sentinels/SentinelPowersuits/PrismaShadePowerSuit", "PrimePrice": 500, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Sentinels/Skins/DesertTaxonSkin", "PrimePrice": 200, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Catbrows/Armor/CatbrowArmorHalloweenA", "PrimePrice": 400, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/Types/StoreItems/Boosters/AffinityBooster3DayStoreItem", "PrimePrice": 450, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/Types/StoreItems/Boosters/CreditBooster3DayStoreItem", "PrimePrice": 350, "RegularPrice": 75000 },
|
||||||
|
{ "ItemType": "/Lotus/Types/StoreItems/Boosters/ModDropChanceBooster3DayStoreItem", "PrimePrice": 500, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/Types/StoreItems/Boosters/ResourceAmount3DayStoreItem", "PrimePrice": 400, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Game/Projections/T4VoidProjectionPBronze", "PrimePrice": 50, "RegularPrice": 45000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Recipes/Components/CorruptedBombardBallBlueprint", "PrimePrice": 100, "RegularPrice": 50000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Restoratives/Consumable/CorruptedHeavyGunnerBall", "PrimePrice": 100, "RegularPrice": 40000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/OrbiterPictureFrameBaro", "PrimePrice": 100, "RegularPrice": 75000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Restoratives/Consumable/AssassinBaitC", "PrimePrice": 200, "RegularPrice": 125000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/MiscItems/PhotoboothTileInarosTomb", "PrimePrice": 325, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Restoratives/Consumable/BaroFireWorksCrate", "PrimePrice": 50, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/MiscItems/PhotoboothTileOrokinExtraction", "PrimePrice": 325, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Keys/MummyQuestKeyBlueprint", "PrimePrice": 100, "RegularPrice": 25000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Restoratives/Consumable/AssassinBait", "PrimePrice": 200, "RegularPrice": 125000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Restoratives/Consumable/AssassinBaitB", "PrimePrice": 200, "RegularPrice": 125000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/BaroKiTeerDecorationB", "PrimePrice": 100, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/BaroKiTeerDecorationE", "PrimePrice": 100, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/LisetPropCleaningDroneBaro", "PrimePrice": 700, "RegularPrice": 500000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/BaroKiTeerBobbleHead", "PrimePrice": 70, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Hoverboard/HoverboardStickerBaroA", "PrimePrice": 75, "RegularPrice": 75000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/KavatBust", "PrimePrice": 220, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/KubrowBust", "PrimePrice": 220, "RegularPrice": 250000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyDesertSkate", "PrimePrice": 125, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/BaroKiTeerDecorationD", "PrimePrice": 100, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/ExcaliburArchwingBobbleHead", "PrimePrice": 90, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Operator/Accessories/BaroTiara", "PrimePrice": 525, "RegularPrice": 375000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Operator/Accessories/EarpieceBaroC", "PrimePrice": 500, "RegularPrice": 400000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Operator/Accessories/BaroMouthPieceA", "PrimePrice": 500, "RegularPrice": 400000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Operator/Accessories/BaroVisor", "PrimePrice": 525, "RegularPrice": 375000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Operator/Accessories/BaroHorn", "PrimePrice": 525, "RegularPrice": 375000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Operator/Accessories/EarpieceBaroA", "PrimePrice": 500, "RegularPrice": 400000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Operator/Accessories/EarpieceBaroB", "PrimePrice": 250, "RegularPrice": 200000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Game/QuartersWallpapers/BaroWallpaper", "PrimePrice": 250, "RegularPrice": 175000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Liset/InarosLisetSkin", "PrimePrice": 400, "RegularPrice": 300000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/BaroKiTeerDecorationA", "PrimePrice": 100, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Liset/LisetInsectSkinInaros", "PrimePrice": 425, "RegularPrice": 320000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Liset/LisetInsectSkinPrimeTrader", "PrimePrice": 230, "RegularPrice": 375000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/ParazonPoster", "PrimePrice": 100, "RegularPrice": 125000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/KubrowKavatLowPolyPoster", "PrimePrice": 90, "RegularPrice": 110000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Liset/LisetSkinVoidTrader", "PrimePrice": 120, "RegularPrice": 150000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Liset/LisetBlueSkySkinPrimeTrader", "PrimePrice": 210, "RegularPrice": 450000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/BaroKiTeerDecorationF", "PrimePrice": 100, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Liset/LisetBlueSkySkinInaros", "PrimePrice": 375, "RegularPrice": 340000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/BaroKiTeerDecorationG", "PrimePrice": 100, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/LisetPropOstRugBaro", "PrimePrice": 225, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/BaroKiTeerDecorationH", "PrimePrice": 100, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Skins/Liset/Gyroscope/LisetGyroscopeSkinPrimeTrader", "PrimePrice": 220, "RegularPrice": 400000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/BaroKiTeerDecorationC", "PrimePrice": 100, "RegularPrice": 100000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/ShipDecos/PedistalPrime", "PrimePrice": 0, "RegularPrice": 1000000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Types/Items/Emotes/BaroEmote", "PrimePrice": 0, "RegularPrice": 1000000 },
|
||||||
|
{ "ItemType": "/Lotus/StoreItems/Upgrades/Mods/Rifle/EventSniperReloadDamageMod", "PrimePrice": 2995, "RegularPrice": 1000000 }
|
||||||
|
],
|
||||||
|
"allIfAny": [
|
||||||
|
[
|
||||||
|
"/Lotus/StoreItems/Upgrades/Skins/Operator/Leggings/LeggingsNovaEngineer",
|
||||||
|
"/Lotus/StoreItems/Upgrades/Skins/Operator/BodySuits/BodySuitNovaEngineer",
|
||||||
|
"/Lotus/StoreItems/Upgrades/Skins/Operator/Sleeves/SleevesNovaEngineer",
|
||||||
|
"/Lotus/StoreItems/Upgrades/Skins/Operator/Hoods/HoodNovaEngineer"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -452,9 +452,6 @@
|
|||||||
<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>
|
<button class="btn btn-success" onclick="maxRankAllEvolutions();" data-loc="inventory_bulkRankUpEvolutionProgress"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-2 d-flex flex-wrap gap-2">
|
|
||||||
<button class="btn btn-primary" onclick="debounce(doMaxPlexus);" data-loc="inventory_maxPlexus"></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -587,10 +584,6 @@
|
|||||||
<input class="form-check-input" type="checkbox" id="unlockAllScans" />
|
<input class="form-check-input" type="checkbox" id="unlockAllScans" />
|
||||||
<label class="form-check-label" for="unlockAllScans" data-loc="cheats_unlockAllScans"></label>
|
<label class="form-check-label" for="unlockAllScans" data-loc="cheats_unlockAllScans"></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input" type="checkbox" id="unlockAllMissions" />
|
|
||||||
<label class="form-check-label" for="unlockAllMissions" data-loc="cheats_unlockAllMissions"></label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="checkbox" id="infiniteCredits" />
|
<input class="form-check-input" type="checkbox" id="infiniteCredits" />
|
||||||
<label class="form-check-label" for="infiniteCredits" data-loc="cheats_infiniteCredits"></label>
|
<label class="form-check-label" for="infiniteCredits" data-loc="cheats_infiniteCredits"></label>
|
||||||
@ -707,6 +700,18 @@
|
|||||||
<input class="form-check-input" type="checkbox" id="noKimCooldowns" />
|
<input class="form-check-input" type="checkbox" id="noKimCooldowns" />
|
||||||
<label class="form-check-label" for="noKimCooldowns" data-loc="cheats_noKimCooldowns"></label>
|
<label class="form-check-label" for="noKimCooldowns" data-loc="cheats_noKimCooldowns"></label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="fullyStockedVendors" />
|
||||||
|
<label class="form-check-label" for="fullyStockedVendors" data-loc="cheats_fullyStockedVendors"></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="baroAlwaysAvailable" />
|
||||||
|
<label class="form-check-label" for="baroAlwaysAvailable" data-loc="cheats_baroAlwaysAvailable"></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="baroFullyStocked" />
|
||||||
|
<label class="form-check-label" for="baroFullyStocked" data-loc="cheats_baroFullyStocked"></label>
|
||||||
|
</div>
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="checkbox" id="syndicateMissionsRepeatable" />
|
<input class="form-check-input" type="checkbox" id="syndicateMissionsRepeatable" />
|
||||||
<label class="form-check-label" for="syndicateMissionsRepeatable" data-loc="cheats_syndicateMissionsRepeatable"></label>
|
<label class="form-check-label" for="syndicateMissionsRepeatable" data-loc="cheats_syndicateMissionsRepeatable"></label>
|
||||||
@ -759,6 +764,10 @@
|
|||||||
<input class="form-check-input" type="checkbox" id="missionsCanGiveAllRelics" />
|
<input class="form-check-input" type="checkbox" id="missionsCanGiveAllRelics" />
|
||||||
<label class="form-check-label" for="missionsCanGiveAllRelics" data-loc="cheats_missionsCanGiveAllRelics"></label>
|
<label class="form-check-label" for="missionsCanGiveAllRelics" data-loc="cheats_missionsCanGiveAllRelics"></label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="unlockAllSimarisResearchEntries" />
|
||||||
|
<label class="form-check-label" for="unlockAllSimarisResearchEntries" data-loc="cheats_unlockAllSimarisResearchEntries"></label>
|
||||||
|
</div>
|
||||||
<form class="form-group mt-2" onsubmit="doSaveConfig('spoofMasteryRank'); return false;">
|
<form class="form-group mt-2" onsubmit="doSaveConfig('spoofMasteryRank'); return false;">
|
||||||
<label class="form-label" for="spoofMasteryRank" data-loc="cheats_spoofMasteryRank"></label>
|
<label class="form-label" for="spoofMasteryRank" data-loc="cheats_spoofMasteryRank"></label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
@ -782,9 +791,11 @@
|
|||||||
<h5 class="card-header" data-loc="cheats_account"></h5>
|
<h5 class="card-header" data-loc="cheats_account"></h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="mb-2 d-flex flex-wrap gap-2">
|
<div class="mb-2 d-flex flex-wrap gap-2">
|
||||||
|
<button class="btn btn-primary" onclick="debounce(doUnlockAllMissions);" data-loc="cheats_unlockAllMissions"></button>
|
||||||
<button class="btn btn-primary" onclick="doUnlockAllFocusSchools();" data-loc="cheats_unlockAllFocusSchools"></button>
|
<button class="btn btn-primary" onclick="doUnlockAllFocusSchools();" data-loc="cheats_unlockAllFocusSchools"></button>
|
||||||
<button class="btn btn-primary" onclick="doHelminthUnlockAll();" data-loc="cheats_helminthUnlockAll"></button>
|
<button class="btn btn-primary" onclick="doHelminthUnlockAll();" data-loc="cheats_helminthUnlockAll"></button>
|
||||||
<button class="btn btn-primary" onclick="doIntrinsicsUnlockAll();" data-loc="cheats_intrinsicsUnlockAll"></button>
|
<button class="btn btn-primary" onclick="doIntrinsicsUnlockAll();" data-loc="cheats_intrinsicsUnlockAll"></button>
|
||||||
|
<button class="btn btn-primary" onclick="debounce(doMaxPlexus);" data-loc="inventory_maxPlexus"></button>
|
||||||
</div>
|
</div>
|
||||||
<form class="mt-2" onsubmit="doChangeSupportedSyndicate(); return false;">
|
<form class="mt-2" onsubmit="doChangeSupportedSyndicate(); return false;">
|
||||||
<label class="form-label" for="changeSyndicate" data-loc="cheats_changeSupportedSyndicate"></label>
|
<label class="form-label" for="changeSyndicate" data-loc="cheats_changeSupportedSyndicate"></label>
|
||||||
@ -800,8 +811,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div data-route="/webui/import" data-title="Import | OpenWF WebUI">
|
<div data-route="/webui/import" data-title="Import | OpenWF WebUI">
|
||||||
<p data-loc="import_importNote"></p>
|
<p data-loc="import_importNote"></p>
|
||||||
<textarea class="form-control" id="import-inventory"></textarea>
|
<textarea class="form-control" id="import-inventory" style="height: calc(100vh - 300px)"></textarea>
|
||||||
<button class="btn btn-primary mt-3" onclick="doImport();" data-loc="import_submit"></button>
|
<button class="btn btn-primary mt-3" onclick="doImport();" data-loc="import_submit"></button>
|
||||||
|
<p class="mt-3 mb-1" data-loc="import_samples"></p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#" onclick="event.preventDefault();setImportSample('maxFocus');" data-loc="import_samples_maxFocus"></a></li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="toast-container position-fixed bottom-0 end-0 p-3"></div>
|
<div class="toast-container position-fixed bottom-0 end-0 p-3"></div>
|
||||||
|
@ -79,6 +79,9 @@ function openWebSocket() {
|
|||||||
if ("logged_out" in msg) {
|
if ("logged_out" in msg) {
|
||||||
sendAuth();
|
sendAuth();
|
||||||
}
|
}
|
||||||
|
if ("update_inventory" in msg) {
|
||||||
|
updateInventory();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
window.ws.onclose = function () {
|
window.ws.onclose = function () {
|
||||||
ws_is_open = false;
|
ws_is_open = false;
|
||||||
@ -111,11 +114,9 @@ function doLogin() {
|
|||||||
window.registerSubmit = false;
|
window.registerSubmit = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function revalidateAuthz(succ_cb) {
|
async function revalidateAuthz() {
|
||||||
getWebSocket().then(() => {
|
await getWebSocket();
|
||||||
// We have a websocket connection, so authz should be good.
|
// We have a websocket connection, so authz should be good.
|
||||||
succ_cb();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
@ -135,7 +136,7 @@ function doLogout() {
|
|||||||
function renameAccount() {
|
function renameAccount() {
|
||||||
const newname = window.prompt(loc("code_changeNameConfirm"));
|
const newname = window.prompt(loc("code_changeNameConfirm"));
|
||||||
if (newname) {
|
if (newname) {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
fetch("/custom/renameAccount?" + window.authz + "&newname=" + newname).then(() => {
|
fetch("/custom/renameAccount?" + window.authz + "&newname=" + newname).then(() => {
|
||||||
$(".displayname").text(newname);
|
$(".displayname").text(newname);
|
||||||
updateLocElements();
|
updateLocElements();
|
||||||
@ -146,7 +147,7 @@ function renameAccount() {
|
|||||||
|
|
||||||
function deleteAccount() {
|
function deleteAccount() {
|
||||||
if (window.confirm(loc("code_deleteAccountConfirm"))) {
|
if (window.confirm(loc("code_deleteAccountConfirm"))) {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
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
|
||||||
@ -646,7 +647,7 @@ function updateInventory() {
|
|||||||
a.href = "#";
|
a.href = "#";
|
||||||
a.onclick = function (event) {
|
a.onclick = function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
if (item.XP < maxXP) {
|
if (item.XP < maxXP) {
|
||||||
promises.push(addGearExp(category, item.ItemId.$oid, maxXP - item.XP));
|
promises.push(addGearExp(category, item.ItemId.$oid, maxXP - item.XP));
|
||||||
@ -1236,7 +1237,7 @@ function doAcquireEquipment(category) {
|
|||||||
.focus();
|
.focus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
const req = $.post({
|
const req = $.post({
|
||||||
url: "/custom/addItems?" + window.authz,
|
url: "/custom/addItems?" + window.authz,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
@ -1363,7 +1364,7 @@ function doAcquireModularEquipment(category, WeaponType) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (category == "KubrowPets") Parts.unshift(WeaponType);
|
if (category == "KubrowPets") Parts.unshift(WeaponType);
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
const req = $.post({
|
const req = $.post({
|
||||||
url: "/api/modularWeaponCrafting.php?" + window.authz,
|
url: "/api/modularWeaponCrafting.php?" + window.authz,
|
||||||
contentType: "application/octet-stream",
|
contentType: "application/octet-stream",
|
||||||
@ -1416,7 +1417,7 @@ $("input[list]").on("input", function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function dispatchAddItemsRequestsBatch(requests) {
|
function dispatchAddItemsRequestsBatch(requests) {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
const req = $.post({
|
const req = $.post({
|
||||||
url: "/custom/addItems?" + window.authz,
|
url: "/custom/addItems?" + window.authz,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
@ -1460,7 +1461,7 @@ function addMissingEvolutionProgress() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function maxRankAllEvolutions() {
|
function maxRankAllEvolutions() {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
|
const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
|
||||||
req.done(data => {
|
req.done(data => {
|
||||||
const requests = [];
|
const requests = [];
|
||||||
@ -1484,7 +1485,7 @@ function maxRankAllEvolutions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function maxRankAllEquipment(categories) {
|
function maxRankAllEquipment(categories) {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
|
const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
|
||||||
req.done(data => {
|
req.done(data => {
|
||||||
window.itemListPromise.then(itemMap => {
|
window.itemListPromise.then(itemMap => {
|
||||||
@ -1558,7 +1559,7 @@ function addGearExp(category, oid, xp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function sendBatchGearExp(data) {
|
function sendBatchGearExp(data) {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.post({
|
$.post({
|
||||||
url: "/custom/addXp?" + window.authz,
|
url: "/custom/addXp?" + window.authz,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
@ -1571,7 +1572,7 @@ function sendBatchGearExp(data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renameGear(category, oid, name) {
|
function renameGear(category, oid, name) {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
if (category == "KubrowPets") {
|
if (category == "KubrowPets") {
|
||||||
$.post({
|
$.post({
|
||||||
url: "/api/renamePet.php?" + window.authz + "&webui=1",
|
url: "/api/renamePet.php?" + window.authz + "&webui=1",
|
||||||
@ -1599,7 +1600,7 @@ function renameGear(category, oid, name) {
|
|||||||
|
|
||||||
function disposeOfGear(category, oid) {
|
function disposeOfGear(category, oid) {
|
||||||
if (category == "KubrowPets") {
|
if (category == "KubrowPets") {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.post({
|
$.post({
|
||||||
url: "/api/releasePet.php?" + window.authz,
|
url: "/api/releasePet.php?" + window.authz,
|
||||||
contentType: "application/octet-stream",
|
contentType: "application/octet-stream",
|
||||||
@ -1621,7 +1622,7 @@ function disposeOfGear(category, oid) {
|
|||||||
Count: 0
|
Count: 0
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.post({
|
$.post({
|
||||||
url: "/api/sell.php?" + window.authz,
|
url: "/api/sell.php?" + window.authz,
|
||||||
contentType: "text/plain",
|
contentType: "text/plain",
|
||||||
@ -1643,7 +1644,7 @@ function disposeOfItems(category, type, count) {
|
|||||||
Count: count
|
Count: count
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.post({
|
$.post({
|
||||||
url: "/api/sell.php?" + window.authz,
|
url: "/api/sell.php?" + window.authz,
|
||||||
contentType: "text/plain",
|
contentType: "text/plain",
|
||||||
@ -1653,7 +1654,7 @@ function disposeOfItems(category, type, count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function gildEquipment(category, oid) {
|
function gildEquipment(category, oid) {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.post({
|
$.post({
|
||||||
url: "/api/gildWeapon.php?" + window.authz + "&ItemId=" + oid + "&Category=" + category,
|
url: "/api/gildWeapon.php?" + window.authz + "&ItemId=" + oid + "&Category=" + category,
|
||||||
contentType: "application/octet-stream",
|
contentType: "application/octet-stream",
|
||||||
@ -1667,7 +1668,7 @@ function gildEquipment(category, oid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function maturePet(oid, revert) {
|
function maturePet(oid, revert) {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.post({
|
$.post({
|
||||||
url: "/api/maturePet.php?" + window.authz,
|
url: "/api/maturePet.php?" + window.authz,
|
||||||
contentType: "application/octet-stream",
|
contentType: "application/octet-stream",
|
||||||
@ -1682,7 +1683,7 @@ function maturePet(oid, revert) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setEvolutionProgress(requests) {
|
function setEvolutionProgress(requests) {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
const req = $.post({
|
const req = $.post({
|
||||||
url: "/custom/setEvolutionProgress?" + window.authz,
|
url: "/custom/setEvolutionProgress?" + window.authz,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
@ -1702,7 +1703,7 @@ function doAcquireMiscItems() {
|
|||||||
}
|
}
|
||||||
const count = parseInt($("#miscitem-count").val());
|
const count = parseInt($("#miscitem-count").val());
|
||||||
if (count != 0) {
|
if (count != 0) {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.post({
|
$.post({
|
||||||
url: "/custom/addItems?" + window.authz,
|
url: "/custom/addItems?" + window.authz,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
@ -1743,7 +1744,7 @@ function doAcquireRiven() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const uniqueName = "/Lotus/Upgrades/Mods/Randomized/" + $("#addriven-type").val();
|
const uniqueName = "/Lotus/Upgrades/Mods/Randomized/" + $("#addriven-type").val();
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
// Add riven type to inventory
|
// Add riven type to inventory
|
||||||
$.post({
|
$.post({
|
||||||
url: "/custom/addItems?" + window.authz,
|
url: "/custom/addItems?" + window.authz,
|
||||||
@ -1790,7 +1791,7 @@ $("#addriven-fingerprint").on("input", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function setFingerprint(ItemType, ItemId, fingerprint) {
|
function setFingerprint(ItemType, ItemId, fingerprint) {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.post({
|
$.post({
|
||||||
url: "/api/artifacts.php?" + window.authz,
|
url: "/api/artifacts.php?" + window.authz,
|
||||||
contentType: "text/plain",
|
contentType: "text/plain",
|
||||||
@ -1818,7 +1819,7 @@ function doAcquireMod() {
|
|||||||
}
|
}
|
||||||
const count = parseInt($("#mod-count").val());
|
const count = parseInt($("#mod-count").val());
|
||||||
if (count != 0) {
|
if (count != 0) {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.post({
|
$.post({
|
||||||
url: "/custom/addItems?" + window.authz,
|
url: "/custom/addItems?" + window.authz,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
@ -1895,7 +1896,7 @@ single.getRoute("/webui/cheats").on("beforeload", function () {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if ((await res.text()) == "Log-in expired") {
|
if ((await res.text()) == "Log-in expired") {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
if (single.getCurrentPath() == "/webui/cheats") {
|
if (single.getCurrentPath() == "/webui/cheats") {
|
||||||
single.loadRoute("/webui/cheats");
|
single.loadRoute("/webui/cheats");
|
||||||
}
|
}
|
||||||
@ -1912,7 +1913,7 @@ single.getRoute("/webui/cheats").on("beforeload", function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function doUnlockAllFocusSchools() {
|
function doUnlockAllFocusSchools() {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1").done(async data => {
|
$.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1").done(async data => {
|
||||||
const missingFocusUpgrades = {
|
const missingFocusUpgrades = {
|
||||||
"/Lotus/Upgrades/Focus/Attack/AttackFocusAbility": true,
|
"/Lotus/Upgrades/Focus/Attack/AttackFocusAbility": true,
|
||||||
@ -1963,13 +1964,13 @@ function unlockFocusSchool(upgradeType) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function doHelminthUnlockAll() {
|
function doHelminthUnlockAll() {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.post("/api/infestedFoundry.php?" + window.authz + "&mode=custom_unlockall");
|
$.post("/api/infestedFoundry.php?" + window.authz + "&mode=custom_unlockall");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function doIntrinsicsUnlockAll() {
|
function doIntrinsicsUnlockAll() {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.get("/custom/unlockAllIntrinsics?" + window.authz);
|
$.get("/custom/unlockAllIntrinsics?" + window.authz);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1981,7 +1982,7 @@ function doAddAllMods() {
|
|||||||
}
|
}
|
||||||
modsAll.delete("/Lotus/Upgrades/Mods/Fusers/LegendaryModFuser");
|
modsAll.delete("/Lotus/Upgrades/Mods/Fusers/LegendaryModFuser");
|
||||||
|
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
|
const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
|
||||||
req.done(data => {
|
req.done(data => {
|
||||||
for (const modOwned of data.RawUpgrades) {
|
for (const modOwned of data.RawUpgrades) {
|
||||||
@ -2013,7 +2014,7 @@ function doAddAllMods() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function doRemoveUnrankedMods() {
|
function doRemoveUnrankedMods() {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
|
const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
|
||||||
req.done(inventory => {
|
req.done(inventory => {
|
||||||
window.itemListPromise.then(itemMap => {
|
window.itemListPromise.then(itemMap => {
|
||||||
@ -2038,7 +2039,7 @@ function doRemoveUnrankedMods() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function doAddMissingMaxRankMods() {
|
function doAddMissingMaxRankMods() {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
fetch("/custom/addMissingMaxRankMods?" + window.authz).then(() => {
|
fetch("/custom/addMissingMaxRankMods?" + window.authz).then(() => {
|
||||||
updateInventory();
|
updateInventory();
|
||||||
});
|
});
|
||||||
@ -2060,7 +2061,7 @@ function doPushArchonCrystalUpgrade() {
|
|||||||
$("[list='datalist-archonCrystalUpgrades']").addClass("is-invalid").focus();
|
$("[list='datalist-archonCrystalUpgrades']").addClass("is-invalid").focus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.get(
|
$.get(
|
||||||
"/custom/pushArchonCrystalUpgrade?" +
|
"/custom/pushArchonCrystalUpgrade?" +
|
||||||
window.authz +
|
window.authz +
|
||||||
@ -2078,7 +2079,7 @@ function doPushArchonCrystalUpgrade() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function doPopArchonCrystalUpgrade(type) {
|
function doPopArchonCrystalUpgrade(type) {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.get(
|
$.get(
|
||||||
"/custom/popArchonCrystalUpgrade?" +
|
"/custom/popArchonCrystalUpgrade?" +
|
||||||
window.authz +
|
window.authz +
|
||||||
@ -2093,7 +2094,7 @@ function doPopArchonCrystalUpgrade(type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function doImport() {
|
function doImport() {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.post({
|
$.post({
|
||||||
url: "/custom/import?" + window.authz,
|
url: "/custom/import?" + window.authz,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
@ -2110,7 +2111,7 @@ function doImport() {
|
|||||||
function doChangeSupportedSyndicate() {
|
function doChangeSupportedSyndicate() {
|
||||||
const uniqueName = document.getElementById("changeSyndicate").value;
|
const uniqueName = document.getElementById("changeSyndicate").value;
|
||||||
|
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.get("/api/setSupportedSyndicate.php?" + window.authz + "&syndicate=" + uniqueName).done(function () {
|
$.get("/api/setSupportedSyndicate.php?" + window.authz + "&syndicate=" + uniqueName).done(function () {
|
||||||
updateInventory();
|
updateInventory();
|
||||||
});
|
});
|
||||||
@ -2118,7 +2119,7 @@ function doChangeSupportedSyndicate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function doAddCurrency(currency) {
|
function doAddCurrency(currency) {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.post({
|
$.post({
|
||||||
url: "/custom/addCurrency?" + window.authz,
|
url: "/custom/addCurrency?" + window.authz,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
@ -2133,7 +2134,7 @@ function doAddCurrency(currency) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function doQuestUpdate(operation, itemType) {
|
function doQuestUpdate(operation, itemType) {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.post({
|
$.post({
|
||||||
url: "/custom/manageQuests?" + window.authz + "&operation=" + operation + "&itemType=" + itemType,
|
url: "/custom/manageQuests?" + window.authz + "&operation=" + operation + "&itemType=" + itemType,
|
||||||
contentType: "application/json"
|
contentType: "application/json"
|
||||||
@ -2144,7 +2145,7 @@ function doQuestUpdate(operation, itemType) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function doBulkQuestUpdate(operation) {
|
function doBulkQuestUpdate(operation) {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.post({
|
$.post({
|
||||||
url: "/custom/manageQuests?" + window.authz + "&operation=" + operation,
|
url: "/custom/manageQuests?" + window.authz + "&operation=" + operation,
|
||||||
contentType: "application/json"
|
contentType: "application/json"
|
||||||
@ -2242,7 +2243,7 @@ function handleModularSelection(category) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setBooster(ItemType, ExpiryDate, callback) {
|
function setBooster(ItemType, ExpiryDate, callback) {
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.post({
|
$.post({
|
||||||
url: "/custom/setBooster?" + window.authz,
|
url: "/custom/setBooster?" + window.authz,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
@ -2332,3 +2333,244 @@ async function doMaxPlexus() {
|
|||||||
toast(loc("code_noEquipmentToRankUp"));
|
toast(loc("code_noEquipmentToRankUp"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function doUnlockAllMissions() {
|
||||||
|
await revalidateAuthz();
|
||||||
|
await fetch("/custom/completeAllMissions?" + window.authz);
|
||||||
|
updateInventory();
|
||||||
|
}
|
||||||
|
|
||||||
|
const importSamples = {
|
||||||
|
maxFocus: {
|
||||||
|
FocusUpgrades: [
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Attack/AttackFocusAbility"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Attack/Stats/MoreAmmoFocusUpgrade",
|
||||||
|
Level: 3,
|
||||||
|
IsUniversal: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Attack/Residual/PowerSnapFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Attack/Residual/PhysicalDamageFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Attack/Active/CloakAttackChargeFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Attack/Stats/RegenAmmoFocusUpgrade",
|
||||||
|
Level: 3,
|
||||||
|
IsUniversal: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Tactic/TacticFocusAbility"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Ward/WardFocusAbility"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Defense/DefenseFocusAbility"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Power/PowerFocusAbility"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Ward/Active/KnockdownImmunityFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Ward/Active/UnairuWispFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Ward/Active/SunderingDissipationUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Ward/Active/MagneticExtensionUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Ward/Active/MagneticFieldFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Ward/Residual/ArmourBuffFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Ward/Active/ClearStaticOnKillFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Ward/Residual/SecondChanceDamageBuffFocusUpgrade",
|
||||||
|
Level: 3,
|
||||||
|
IsUniversal: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Ward/Residual/SecondChanceFocusUpgrade",
|
||||||
|
Level: 3,
|
||||||
|
IsUniversal: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Ward/Active/InvulnerableReturnFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Attack/Active/ConsecutivePowerUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Attack/Active/AttackEfficiencyFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Attack/Active/GhostlyTouchUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Attack/Active/GhostWaveUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Attack/Active/ConsecutiveEfficienyUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Tactic/Active/ProjectionStretchUpgrade",
|
||||||
|
Level: 3,
|
||||||
|
IsUniversal: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Tactic/Active/ProjectionExecutionUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Tactic/Active/FinisherTransferenceUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Tactic/Active/ComboAmpDamageFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Tactic/Residual/MeleeComboFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Tactic/Residual/MeleeXpFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Tactic/Active/LiftHitWaveUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Tactic/Active/LiftHitDamageUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Tactic/Stats/MoveSpeedFocusUpgrade",
|
||||||
|
Level: 3,
|
||||||
|
IsUniversal: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Tactic/Active/SlamComboFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Power/Active/PowerFieldFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Power/Active/DisarmedEnergyUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Power/Stats/EnergyPoolFocusUpgrade",
|
||||||
|
Level: 3,
|
||||||
|
IsUniversal: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Power/Residual/EnergyOverTimeFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Power/Active/BlastSlowFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Power/Stats/EnergyRestoreFocusUpgrade",
|
||||||
|
Level: 3,
|
||||||
|
IsUniversal: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Power/Residual/FreeAbilityCastsFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Power/Active/DisarmingProjectionUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Power/Residual/SlowHeadshotDamageFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Power/Active/DashBubbleFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Defense/Stats/HealthRegenFocusUpgrade",
|
||||||
|
Level: 3,
|
||||||
|
IsUniversal: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Defense/Residual/RadialXpFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Defense/Active/DefenseShieldFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Defense/Active/CloakHealFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Defense/Active/DefenseShieldBreakFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Defense/Active/DashImmunityFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Defense/Residual/InstantReviveFocusUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Defense/Active/SonicDissipationUpgrade",
|
||||||
|
Level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Defense/Stats/HealthMaxFocusUpgrade",
|
||||||
|
Level: 3,
|
||||||
|
IsUniversal: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Upgrades/Focus/Defense/Active/CloakHealOthersFocusUpgrade",
|
||||||
|
Level: 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function setImportSample(key) {
|
||||||
|
$("#import-inventory").val(JSON.stringify(importSamples[key], null, 2));
|
||||||
|
}
|
||||||
|
@ -158,6 +158,9 @@ dict = {
|
|||||||
cheats_noVendorPurchaseLimits: `Keine Kaufbeschränkungen bei Händlern`,
|
cheats_noVendorPurchaseLimits: `Keine Kaufbeschränkungen bei Händlern`,
|
||||||
cheats_noDeathMarks: `Keine Todesmarkierungen`,
|
cheats_noDeathMarks: `Keine Todesmarkierungen`,
|
||||||
cheats_noKimCooldowns: `Keine Wartezeit bei KIM`,
|
cheats_noKimCooldowns: `Keine Wartezeit bei KIM`,
|
||||||
|
cheats_fullyStockedVendors: `[UNTRANSLATED] Fully Stocked Vendors`,
|
||||||
|
cheats_baroAlwaysAvailable: `[UNTRANSLATED] Baro Always Available`,
|
||||||
|
cheats_baroFullyStocked: `[UNTRANSLATED] Baro Fully Stocked`,
|
||||||
cheats_syndicateMissionsRepeatable: `Syndikat-Missionen wiederholbar`,
|
cheats_syndicateMissionsRepeatable: `Syndikat-Missionen wiederholbar`,
|
||||||
cheats_unlockAllProfitTakerStages: `[UNTRANSLATED] Unlock All Profit Taker Stages`,
|
cheats_unlockAllProfitTakerStages: `[UNTRANSLATED] Unlock All Profit Taker Stages`,
|
||||||
cheats_instantFinishRivenChallenge: `Riven-Mod Herausforderung sofort abschließen`,
|
cheats_instantFinishRivenChallenge: `Riven-Mod Herausforderung sofort abschließen`,
|
||||||
@ -171,6 +174,7 @@ dict = {
|
|||||||
cheats_noDojoResearchTime: `Keine Dojo-Forschungszeit`,
|
cheats_noDojoResearchTime: `Keine Dojo-Forschungszeit`,
|
||||||
cheats_fastClanAscension: `Schneller Clan-Aufstieg`,
|
cheats_fastClanAscension: `Schneller Clan-Aufstieg`,
|
||||||
cheats_missionsCanGiveAllRelics: `[UNTRANSLATED] Missions Can Give All Relics`,
|
cheats_missionsCanGiveAllRelics: `[UNTRANSLATED] Missions Can Give All Relics`,
|
||||||
|
cheats_unlockAllSimarisResearchEntries: `[UNTRANSLATED] Unlock All Simaris Research Entries`,
|
||||||
cheats_spoofMasteryRank: `Gefälschter Meisterschaftsrang (-1 zum deaktivieren)`,
|
cheats_spoofMasteryRank: `Gefälschter Meisterschaftsrang (-1 zum deaktivieren)`,
|
||||||
cheats_nightwaveStandingMultiplier: `[UNTRANSLATED] Nightwave Standing Multiplier`,
|
cheats_nightwaveStandingMultiplier: `[UNTRANSLATED] Nightwave Standing Multiplier`,
|
||||||
cheats_save: `[UNTRANSLATED] Save`,
|
cheats_save: `[UNTRANSLATED] Save`,
|
||||||
@ -183,6 +187,8 @@ dict = {
|
|||||||
cheats_none: `Keines`,
|
cheats_none: `Keines`,
|
||||||
import_importNote: `Du kannst hier eine vollständige oder teilweise Inventarantwort (Client-Darstellung) einfügen. Alle Felder, die vom Importer unterstützt werden, <b>werden in deinem Account überschrieben</b>.`,
|
import_importNote: `Du kannst hier eine vollständige oder teilweise Inventarantwort (Client-Darstellung) einfügen. Alle Felder, die vom Importer unterstützt werden, <b>werden in deinem Account überschrieben</b>.`,
|
||||||
import_submit: `Absenden`,
|
import_submit: `Absenden`,
|
||||||
|
import_samples: `[UNTRANSLATED] Samples:`,
|
||||||
|
import_samples_maxFocus: `[UNTRANSLATED] All Focus Schools Maxed Out`,
|
||||||
|
|
||||||
upgrade_Equilibrium: `[UNTRANSLATED] +|VAL|% Energy from Health pickups, +|VAL|% Health from Energy pickups`,
|
upgrade_Equilibrium: `[UNTRANSLATED] +|VAL|% Energy from Health pickups, +|VAL|% Health from Energy pickups`,
|
||||||
upgrade_MeleeCritDamage: `[UNTRANSLATED] +|VAL|% Melee Critical Damage`,
|
upgrade_MeleeCritDamage: `[UNTRANSLATED] +|VAL|% Melee Critical Damage`,
|
||||||
@ -225,7 +231,7 @@ dict = {
|
|||||||
upgrade_DamageReductionOnHack: `[UNTRANSLATED] 75% Damage Reduction while Hacking`,
|
upgrade_DamageReductionOnHack: `[UNTRANSLATED] 75% Damage Reduction while Hacking`,
|
||||||
upgrade_OnExecutionReviveCompanion: `[UNTRANSLATED] Mercy Kills reduce Companion Recovery by 15s`,
|
upgrade_OnExecutionReviveCompanion: `[UNTRANSLATED] Mercy Kills reduce Companion Recovery by 15s`,
|
||||||
upgrade_OnExecutionParkourSpeed: `[UNTRANSLATED] +60% Parkour Speed after a Mercy for 15s`,
|
upgrade_OnExecutionParkourSpeed: `[UNTRANSLATED] +60% Parkour Speed after a Mercy for 15s`,
|
||||||
upgrade_AvatarTimeLimitIncrease: `[UNTRANSLATED] s to Hacking`,
|
upgrade_AvatarTimeLimitIncrease: `[UNTRANSLATED] +8s to Hacking`,
|
||||||
upgrade_ElectrifyOnHack: `[UNTRANSLATED] Shock enemies within 20m while Hacking`,
|
upgrade_ElectrifyOnHack: `[UNTRANSLATED] Shock enemies within 20m while Hacking`,
|
||||||
upgrade_OnExecutionTerrify: `[UNTRANSLATED] 50% chance for enemies within 15m to cower in fear for 8 seconds on Mercy`,
|
upgrade_OnExecutionTerrify: `[UNTRANSLATED] 50% chance for enemies within 15m to cower in fear for 8 seconds on Mercy`,
|
||||||
upgrade_OnHackLockers: `[UNTRANSLATED] Unlock 5 lockers within 20m after Hacking`,
|
upgrade_OnHackLockers: `[UNTRANSLATED] Unlock 5 lockers within 20m after Hacking`,
|
||||||
|
@ -157,6 +157,9 @@ dict = {
|
|||||||
cheats_noVendorPurchaseLimits: `No Vendor Purchase Limits`,
|
cheats_noVendorPurchaseLimits: `No Vendor Purchase Limits`,
|
||||||
cheats_noDeathMarks: `No Death Marks`,
|
cheats_noDeathMarks: `No Death Marks`,
|
||||||
cheats_noKimCooldowns: `No KIM Cooldowns`,
|
cheats_noKimCooldowns: `No KIM Cooldowns`,
|
||||||
|
cheats_fullyStockedVendors: `Fully Stocked Vendors`,
|
||||||
|
cheats_baroAlwaysAvailable: `Baro Always Available`,
|
||||||
|
cheats_baroFullyStocked: `Baro Fully Stocked`,
|
||||||
cheats_syndicateMissionsRepeatable: `Syndicate Missions Repeatable`,
|
cheats_syndicateMissionsRepeatable: `Syndicate Missions Repeatable`,
|
||||||
cheats_unlockAllProfitTakerStages: `Unlock All Profit Taker Stages`,
|
cheats_unlockAllProfitTakerStages: `Unlock All Profit Taker Stages`,
|
||||||
cheats_instantFinishRivenChallenge: `Instant Finish Riven Challenge`,
|
cheats_instantFinishRivenChallenge: `Instant Finish Riven Challenge`,
|
||||||
@ -170,6 +173,7 @@ dict = {
|
|||||||
cheats_noDojoResearchTime: `No Dojo Research Time`,
|
cheats_noDojoResearchTime: `No Dojo Research Time`,
|
||||||
cheats_fastClanAscension: `Fast Clan Ascension`,
|
cheats_fastClanAscension: `Fast Clan Ascension`,
|
||||||
cheats_missionsCanGiveAllRelics: `Missions Can Give All Relics`,
|
cheats_missionsCanGiveAllRelics: `Missions Can Give All Relics`,
|
||||||
|
cheats_unlockAllSimarisResearchEntries: `Unlock All Simaris Research Entries`,
|
||||||
cheats_spoofMasteryRank: `Spoofed Mastery Rank (-1 to disable)`,
|
cheats_spoofMasteryRank: `Spoofed Mastery Rank (-1 to disable)`,
|
||||||
cheats_nightwaveStandingMultiplier: `Nightwave Standing Multiplier`,
|
cheats_nightwaveStandingMultiplier: `Nightwave Standing Multiplier`,
|
||||||
cheats_save: `Save`,
|
cheats_save: `Save`,
|
||||||
@ -182,6 +186,8 @@ dict = {
|
|||||||
cheats_none: `None`,
|
cheats_none: `None`,
|
||||||
import_importNote: `You can provide a full or partial inventory response (client respresentation) here. All fields that are supported by the importer <b>will be overwritten</b> in your account.`,
|
import_importNote: `You can provide a full or partial inventory response (client respresentation) here. All fields that are supported by the importer <b>will be overwritten</b> in your account.`,
|
||||||
import_submit: `Submit`,
|
import_submit: `Submit`,
|
||||||
|
import_samples: `Samples:`,
|
||||||
|
import_samples_maxFocus: `All Focus Schools Maxed Out`,
|
||||||
|
|
||||||
upgrade_Equilibrium: `+|VAL|% Energy from Health pickups, +|VAL|% Health from Energy pickups`,
|
upgrade_Equilibrium: `+|VAL|% Energy from Health pickups, +|VAL|% Health from Energy pickups`,
|
||||||
upgrade_MeleeCritDamage: `+|VAL|% Melee Critical Damage`,
|
upgrade_MeleeCritDamage: `+|VAL|% Melee Critical Damage`,
|
||||||
@ -224,7 +230,7 @@ dict = {
|
|||||||
upgrade_DamageReductionOnHack: `75% Damage Reduction while Hacking`,
|
upgrade_DamageReductionOnHack: `75% Damage Reduction while Hacking`,
|
||||||
upgrade_OnExecutionReviveCompanion: `Mercy Kills reduce Companion Recovery by 15s`,
|
upgrade_OnExecutionReviveCompanion: `Mercy Kills reduce Companion Recovery by 15s`,
|
||||||
upgrade_OnExecutionParkourSpeed: `+60% Parkour Speed after a Mercy for 15s`,
|
upgrade_OnExecutionParkourSpeed: `+60% Parkour Speed after a Mercy for 15s`,
|
||||||
upgrade_AvatarTimeLimitIncrease: `s to Hacking`,
|
upgrade_AvatarTimeLimitIncrease: `+8s to Hacking`,
|
||||||
upgrade_ElectrifyOnHack: `Shock enemies within 20m while Hacking`,
|
upgrade_ElectrifyOnHack: `Shock enemies within 20m while Hacking`,
|
||||||
upgrade_OnExecutionTerrify: `50% chance for enemies within 15m to cower in fear for 8 seconds on Mercy`,
|
upgrade_OnExecutionTerrify: `50% chance for enemies within 15m to cower in fear for 8 seconds on Mercy`,
|
||||||
upgrade_OnHackLockers: `Unlock 5 lockers within 20m after Hacking`,
|
upgrade_OnHackLockers: `Unlock 5 lockers within 20m after Hacking`,
|
||||||
|
@ -158,6 +158,9 @@ dict = {
|
|||||||
cheats_noVendorPurchaseLimits: `Sin límite de compras de vendedores`,
|
cheats_noVendorPurchaseLimits: `Sin límite de compras de vendedores`,
|
||||||
cheats_noDeathMarks: `Sin marcas de muerte`,
|
cheats_noDeathMarks: `Sin marcas de muerte`,
|
||||||
cheats_noKimCooldowns: `Sin tiempo de espera para conversaciones KIM`,
|
cheats_noKimCooldowns: `Sin tiempo de espera para conversaciones KIM`,
|
||||||
|
cheats_fullyStockedVendors: `Vendedores con stock completo`,
|
||||||
|
cheats_baroAlwaysAvailable: `Baro siempre disponible`,
|
||||||
|
cheats_baroFullyStocked: `Baro con stock completo`,
|
||||||
cheats_syndicateMissionsRepeatable: `Misiones de sindicato rejugables`,
|
cheats_syndicateMissionsRepeatable: `Misiones de sindicato rejugables`,
|
||||||
cheats_unlockAllProfitTakerStages: `Deslobquea todas las etapas del Roba-ganancias`,
|
cheats_unlockAllProfitTakerStages: `Deslobquea todas las etapas del Roba-ganancias`,
|
||||||
cheats_instantFinishRivenChallenge: `Terminar desafío de agrietado inmediatamente`,
|
cheats_instantFinishRivenChallenge: `Terminar desafío de agrietado inmediatamente`,
|
||||||
@ -171,6 +174,7 @@ dict = {
|
|||||||
cheats_noDojoResearchTime: `Sin tiempo de investigación del dojo`,
|
cheats_noDojoResearchTime: `Sin tiempo de investigación del dojo`,
|
||||||
cheats_fastClanAscension: `Ascenso rápido del clan`,
|
cheats_fastClanAscension: `Ascenso rápido del clan`,
|
||||||
cheats_missionsCanGiveAllRelics: `Las misiones pueden otorgar todas las reliquias`,
|
cheats_missionsCanGiveAllRelics: `Las misiones pueden otorgar todas las reliquias`,
|
||||||
|
cheats_unlockAllSimarisResearchEntries: `Desbloquear todas las entradas de investigación de Simaris`,
|
||||||
cheats_spoofMasteryRank: `Rango de maestría simulado (-1 para desactivar)`,
|
cheats_spoofMasteryRank: `Rango de maestría simulado (-1 para desactivar)`,
|
||||||
cheats_nightwaveStandingMultiplier: `Multiplicador de Reputación de Onda Nocturna`,
|
cheats_nightwaveStandingMultiplier: `Multiplicador de Reputación de Onda Nocturna`,
|
||||||
cheats_save: `Guardar`,
|
cheats_save: `Guardar`,
|
||||||
@ -183,6 +187,8 @@ dict = {
|
|||||||
cheats_none: `Ninguno`,
|
cheats_none: `Ninguno`,
|
||||||
import_importNote: `Puedes proporcionar una respuesta de inventario completa o parcial (representación del cliente) aquí. Todos los campos compatibles con el importador <b>serán sobrescritos</b> en tu cuenta.`,
|
import_importNote: `Puedes proporcionar una respuesta de inventario completa o parcial (representación del cliente) aquí. Todos los campos compatibles con el importador <b>serán sobrescritos</b> en tu cuenta.`,
|
||||||
import_submit: `Enviar`,
|
import_submit: `Enviar`,
|
||||||
|
import_samples: `Muestras:`,
|
||||||
|
import_samples_maxFocus: `Todas las escuelas de enfoque al máximo`,
|
||||||
|
|
||||||
upgrade_Equilibrium: `+|VAL|% de Energía al recoger salud, +|VAL|% de Salud al recoger energía`,
|
upgrade_Equilibrium: `+|VAL|% de Energía al recoger salud, +|VAL|% de Salud al recoger energía`,
|
||||||
upgrade_MeleeCritDamage: `+|VAL|% de daño crítico cuerpo a cuerpo`,
|
upgrade_MeleeCritDamage: `+|VAL|% de daño crítico cuerpo a cuerpo`,
|
||||||
@ -225,7 +231,7 @@ dict = {
|
|||||||
upgrade_DamageReductionOnHack: `75% de reducción de daño al hackear`,
|
upgrade_DamageReductionOnHack: `75% de reducción de daño al hackear`,
|
||||||
upgrade_OnExecutionReviveCompanion: `Las ejecuciones reducen el tiempo de recuperación del compañero en 15s`,
|
upgrade_OnExecutionReviveCompanion: `Las ejecuciones reducen el tiempo de recuperación del compañero en 15s`,
|
||||||
upgrade_OnExecutionParkourSpeed: `+60% de velocidad de parkour durante 15s tras una ejecución`,
|
upgrade_OnExecutionParkourSpeed: `+60% de velocidad de parkour durante 15s tras una ejecución`,
|
||||||
upgrade_AvatarTimeLimitIncrease: `+|VAL|s al tiempo de hackeo`,
|
upgrade_AvatarTimeLimitIncrease: `[UNTRANSLATED] +8s to Hacking`,
|
||||||
upgrade_ElectrifyOnHack: `Electrocuta a los enemigos en un radio de 20m al hackear`,
|
upgrade_ElectrifyOnHack: `Electrocuta a los enemigos en un radio de 20m al hackear`,
|
||||||
upgrade_OnExecutionTerrify: `50% de probabilidad de que enemigos en un radio de 15m entren en pánico por 8s tras una ejecución`,
|
upgrade_OnExecutionTerrify: `50% de probabilidad de que enemigos en un radio de 15m entren en pánico por 8s tras una ejecución`,
|
||||||
upgrade_OnHackLockers: `Desbloquea 5 casilleros en un radio de 20m tras hackear`,
|
upgrade_OnHackLockers: `Desbloquea 5 casilleros en un radio de 20m tras hackear`,
|
||||||
|
@ -158,6 +158,9 @@ dict = {
|
|||||||
cheats_noVendorPurchaseLimits: `Aucune limite d'achat chez les PNJ`,
|
cheats_noVendorPurchaseLimits: `Aucune limite d'achat chez les PNJ`,
|
||||||
cheats_noDeathMarks: `Aucune marque d'assassin`,
|
cheats_noDeathMarks: `Aucune marque d'assassin`,
|
||||||
cheats_noKimCooldowns: `Aucun cooldown sur le KIM`,
|
cheats_noKimCooldowns: `Aucun cooldown sur le KIM`,
|
||||||
|
cheats_fullyStockedVendors: `[UNTRANSLATED] Fully Stocked Vendors`,
|
||||||
|
cheats_baroAlwaysAvailable: `[UNTRANSLATED] Baro Always Available`,
|
||||||
|
cheats_baroFullyStocked: `[UNTRANSLATED] Baro Fully Stocked`,
|
||||||
cheats_syndicateMissionsRepeatable: `Mission syndicat répétables`,
|
cheats_syndicateMissionsRepeatable: `Mission syndicat répétables`,
|
||||||
cheats_unlockAllProfitTakerStages: `[UNTRANSLATED] Unlock All Profit Taker Stages`,
|
cheats_unlockAllProfitTakerStages: `[UNTRANSLATED] Unlock All Profit Taker Stages`,
|
||||||
cheats_instantFinishRivenChallenge: `Débloquer le challenge Riven instantanément`,
|
cheats_instantFinishRivenChallenge: `Débloquer le challenge Riven instantanément`,
|
||||||
@ -171,6 +174,7 @@ dict = {
|
|||||||
cheats_noDojoResearchTime: `Aucun temps de recherche (Dojo)`,
|
cheats_noDojoResearchTime: `Aucun temps de recherche (Dojo)`,
|
||||||
cheats_fastClanAscension: `Ascension de clan rapide`,
|
cheats_fastClanAscension: `Ascension de clan rapide`,
|
||||||
cheats_missionsCanGiveAllRelics: `[UNTRANSLATED] Missions Can Give All Relics`,
|
cheats_missionsCanGiveAllRelics: `[UNTRANSLATED] Missions Can Give All Relics`,
|
||||||
|
cheats_unlockAllSimarisResearchEntries: `[UNTRANSLATED] Unlock All Simaris Research Entries`,
|
||||||
cheats_spoofMasteryRank: `Rang de maîtrise personnalisé (-1 pour désactiver)`,
|
cheats_spoofMasteryRank: `Rang de maîtrise personnalisé (-1 pour désactiver)`,
|
||||||
cheats_nightwaveStandingMultiplier: `[UNTRANSLATED] Nightwave Standing Multiplier`,
|
cheats_nightwaveStandingMultiplier: `[UNTRANSLATED] Nightwave Standing Multiplier`,
|
||||||
cheats_save: `[UNTRANSLATED] Save`,
|
cheats_save: `[UNTRANSLATED] Save`,
|
||||||
@ -183,6 +187,8 @@ dict = {
|
|||||||
cheats_none: `Aucun`,
|
cheats_none: `Aucun`,
|
||||||
import_importNote: `Import manuel. Toutes les modifcations supportées par l'inventaire <b>écraseront celles présentes dans la base de données</b>.`,
|
import_importNote: `Import manuel. Toutes les modifcations supportées par l'inventaire <b>écraseront celles présentes dans la base de données</b>.`,
|
||||||
import_submit: `Soumettre`,
|
import_submit: `Soumettre`,
|
||||||
|
import_samples: `[UNTRANSLATED] Samples:`,
|
||||||
|
import_samples_maxFocus: `[UNTRANSLATED] All Focus Schools Maxed Out`,
|
||||||
|
|
||||||
upgrade_Equilibrium: `[UNTRANSLATED] +|VAL|% Energy from Health pickups, +|VAL|% Health from Energy pickups`,
|
upgrade_Equilibrium: `[UNTRANSLATED] +|VAL|% Energy from Health pickups, +|VAL|% Health from Energy pickups`,
|
||||||
upgrade_MeleeCritDamage: `[UNTRANSLATED] +|VAL|% Melee Critical Damage`,
|
upgrade_MeleeCritDamage: `[UNTRANSLATED] +|VAL|% Melee Critical Damage`,
|
||||||
@ -225,7 +231,7 @@ dict = {
|
|||||||
upgrade_DamageReductionOnHack: `[UNTRANSLATED] 75% Damage Reduction while Hacking`,
|
upgrade_DamageReductionOnHack: `[UNTRANSLATED] 75% Damage Reduction while Hacking`,
|
||||||
upgrade_OnExecutionReviveCompanion: `[UNTRANSLATED] Mercy Kills reduce Companion Recovery by 15s`,
|
upgrade_OnExecutionReviveCompanion: `[UNTRANSLATED] Mercy Kills reduce Companion Recovery by 15s`,
|
||||||
upgrade_OnExecutionParkourSpeed: `[UNTRANSLATED] +60% Parkour Speed after a Mercy for 15s`,
|
upgrade_OnExecutionParkourSpeed: `[UNTRANSLATED] +60% Parkour Speed after a Mercy for 15s`,
|
||||||
upgrade_AvatarTimeLimitIncrease: `[UNTRANSLATED] s to Hacking`,
|
upgrade_AvatarTimeLimitIncrease: `[UNTRANSLATED] +8s to Hacking`,
|
||||||
upgrade_ElectrifyOnHack: `[UNTRANSLATED] Shock enemies within 20m while Hacking`,
|
upgrade_ElectrifyOnHack: `[UNTRANSLATED] Shock enemies within 20m while Hacking`,
|
||||||
upgrade_OnExecutionTerrify: `[UNTRANSLATED] 50% chance for enemies within 15m to cower in fear for 8 seconds on Mercy`,
|
upgrade_OnExecutionTerrify: `[UNTRANSLATED] 50% chance for enemies within 15m to cower in fear for 8 seconds on Mercy`,
|
||||||
upgrade_OnHackLockers: `[UNTRANSLATED] Unlock 5 lockers within 20m after Hacking`,
|
upgrade_OnHackLockers: `[UNTRANSLATED] Unlock 5 lockers within 20m after Hacking`,
|
||||||
|
@ -158,6 +158,9 @@ dict = {
|
|||||||
cheats_noVendorPurchaseLimits: `Отсутствие лимитов на покупки у вендоров`,
|
cheats_noVendorPurchaseLimits: `Отсутствие лимитов на покупки у вендоров`,
|
||||||
cheats_noDeathMarks: `Без меток сметри`,
|
cheats_noDeathMarks: `Без меток сметри`,
|
||||||
cheats_noKimCooldowns: `Чаты KIM без кулдауна`,
|
cheats_noKimCooldowns: `Чаты KIM без кулдауна`,
|
||||||
|
cheats_fullyStockedVendors: `[UNTRANSLATED] Fully Stocked Vendors`,
|
||||||
|
cheats_baroAlwaysAvailable: `[UNTRANSLATED] Baro Always Available`,
|
||||||
|
cheats_baroFullyStocked: `[UNTRANSLATED] Baro Fully Stocked`,
|
||||||
cheats_syndicateMissionsRepeatable: `[UNTRANSLATED] Syndicate Missions Repeatable`,
|
cheats_syndicateMissionsRepeatable: `[UNTRANSLATED] Syndicate Missions Repeatable`,
|
||||||
cheats_unlockAllProfitTakerStages: `[UNTRANSLATED] Unlock All Profit Taker Stages`,
|
cheats_unlockAllProfitTakerStages: `[UNTRANSLATED] Unlock All Profit Taker Stages`,
|
||||||
cheats_instantFinishRivenChallenge: `[UNTRANSLATED] Instant Finish Riven Challenge`,
|
cheats_instantFinishRivenChallenge: `[UNTRANSLATED] Instant Finish Riven Challenge`,
|
||||||
@ -171,6 +174,7 @@ dict = {
|
|||||||
cheats_noDojoResearchTime: `Мгновенные Исследование Додзё`,
|
cheats_noDojoResearchTime: `Мгновенные Исследование Додзё`,
|
||||||
cheats_fastClanAscension: `Мгновенное Вознесение Клана`,
|
cheats_fastClanAscension: `Мгновенное Вознесение Клана`,
|
||||||
cheats_missionsCanGiveAllRelics: `[UNTRANSLATED] Missions Can Give All Relics`,
|
cheats_missionsCanGiveAllRelics: `[UNTRANSLATED] Missions Can Give All Relics`,
|
||||||
|
cheats_unlockAllSimarisResearchEntries: `[UNTRANSLATED] Unlock All Simaris Research Entries`,
|
||||||
cheats_spoofMasteryRank: `Подделанный ранг мастерства (-1 для отключения)`,
|
cheats_spoofMasteryRank: `Подделанный ранг мастерства (-1 для отключения)`,
|
||||||
cheats_nightwaveStandingMultiplier: `[UNTRANSLATED] Nightwave Standing Multiplier`,
|
cheats_nightwaveStandingMultiplier: `[UNTRANSLATED] Nightwave Standing Multiplier`,
|
||||||
cheats_save: `[UNTRANSLATED] Save`,
|
cheats_save: `[UNTRANSLATED] Save`,
|
||||||
@ -183,6 +187,8 @@ dict = {
|
|||||||
cheats_none: `Отсутствует`,
|
cheats_none: `Отсутствует`,
|
||||||
import_importNote: `Вы можете загрузить полный или частичный ответ инвентаря (клиентское представление) здесь. Все поддерживаемые поля <b>будут перезаписаны</b> в вашем аккаунте.`,
|
import_importNote: `Вы можете загрузить полный или частичный ответ инвентаря (клиентское представление) здесь. Все поддерживаемые поля <b>будут перезаписаны</b> в вашем аккаунте.`,
|
||||||
import_submit: `Отправить`,
|
import_submit: `Отправить`,
|
||||||
|
import_samples: `[UNTRANSLATED] Samples:`,
|
||||||
|
import_samples_maxFocus: `[UNTRANSLATED] All Focus Schools Maxed Out`,
|
||||||
|
|
||||||
upgrade_Equilibrium: `[UNTRANSLATED] +|VAL|% Energy from Health pickups, +|VAL|% Health from Energy pickups`,
|
upgrade_Equilibrium: `[UNTRANSLATED] +|VAL|% Energy from Health pickups, +|VAL|% Health from Energy pickups`,
|
||||||
upgrade_MeleeCritDamage: `[UNTRANSLATED] +|VAL|% Melee Critical Damage`,
|
upgrade_MeleeCritDamage: `[UNTRANSLATED] +|VAL|% Melee Critical Damage`,
|
||||||
@ -225,7 +231,7 @@ dict = {
|
|||||||
upgrade_DamageReductionOnHack: `[UNTRANSLATED] 75% Damage Reduction while Hacking`,
|
upgrade_DamageReductionOnHack: `[UNTRANSLATED] 75% Damage Reduction while Hacking`,
|
||||||
upgrade_OnExecutionReviveCompanion: `[UNTRANSLATED] Mercy Kills reduce Companion Recovery by 15s`,
|
upgrade_OnExecutionReviveCompanion: `[UNTRANSLATED] Mercy Kills reduce Companion Recovery by 15s`,
|
||||||
upgrade_OnExecutionParkourSpeed: `[UNTRANSLATED] +60% Parkour Speed after a Mercy for 15s`,
|
upgrade_OnExecutionParkourSpeed: `[UNTRANSLATED] +60% Parkour Speed after a Mercy for 15s`,
|
||||||
upgrade_AvatarTimeLimitIncrease: `[UNTRANSLATED] s to Hacking`,
|
upgrade_AvatarTimeLimitIncrease: `[UNTRANSLATED] +8s to Hacking`,
|
||||||
upgrade_ElectrifyOnHack: `[UNTRANSLATED] Shock enemies within 20m while Hacking`,
|
upgrade_ElectrifyOnHack: `[UNTRANSLATED] Shock enemies within 20m while Hacking`,
|
||||||
upgrade_OnExecutionTerrify: `[UNTRANSLATED] 50% chance for enemies within 15m to cower in fear for 8 seconds on Mercy`,
|
upgrade_OnExecutionTerrify: `[UNTRANSLATED] 50% chance for enemies within 15m to cower in fear for 8 seconds on Mercy`,
|
||||||
upgrade_OnHackLockers: `[UNTRANSLATED] Unlock 5 lockers within 20m after Hacking`,
|
upgrade_OnHackLockers: `[UNTRANSLATED] Unlock 5 lockers within 20m after Hacking`,
|
||||||
|
@ -158,6 +158,9 @@ dict = {
|
|||||||
cheats_noVendorPurchaseLimits: `商城或商人无购买限制`,
|
cheats_noVendorPurchaseLimits: `商城或商人无购买限制`,
|
||||||
cheats_noDeathMarks: `无死亡标记(不会被 Stalker/Grustrag 三霸/Zanuka 猎人等标记)`,
|
cheats_noDeathMarks: `无死亡标记(不会被 Stalker/Grustrag 三霸/Zanuka 猎人等标记)`,
|
||||||
cheats_noKimCooldowns: `无 KIM 冷却时间`,
|
cheats_noKimCooldowns: `无 KIM 冷却时间`,
|
||||||
|
cheats_fullyStockedVendors: `[UNTRANSLATED] Fully Stocked Vendors`,
|
||||||
|
cheats_baroAlwaysAvailable: `[UNTRANSLATED] Baro Always Available`,
|
||||||
|
cheats_baroFullyStocked: `[UNTRANSLATED] Baro Fully Stocked`,
|
||||||
cheats_syndicateMissionsRepeatable: `集团任务可重复`,
|
cheats_syndicateMissionsRepeatable: `集团任务可重复`,
|
||||||
cheats_unlockAllProfitTakerStages: `解锁利润收割者圆蛛所有阶段`,
|
cheats_unlockAllProfitTakerStages: `解锁利润收割者圆蛛所有阶段`,
|
||||||
cheats_instantFinishRivenChallenge: `立即完成裂罅挑战`,
|
cheats_instantFinishRivenChallenge: `立即完成裂罅挑战`,
|
||||||
@ -171,6 +174,7 @@ dict = {
|
|||||||
cheats_noDojoResearchTime: `无视道场研究时间`,
|
cheats_noDojoResearchTime: `无视道场研究时间`,
|
||||||
cheats_fastClanAscension: `快速升级氏族`,
|
cheats_fastClanAscension: `快速升级氏族`,
|
||||||
cheats_missionsCanGiveAllRelics: `任务可获取所有遗物`,
|
cheats_missionsCanGiveAllRelics: `任务可获取所有遗物`,
|
||||||
|
cheats_unlockAllSimarisResearchEntries: `[UNTRANSLATED] Unlock All Simaris Research Entries`,
|
||||||
cheats_spoofMasteryRank: `伪造精通段位(-1为禁用)`,
|
cheats_spoofMasteryRank: `伪造精通段位(-1为禁用)`,
|
||||||
cheats_nightwaveStandingMultiplier: `午夜电波声望倍率`,
|
cheats_nightwaveStandingMultiplier: `午夜电波声望倍率`,
|
||||||
cheats_save: `保存`,
|
cheats_save: `保存`,
|
||||||
@ -183,6 +187,8 @@ dict = {
|
|||||||
cheats_none: `无`,
|
cheats_none: `无`,
|
||||||
import_importNote: `您可以在此处提供完整或部分库存响应(客户端表示)。支持的所有字段<b>将被覆盖</b>到您的账户中。`,
|
import_importNote: `您可以在此处提供完整或部分库存响应(客户端表示)。支持的所有字段<b>将被覆盖</b>到您的账户中。`,
|
||||||
import_submit: `提交`,
|
import_submit: `提交`,
|
||||||
|
import_samples: `[UNTRANSLATED] Samples:`,
|
||||||
|
import_samples_maxFocus: `[UNTRANSLATED] All Focus Schools Maxed Out`,
|
||||||
|
|
||||||
upgrade_Equilibrium: `+|VAL|% 能量 来自生命球, +|VAL|% 生命 来自能量球`,
|
upgrade_Equilibrium: `+|VAL|% 能量 来自生命球, +|VAL|% 生命 来自能量球`,
|
||||||
upgrade_MeleeCritDamage: `+|VAL|% 近战暴击伤害`,
|
upgrade_MeleeCritDamage: `+|VAL|% 近战暴击伤害`,
|
||||||
@ -225,7 +231,7 @@ dict = {
|
|||||||
upgrade_DamageReductionOnHack: `入侵时,+75% 伤害减免`,
|
upgrade_DamageReductionOnHack: `入侵时,+75% 伤害减免`,
|
||||||
upgrade_OnExecutionReviveCompanion: `怜悯之击 减少同伴复苏时间 15秒`,
|
upgrade_OnExecutionReviveCompanion: `怜悯之击 减少同伴复苏时间 15秒`,
|
||||||
upgrade_OnExecutionParkourSpeed: `怜悯之击 15秒内 +60% 跑酷速度`,
|
upgrade_OnExecutionParkourSpeed: `怜悯之击 15秒内 +60% 跑酷速度`,
|
||||||
upgrade_AvatarTimeLimitIncrease: `增加入侵限制时间`,
|
upgrade_AvatarTimeLimitIncrease: `[UNTRANSLATED] +8s to Hacking`,
|
||||||
upgrade_ElectrifyOnHack: `入侵时震慑20米之内的敌人`,
|
upgrade_ElectrifyOnHack: `入侵时震慑20米之内的敌人`,
|
||||||
upgrade_OnExecutionTerrify: `怜悯之击 50% 几率让 15米 以内的敌人恐慌`,
|
upgrade_OnExecutionTerrify: `怜悯之击 50% 几率让 15米 以内的敌人恐慌`,
|
||||||
upgrade_OnHackLockers: `入侵后解锁20米内的5个储物柜`,
|
upgrade_OnHackLockers: `入侵后解锁20米内的5个储物柜`,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user