forked from OpenWF/SpaceNinjaServer
Compare commits
40 Commits
02f0935710
...
654652b889
| Author | SHA1 | Date | |
|---|---|---|---|
| 654652b889 | |||
| e3048ea188 | |||
| bb1d6a98c5 | |||
| c3bf0ae7c7 | |||
| 3a72617a0f | |||
| 3ae535ccbc | |||
| 23abe5de02 | |||
| 0d21c73ab7 | |||
| 482101ccd0 | |||
| 60e87543aa | |||
| c4c17f24d7 | |||
| 43fa1978c0 | |||
| 18fafc38b5 | |||
| 98a46e51de | |||
| 2a7767ef4a | |||
| e867123f89 | |||
| 2322a994c6 | |||
| be8e2feae6 | |||
| 4f8b07322e | |||
| 4b3b1969da | |||
| a0ce110e7e | |||
| 7fe00da2a4 | |||
| bac23a8465 | |||
| db112ee5ed | |||
| 86998b6760 | |||
| be3dd7ab66 | |||
| e6fb675e21 | |||
| fb4c42490e | |||
| 96a15e25df | |||
| ff234c9874 | |||
| 7d3915fe05 | |||
| 4b3e2dfc62 | |||
| 737d013655 | |||
| 1f8d437fad | |||
| 9263b8f179 | |||
| 875f4b9fa4 | |||
| fd7ddd9696 | |||
| 065afc0089 | |||
| c1c14b2068 | |||
| 9e66d22256 |
25
.github/workflows/docker.yml
vendored
25
.github/workflows/docker.yml
vendored
@ -4,9 +4,9 @@ on:
|
||||
branches:
|
||||
- main
|
||||
jobs:
|
||||
docker-amd64:
|
||||
docker:
|
||||
if: github.repository == 'OpenWF/SpaceNinjaServer'
|
||||
runs-on: amd64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Docker buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@ -18,27 +18,10 @@ jobs:
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
platforms: linux/amd64
|
||||
platforms: linux/arm64,linux/amd64
|
||||
push: true
|
||||
tags: |
|
||||
openwf/spaceninjaserver:latest
|
||||
openwf/spaceninjaserver:${{ github.sha }}
|
||||
docker-arm64:
|
||||
if: github.repository == 'OpenWF/SpaceNinjaServer'
|
||||
runs-on: arm64
|
||||
steps:
|
||||
- name: Set up Docker buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Log in to container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: openwf
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
platforms: linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
openwf/spaceninjaserver:latest-arm64
|
||||
openwf/spaceninjaserver:${{ github.sha }}
|
||||
openwf/spaceninjaserver:${{ github.sha }}-arm64
|
||||
|
||||
@ -14,7 +14,8 @@ SpaceNinjaServer requires a `config.json`. To set it up, you can copy the [confi
|
||||
|
||||
- `skipTutorial` affects only newly created accounts, so you may wish to change it before logging in for the first time.
|
||||
- `logger.level` can be `fatal`, `error`, `warn`, `info`, `http`, `debug`, or `trace`.
|
||||
- `ircAddress`, `hubAddress`, and `nrsAddress` are not present by default but can be provided if these secondary servers are on a different machine.
|
||||
- `ircExecutable` can be provided with a relative path to an EXE which will be ran as a child process of SpaceNinjaServer.
|
||||
- `ircAddress`, `hubAddress`, and `nrsAddress` can be provided if these secondary servers are on a different machine.
|
||||
- `worldState.eidolonOverride` can be set to `day` or `night` to lock the time to day/fass and night/vome on Plains of Eidolon/Cambion Drift.
|
||||
- `worldState.vallisOverride` can be set to `warm` or `cold` to lock the temperature on Orb Vallis.
|
||||
- `worldState.duviriOverride` can be set to `joy`, `anger`, `envy`, `sorrow`, or `fear` to lock the Duviri spiral.
|
||||
|
||||
@ -8,15 +8,16 @@
|
||||
"bindAddress": "0.0.0.0",
|
||||
"httpPort": 80,
|
||||
"httpsPort": 443,
|
||||
"ircExecutable": null,
|
||||
"ircAddress": null,
|
||||
"hubAddress": null,
|
||||
"nrsAddress": null,
|
||||
"administratorNames": [],
|
||||
"autoCreateAccount": true,
|
||||
"skipTutorial": false,
|
||||
"unlockAllSkins": false,
|
||||
"fullyStockedVendors": false,
|
||||
"skipClanKeyCrafting": false,
|
||||
"spoofMasteryRank": -1,
|
||||
"relicRewardItemCountMultiplier": 1,
|
||||
"nightwaveStandingMultiplier": 1,
|
||||
"unfaithfulBugFixes": {
|
||||
"ignore1999LastRegionPlayed": false,
|
||||
"fixXtraCheeseTimer": false,
|
||||
@ -31,7 +32,7 @@
|
||||
"baroAlwaysAvailable": false,
|
||||
"baroFullyStocked": false,
|
||||
"varziaFullyStocked": false,
|
||||
"wolfHunt": false,
|
||||
"wolfHunt": null,
|
||||
"orphixVenom": false,
|
||||
"longShadow": false,
|
||||
"hallowedFlame": false,
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
services:
|
||||
spaceninjaserver:
|
||||
# The image to use. If you have an ARM CPU, replace 'latest' with 'latest-arm64'.
|
||||
image: openwf/spaceninjaserver:latest
|
||||
|
||||
volumes:
|
||||
@ -19,9 +18,6 @@ services:
|
||||
- mongodb
|
||||
mongodb:
|
||||
image: docker.io/library/mongo:8.0.0-noble
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: openwfagent
|
||||
MONGO_INITDB_ROOT_PASSWORD: spaceninjaserver
|
||||
volumes:
|
||||
- ./docker-data/database:/data/db
|
||||
command: mongod --quiet --logpath /dev/null
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
set -e
|
||||
|
||||
if [ ! -f conf/config.json ]; then
|
||||
jq --arg value "mongodb://openwfagent:spaceninjaserver@mongodb:27017/" '.mongodbUrl = $value' /app/config-vanilla.json > /app/conf/config.json
|
||||
jq --arg value "mongodb://mongodb:27017/openWF" '.mongodbUrl = $value' /app/config-vanilla.json > /app/conf/config.json
|
||||
fi
|
||||
|
||||
exec npm run raw -- --configPath conf/config.json
|
||||
|
||||
8
package-lock.json
generated
8
package-lock.json
generated
@ -18,7 +18,7 @@
|
||||
"morgan": "^1.10.0",
|
||||
"ncp": "^2.0.0",
|
||||
"undici": "^7.10.0",
|
||||
"warframe-public-export-plus": "^0.5.90",
|
||||
"warframe-public-export-plus": "^0.5.93",
|
||||
"warframe-riven-info": "^0.1.2",
|
||||
"winston": "^3.17.0",
|
||||
"winston-daily-rotate-file": "^5.0.0",
|
||||
@ -5534,9 +5534,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/warframe-public-export-plus": {
|
||||
"version": "0.5.90",
|
||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.90.tgz",
|
||||
"integrity": "sha512-PzYFJ+qOZawPOVx9+hGlOosGdqSJMSRL6c1z3CCXMiY5SEHUs7p9JIMjkqnvg1g7vflVWnyG6E5/2gYkQs0d7w=="
|
||||
"version": "0.5.93",
|
||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.93.tgz",
|
||||
"integrity": "sha512-A8LSFJoyg7sU1n4L0zhLK1g0CREh8Fxvk7eXKoT8nMTroQg6YgEw02gK0MUi9U3rWTnlaGTsXZMp/tgC7HWUKw=="
|
||||
},
|
||||
"node_modules/warframe-riven-info": {
|
||||
"version": "0.1.2",
|
||||
|
||||
@ -10,7 +10,6 @@
|
||||
"build:dev": "tsgo --inlineSourceMap",
|
||||
"build:dev:tsc": "tsc --incremental --inlineSourceMap",
|
||||
"build-and-start": "npm run build && npm run start",
|
||||
"build-and-start:bun": "npm run verify && npm run bun-run",
|
||||
"dev": "node scripts/dev.cjs",
|
||||
"dev:bun": "bun scripts/dev.cjs",
|
||||
"verify": "tsgo --noEmit",
|
||||
@ -22,7 +21,7 @@
|
||||
"lint:fix": "eslint --fix --ext .ts .",
|
||||
"prettier": "prettier --write .",
|
||||
"update-translations": "cd scripts && node update-translations.cjs",
|
||||
"fix": "npm run update-translations && npm run lint:fix"
|
||||
"fix": "npm run update-translations && npm run prettier"
|
||||
},
|
||||
"license": "GNU",
|
||||
"type": "module",
|
||||
@ -36,7 +35,7 @@
|
||||
"morgan": "^1.10.0",
|
||||
"ncp": "^2.0.0",
|
||||
"undici": "^7.10.0",
|
||||
"warframe-public-export-plus": "^0.5.90",
|
||||
"warframe-public-export-plus": "^0.5.93",
|
||||
"warframe-riven-info": "^0.1.2",
|
||||
"winston": "^3.17.0",
|
||||
"winston-daily-rotate-file": "^5.0.0",
|
||||
|
||||
@ -40,7 +40,11 @@ function run(changedFile) {
|
||||
runproc = undefined;
|
||||
}
|
||||
|
||||
const thisbuildproc = spawn("npm", ["run", cangoraw ? "verify" : "build:dev"], spawnopts);
|
||||
const thisbuildproc = spawn(
|
||||
process.versions.bun ? "bun" : "npm",
|
||||
["run", cangoraw ? "verify" : "build:dev"],
|
||||
spawnopts
|
||||
);
|
||||
const thisbuildstart = Date.now();
|
||||
buildproc = thisbuildproc;
|
||||
buildproc.on("exit", code => {
|
||||
@ -51,7 +55,7 @@ function run(changedFile) {
|
||||
if (code === 0) {
|
||||
console.log(`${cangoraw ? "Verified" : "Built"} in ${Date.now() - thisbuildstart} ms`);
|
||||
runproc = spawn(
|
||||
"npm",
|
||||
process.versions.bun ? "bun" : "npm",
|
||||
["run", cangoraw ? (process.versions.bun ? "raw:bun" : "raw") : "start", "--", ...args],
|
||||
spawnopts
|
||||
);
|
||||
|
||||
62
src/controllers/api/feedPrinceController.ts
Normal file
62
src/controllers/api/feedPrinceController.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import type { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
||||
import { addMiscItem, getInventory } from "../../services/inventoryService.ts";
|
||||
import { getJSONfromString } from "../../helpers/stringHelpers.ts";
|
||||
import { logger } from "../../utils/logger.ts";
|
||||
import type { IInventoryChanges } from "../../types/purchaseTypes.ts";
|
||||
|
||||
export const feedPrinceController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId, "MiscItems NokkoColony NodeIntrosCompleted");
|
||||
const payload = getJSONfromString<IFeedPrinceRequest>(String(req.body));
|
||||
|
||||
switch (payload.Mode) {
|
||||
case "r": {
|
||||
inventory.NokkoColony ??= {
|
||||
FeedLevel: 0,
|
||||
JournalEntries: []
|
||||
};
|
||||
const InventoryChanges: IInventoryChanges = {};
|
||||
inventory.NokkoColony.FeedLevel += payload.Amount;
|
||||
if (
|
||||
(!inventory.NodeIntrosCompleted.includes("CompletedVision1") && inventory.NokkoColony.FeedLevel > 20) ||
|
||||
(!inventory.NodeIntrosCompleted.includes("CompletedVision2") && inventory.NokkoColony.FeedLevel > 60)
|
||||
) {
|
||||
res.json({
|
||||
FeedSucceeded: false,
|
||||
FeedLevel: inventory.NokkoColony.FeedLevel - payload.Amount,
|
||||
InventoryChanges
|
||||
} satisfies IFeedPrinceResponse);
|
||||
} else {
|
||||
addMiscItem(
|
||||
inventory,
|
||||
"/Lotus/Types/Items/MiscItems/MushroomFood",
|
||||
payload.Amount * -1,
|
||||
InventoryChanges
|
||||
);
|
||||
await inventory.save();
|
||||
res.json({
|
||||
FeedSucceeded: true,
|
||||
FeedLevel: inventory.NokkoColony.FeedLevel,
|
||||
InventoryChanges
|
||||
} satisfies IFeedPrinceResponse);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
logger.debug(`data provided to ${req.path}: ${String(req.body)}`);
|
||||
throw new Error(`unknown feedPrince mode: ${payload.Mode}`);
|
||||
}
|
||||
};
|
||||
|
||||
interface IFeedPrinceRequest {
|
||||
Mode: string; // r
|
||||
Amount: number;
|
||||
}
|
||||
|
||||
interface IFeedPrinceResponse {
|
||||
FeedSucceeded: boolean;
|
||||
FeedLevel: number;
|
||||
InventoryChanges: IInventoryChanges;
|
||||
}
|
||||
@ -1,23 +1,91 @@
|
||||
import type { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
||||
import { getAccountForRequest } from "../../services/loginService.ts";
|
||||
import { getInventory, addMiscItems, addEquipment, occupySlot } from "../../services/inventoryService.ts";
|
||||
import type { IMiscItem, TFocusPolarity, TEquipmentKey } from "../../types/inventoryTypes/inventoryTypes.ts";
|
||||
import { InventorySlot } from "../../types/inventoryTypes/inventoryTypes.ts";
|
||||
import { logger } from "../../utils/logger.ts";
|
||||
import { ExportFocusUpgrades } from "warframe-public-export-plus";
|
||||
import { Inventory } from "../../models/inventoryModels/inventoryModel.ts";
|
||||
import { version_compare } from "../../helpers/inventoryHelpers.ts";
|
||||
|
||||
export const focusController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
switch (req.query.op) {
|
||||
const account = await getAccountForRequest(req);
|
||||
|
||||
let op = req.query.op as string;
|
||||
const focus2 = account.BuildLabel && version_compare(account.BuildLabel, "2022.04.29.12.53") < 0;
|
||||
if (focus2) {
|
||||
// Focus 2.0
|
||||
switch (req.query.op) {
|
||||
case Focus2Operation.InstallLens:
|
||||
op = "InstallLens";
|
||||
break;
|
||||
case Focus2Operation.UnlockWay:
|
||||
op = "UnlockWay";
|
||||
break;
|
||||
case Focus2Operation.UnlockUpgrade:
|
||||
op = "UnlockUpgrade";
|
||||
break;
|
||||
case Focus2Operation.IncreasePool:
|
||||
op = "IncreasePool";
|
||||
break;
|
||||
case Focus2Operation.LevelUpUpgrade:
|
||||
op = "LevelUpUpgrade";
|
||||
break;
|
||||
case Focus2Operation.ActivateWay:
|
||||
op = "ActivateWay";
|
||||
break;
|
||||
case Focus2Operation.UpdateUpgrade:
|
||||
op = "UpdateUpgrade";
|
||||
break;
|
||||
case Focus2Operation.SentTrainingAmplifier:
|
||||
op = "SentTrainingAmplifier";
|
||||
break;
|
||||
case Focus2Operation.UnbindUpgrade:
|
||||
op = "UnbindUpgrade";
|
||||
break;
|
||||
case Focus2Operation.ConvertShard:
|
||||
op = "ConvertShard";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Focus 3.0
|
||||
switch (req.query.op) {
|
||||
case Focus3Operation.InstallLens:
|
||||
op = "InstallLens";
|
||||
break;
|
||||
case Focus3Operation.UnlockWay:
|
||||
op = "UnlockWay";
|
||||
break;
|
||||
case Focus3Operation.UnlockUpgrade:
|
||||
op = "UnlockUpgrade";
|
||||
break;
|
||||
case Focus3Operation.LevelUpUpgrade:
|
||||
op = "LevelUpUpgrade";
|
||||
break;
|
||||
case Focus3Operation.ActivateWay:
|
||||
op = "ActivateWay";
|
||||
break;
|
||||
case Focus3Operation.SentTrainingAmplifier:
|
||||
op = "SentTrainingAmplifier";
|
||||
break;
|
||||
case Focus3Operation.UnbindUpgrade:
|
||||
op = "UnbindUpgrade";
|
||||
break;
|
||||
case Focus3Operation.ConvertShard:
|
||||
op = "ConvertShard";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
default:
|
||||
logger.error("Unhandled focus op type: " + String(req.query.op));
|
||||
logger.debug(String(req.body));
|
||||
res.end();
|
||||
break;
|
||||
case FocusOperation.InstallLens: {
|
||||
case "InstallLens": {
|
||||
const request = JSON.parse(String(req.body)) as ILensInstallRequest;
|
||||
const inventory = await getInventory(accountId);
|
||||
const inventory = await getInventory(account._id.toString());
|
||||
const item = inventory[request.Category].id(request.WeaponId);
|
||||
if (item) {
|
||||
item.FocusLens = request.LensType;
|
||||
@ -35,10 +103,10 @@ export const focusController: RequestHandler = async (req, res) => {
|
||||
});
|
||||
break;
|
||||
}
|
||||
case FocusOperation.UnlockWay: {
|
||||
case "UnlockWay": {
|
||||
const focusType = (JSON.parse(String(req.body)) as IWayRequest).FocusType;
|
||||
const focusPolarity = focusTypeToPolarity(focusType);
|
||||
const inventory = await getInventory(accountId, "FocusAbility FocusUpgrades FocusXP");
|
||||
const inventory = await getInventory(account._id.toString(), "FocusAbility FocusUpgrades FocusXP");
|
||||
const cost = inventory.FocusAbility ? 50_000 : 0;
|
||||
inventory.FocusAbility ??= focusType;
|
||||
inventory.FocusUpgrades.push({ ItemType: focusType });
|
||||
@ -52,12 +120,29 @@ export const focusController: RequestHandler = async (req, res) => {
|
||||
});
|
||||
break;
|
||||
}
|
||||
case FocusOperation.ActivateWay: {
|
||||
case "IncreasePool": {
|
||||
const request = JSON.parse(String(req.body)) as IIncreasePoolRequest;
|
||||
const focusPolarity = focusTypeToPolarity(request.FocusType);
|
||||
const inventory = await getInventory(account._id.toString(), "FocusXP FocusCapacity");
|
||||
let cost = 0;
|
||||
for (let capacity = request.CurrentTotalCapacity; capacity != request.NewTotalCapacity; ++capacity) {
|
||||
cost += increasePoolCost[capacity - 5];
|
||||
}
|
||||
inventory.FocusXP![focusPolarity]! -= cost;
|
||||
inventory.FocusCapacity = request.NewTotalCapacity;
|
||||
await inventory.save();
|
||||
res.json({
|
||||
TotalCapacity: request.NewTotalCapacity,
|
||||
FocusPointCosts: { [focusPolarity]: cost }
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "ActivateWay": {
|
||||
const focusType = (JSON.parse(String(req.body)) as IWayRequest).FocusType;
|
||||
|
||||
await Inventory.updateOne(
|
||||
{
|
||||
accountOwnerId: accountId
|
||||
accountOwnerId: account._id.toString()
|
||||
},
|
||||
{
|
||||
FocusAbility: focusType
|
||||
@ -69,13 +154,20 @@ export const focusController: RequestHandler = async (req, res) => {
|
||||
});
|
||||
break;
|
||||
}
|
||||
case FocusOperation.UnlockUpgrade: {
|
||||
case "UnlockUpgrade": {
|
||||
const request = JSON.parse(String(req.body)) as IUnlockUpgradeRequest;
|
||||
const focusPolarity = focusTypeToPolarity(request.FocusTypes[0]);
|
||||
const inventory = await getInventory(accountId);
|
||||
const inventory = await getInventory(account._id.toString());
|
||||
let cost = 0;
|
||||
for (const focusType of request.FocusTypes) {
|
||||
cost += ExportFocusUpgrades[focusType].baseFocusPointCost;
|
||||
if (focusType in ExportFocusUpgrades) {
|
||||
cost += ExportFocusUpgrades[focusType].baseFocusPointCost;
|
||||
} else if (focusType == "/Lotus/Upgrades/Focus/Power/Residual/ChannelEfficiencyFocusUpgrade") {
|
||||
// Zenurik's Inner Might (Focus 2.0)
|
||||
cost += 50_000;
|
||||
} else {
|
||||
logger.warn(`unknown focus upgrade ${focusType}, will unlock it for free`);
|
||||
}
|
||||
inventory.FocusUpgrades.push({ ItemType: focusType, Level: 0 });
|
||||
}
|
||||
inventory.FocusXP![focusPolarity]! -= cost;
|
||||
@ -86,15 +178,20 @@ export const focusController: RequestHandler = async (req, res) => {
|
||||
});
|
||||
break;
|
||||
}
|
||||
case FocusOperation.LevelUpUpgrade: {
|
||||
case "LevelUpUpgrade":
|
||||
case "UpdateUpgrade": {
|
||||
const request = JSON.parse(String(req.body)) as ILevelUpUpgradeRequest;
|
||||
const focusPolarity = focusTypeToPolarity(request.FocusInfos[0].ItemType);
|
||||
const inventory = await getInventory(accountId);
|
||||
const inventory = await getInventory(account._id.toString());
|
||||
let cost = 0;
|
||||
for (const focusUpgrade of request.FocusInfos) {
|
||||
cost += focusUpgrade.FocusXpCost;
|
||||
const focusUpgradeDb = inventory.FocusUpgrades.find(entry => entry.ItemType == focusUpgrade.ItemType)!;
|
||||
focusUpgradeDb.Level = focusUpgrade.Level;
|
||||
if (op == "UpdateUpgrade") {
|
||||
focusUpgradeDb.IsActive = focusUpgrade.IsActive;
|
||||
} else {
|
||||
focusUpgradeDb.Level = focusUpgrade.Level;
|
||||
}
|
||||
}
|
||||
inventory.FocusXP![focusPolarity]! -= cost;
|
||||
await inventory.save();
|
||||
@ -104,9 +201,9 @@ export const focusController: RequestHandler = async (req, res) => {
|
||||
});
|
||||
break;
|
||||
}
|
||||
case FocusOperation.SentTrainingAmplifier: {
|
||||
case "SentTrainingAmplifier": {
|
||||
const request = JSON.parse(String(req.body)) as ISentTrainingAmplifierRequest;
|
||||
const inventory = await getInventory(accountId);
|
||||
const inventory = await getInventory(account._id.toString());
|
||||
const inventoryChanges = addEquipment(inventory, "OperatorAmps", request.StartingWeaponType, {
|
||||
ModularParts: [
|
||||
"/Lotus/Weapons/Sentients/OperatorAmplifiers/SentTrainingAmplifier/SentAmpTrainingGrip",
|
||||
@ -119,10 +216,10 @@ export const focusController: RequestHandler = async (req, res) => {
|
||||
res.json(inventoryChanges.OperatorAmps![0]);
|
||||
break;
|
||||
}
|
||||
case FocusOperation.UnbindUpgrade: {
|
||||
case "UnbindUpgrade": {
|
||||
const request = JSON.parse(String(req.body)) as IUnbindUpgradeRequest;
|
||||
const focusPolarity = focusTypeToPolarity(request.FocusTypes[0]);
|
||||
const inventory = await getInventory(accountId);
|
||||
const inventory = await getInventory(account._id.toString());
|
||||
inventory.FocusXP![focusPolarity]! -= 750_000 * request.FocusTypes.length;
|
||||
addMiscItems(inventory, [
|
||||
{
|
||||
@ -149,7 +246,7 @@ export const focusController: RequestHandler = async (req, res) => {
|
||||
});
|
||||
break;
|
||||
}
|
||||
case FocusOperation.ConvertShard: {
|
||||
case "ConvertShard": {
|
||||
const request = JSON.parse(String(req.body)) as IConvertShardRequest;
|
||||
// Tally XP
|
||||
let xp = 0;
|
||||
@ -167,7 +264,7 @@ export const focusController: RequestHandler = async (req, res) => {
|
||||
for (const shard of request.Shards) {
|
||||
shard.ItemCount *= -1;
|
||||
}
|
||||
const inventory = await getInventory(accountId);
|
||||
const inventory = await getInventory(account._id.toString());
|
||||
const polarity = request.Polarity;
|
||||
inventory.FocusXP ??= {};
|
||||
inventory.FocusXP[polarity] ??= 0;
|
||||
@ -179,7 +276,8 @@ export const focusController: RequestHandler = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
enum FocusOperation {
|
||||
// Focus 3.0
|
||||
enum Focus3Operation {
|
||||
InstallLens = "1",
|
||||
UnlockWay = "2",
|
||||
UnlockUpgrade = "3",
|
||||
@ -190,6 +288,20 @@ enum FocusOperation {
|
||||
ConvertShard = "9"
|
||||
}
|
||||
|
||||
// Focus 2.0
|
||||
enum Focus2Operation {
|
||||
InstallLens = "1",
|
||||
UnlockWay = "2",
|
||||
UnlockUpgrade = "3",
|
||||
IncreasePool = "4",
|
||||
LevelUpUpgrade = "5",
|
||||
ActivateWay = "6",
|
||||
UpdateUpgrade = "7", // used to change the IsActive state, same format as ILevelUpUpgradeRequest
|
||||
SentTrainingAmplifier = "9",
|
||||
UnbindUpgrade = "10",
|
||||
ConvertShard = "11"
|
||||
}
|
||||
|
||||
// For UnlockWay & ActivateWay
|
||||
interface IWayRequest {
|
||||
FocusType: string;
|
||||
@ -199,6 +311,13 @@ interface IUnlockUpgradeRequest {
|
||||
FocusTypes: string[];
|
||||
}
|
||||
|
||||
// Focus 2.0
|
||||
interface IIncreasePoolRequest {
|
||||
FocusType: string;
|
||||
CurrentTotalCapacity: number;
|
||||
NewTotalCapacity: number;
|
||||
}
|
||||
|
||||
interface ILevelUpUpgradeRequest {
|
||||
FocusInfos: {
|
||||
ItemType: string;
|
||||
@ -206,6 +325,7 @@ interface ILevelUpUpgradeRequest {
|
||||
IsUniversal: boolean;
|
||||
Level: number;
|
||||
IsActiveAbility: boolean;
|
||||
IsActive?: number; // Focus 2.0
|
||||
}[];
|
||||
}
|
||||
|
||||
@ -240,3 +360,19 @@ const shardValues = {
|
||||
"/Lotus/Types/Gameplay/Eidolon/Resources/SentientShards/SentientShardBrilliantItem": 25_000,
|
||||
"/Lotus/Types/Gameplay/Eidolon/Resources/SentientShards/SentientShardBrilliantTierTwoItem": 40_000
|
||||
};
|
||||
|
||||
// Starting at a capacity of 5 (Source: https://wiki.warframe.com/w/Focus_2.0)
|
||||
const increasePoolCost = [
|
||||
2576, 3099, 3638, 4190, 4755, 5331, 5918, 6514, 7120, 7734, 8357, 8988, 9626, 10271, 10923, 11582, 12247, 12918,
|
||||
13595, 14277, 14965, 15659, 16357, 17061, 17769, 18482, 19200, 19922, 20649, 21380, 22115, 22854, 23597, 24344,
|
||||
25095, 25850, 26609, 27371, 28136, 28905, 29678, 30454, 31233, 32015, 32801, 33590, 34382, 35176, 35974, 36775,
|
||||
37579, 38386, 39195, 40008, 40823, 41641, 42461, 43284, 44110, 44938, 45769, 46603, 47439, 48277, 49118, 49961,
|
||||
50807, 51655, 52505, 53357, 54212, 55069, 55929, 56790, 57654, 58520, 59388, 60258, 61130, 62005, 62881, 63759,
|
||||
64640, 65522, 66407, 67293, 68182, 69072, 69964, 70858, 71754, 72652, 73552, 74453, 75357, 76262, 77169, 78078,
|
||||
78988, 79900, 80814, 81730, 82648, 83567, 84488, 85410, 86334, 87260, 88188, 89117, 90047, 90980, 91914, 92849,
|
||||
93786, 94725, 95665, 96607, 97550, 98495, 99441, 100389, 101338, 102289, 103241, 104195, 105150, 106107, 107065,
|
||||
108024, 108985, 109948, 110911, 111877, 112843, 113811, 114780, 115751, 116723, 117696, 118671, 119647, 120624,
|
||||
121603, 122583, 123564, 124547, 125531, 126516, 127503, 128490, 129479, 130470, 131461, 132454, 133448, 134443,
|
||||
135440, 136438, 137437, 138437, 139438, 140441, 141444, 142449, 143455, 144463, 145471, 146481, 147492, 148503,
|
||||
149517
|
||||
];
|
||||
|
||||
@ -348,12 +348,12 @@ export const getInventoryResponse = async (
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof config.spoofMasteryRank === "number" && config.spoofMasteryRank >= 0) {
|
||||
inventoryResponse.PlayerLevel = config.spoofMasteryRank;
|
||||
if (inventory.spoofMasteryRank && inventory.spoofMasteryRank >= 0) {
|
||||
inventoryResponse.PlayerLevel = inventory.spoofMasteryRank;
|
||||
if (!xpBasedLevelCapDisabled) {
|
||||
// This client has not been patched to accept any mastery rank, need to fake the XP.
|
||||
inventoryResponse.XPInfo = [];
|
||||
let numFrames = getExpRequiredForMr(Math.min(config.spoofMasteryRank, 5030)) / 6000;
|
||||
let numFrames = getExpRequiredForMr(Math.min(inventory.spoofMasteryRank, 5030)) / 6000;
|
||||
while (numFrames-- > 0) {
|
||||
inventoryResponse.XPInfo.push({
|
||||
ItemType: "/Lotus/Powersuits/Mag/Mag",
|
||||
|
||||
117
src/controllers/api/researchMushroomController.ts
Normal file
117
src/controllers/api/researchMushroomController.ts
Normal file
@ -0,0 +1,117 @@
|
||||
import type { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
||||
import { addMiscItem, getInventory } from "../../services/inventoryService.ts";
|
||||
import { getJSONfromString } from "../../helpers/stringHelpers.ts";
|
||||
import { logger } from "../../utils/logger.ts";
|
||||
import type { IJournalEntry } from "../../types/inventoryTypes/inventoryTypes.ts";
|
||||
import type { IAffiliationMods } from "../../types/purchaseTypes.ts";
|
||||
|
||||
export const researchMushroomController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId, "MiscItems NokkoColony Affiliations");
|
||||
const payload = getJSONfromString<IResearchMushroom>(String(req.body));
|
||||
switch (payload.Mode) {
|
||||
case "r": {
|
||||
const InventoryChanges = {};
|
||||
const AffiliationMods: IAffiliationMods[] = [];
|
||||
|
||||
addMiscItem(inventory, payload.MushroomItem, payload.Amount * -1, InventoryChanges);
|
||||
if (payload.Convert) {
|
||||
addMiscItem(inventory, "/Lotus/Types/Items/MiscItems/MushroomFood", payload.Amount, InventoryChanges);
|
||||
}
|
||||
|
||||
inventory.NokkoColony ??= {
|
||||
FeedLevel: 0,
|
||||
JournalEntries: []
|
||||
};
|
||||
|
||||
let journalEntry = inventory.NokkoColony.JournalEntries.find(x => x.EntryType == payload.MushroomItem);
|
||||
if (!journalEntry) {
|
||||
journalEntry = { EntryType: payload.MushroomItem, Progress: 0 };
|
||||
inventory.NokkoColony.JournalEntries.push(journalEntry);
|
||||
}
|
||||
|
||||
let syndicate = inventory.Affiliations.find(x => x.Tag == "NightcapJournalSyndicate");
|
||||
if (!syndicate) {
|
||||
syndicate = { Tag: "NightcapJournalSyndicate", Title: 0, Standing: 0 };
|
||||
inventory.Affiliations.push(syndicate);
|
||||
}
|
||||
const completedBefore = inventory.NokkoColony.JournalEntries.filter(
|
||||
entry => getJournalRank(entry) === 3
|
||||
).length;
|
||||
const PrevRank = syndicateTitleThresholds.reduce(
|
||||
(rank, threshold, i) => (completedBefore >= threshold ? i : rank),
|
||||
0
|
||||
);
|
||||
|
||||
if (getJournalRank(journalEntry) < 3) journalEntry.Progress += payload.Amount;
|
||||
|
||||
const completedAfter = inventory.NokkoColony.JournalEntries.filter(
|
||||
entry => getJournalRank(entry) === 3
|
||||
).length;
|
||||
const NewRank = syndicateTitleThresholds.reduce(
|
||||
(rank, threshold, i) => (completedAfter >= threshold ? i : rank),
|
||||
0
|
||||
);
|
||||
|
||||
if (NewRank > (syndicate.Title ?? 0)) {
|
||||
syndicate.Title = NewRank;
|
||||
AffiliationMods.push({ Tag: "NightcapJournalSyndicate", Title: NewRank });
|
||||
}
|
||||
|
||||
await inventory.save();
|
||||
res.json({
|
||||
PrevRank,
|
||||
NewRank,
|
||||
Progress: journalEntry.Progress,
|
||||
InventoryChanges,
|
||||
AffiliationMods
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
logger.debug(`data provided to ${req.path}: ${String(req.body)}`);
|
||||
throw new Error(`unknown researchMushroom mode: ${payload.Mode}`);
|
||||
}
|
||||
};
|
||||
|
||||
interface IResearchMushroom {
|
||||
Mode: string; // r
|
||||
MushroomItem: string;
|
||||
Amount: number;
|
||||
Convert: boolean;
|
||||
}
|
||||
|
||||
const journalEntriesRank: Record<string, number> = {
|
||||
"/Lotus/Types/Items/MushroomJournal/PlainMushroomJournalItem": 1,
|
||||
"/Lotus/Types/Items/MushroomJournal/GasMushroomJournalItem": 4,
|
||||
"/Lotus/Types/Items/MushroomJournal/ToxinMushroomJournalItem": 3,
|
||||
"/Lotus/Types/Items/MushroomJournal/ViralMushroomJournalItem": 4,
|
||||
"/Lotus/Types/Items/MushroomJournal/MagneticMushroomJournalItem": 4,
|
||||
"/Lotus/Types/Items/MushroomJournal/ElectricMushroomJournalItem": 3,
|
||||
"/Lotus/Types/Items/MushroomJournal/TauMushroomJournalItem": 5,
|
||||
"/Lotus/Types/Items/MushroomJournal/SlashMushroomJournalItem": 3,
|
||||
"/Lotus/Types/Items/MushroomJournal/BlastMushroomJournalItem": 4,
|
||||
"/Lotus/Types/Items/MushroomJournal/ImpactMushroomJournalItem": 3,
|
||||
"/Lotus/Types/Items/MushroomJournal/ColdMushroomJournalItem": 3,
|
||||
"/Lotus/Types/Items/MushroomJournal/CorrosiveMushroomJournalItem": 4,
|
||||
"/Lotus/Types/Items/MushroomJournal/PunctureMushroomJournalItem": 3,
|
||||
"/Lotus/Types/Items/MushroomJournal/HeatMushroomJournalItem": 3,
|
||||
"/Lotus/Types/Items/MushroomJournal/RadiationMushroomJournalItem": 4,
|
||||
"/Lotus/Types/Items/MushroomJournal/VoidMushroomJournalItem": 5
|
||||
};
|
||||
|
||||
const syndicateTitleThresholds = [0, 1, 2, 6, 12, 16];
|
||||
|
||||
const getJournalRank = (journalEntry: IJournalEntry): number => {
|
||||
const k = journalEntriesRank[journalEntry.EntryType];
|
||||
if (!k) return 0;
|
||||
|
||||
const thresholds = [k * 1, k * 3, k * 6];
|
||||
|
||||
if (journalEntry.Progress >= thresholds[2]) return 3;
|
||||
if (journalEntry.Progress >= thresholds[1]) return 2;
|
||||
if (journalEntry.Progress >= thresholds[0]) return 1;
|
||||
return 0;
|
||||
};
|
||||
@ -1,11 +1,20 @@
|
||||
import type { RequestHandler } from "express";
|
||||
import { updateShipFeature } from "../../services/personalRoomsService.ts";
|
||||
import type { IUnlockShipFeatureRequest } from "../../types/requestTypes.ts";
|
||||
import { parseString } from "../../helpers/general.ts";
|
||||
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
||||
import { getInventory } from "../../services/inventoryService.ts";
|
||||
import { getJSONfromString } from "../../helpers/stringHelpers.ts";
|
||||
import { unlockShipFeature } from "../../services/personalRoomsService.ts";
|
||||
|
||||
export const unlockShipFeatureController: RequestHandler = async (req, res) => {
|
||||
const accountId = parseString(req.query.accountId);
|
||||
const shipFeatureRequest = JSON.parse((req.body as string).toString()) as IUnlockShipFeatureRequest;
|
||||
await updateShipFeature(accountId, shipFeatureRequest.Feature);
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId, "MiscItems accountOwnerId");
|
||||
const request = getJSONfromString<IUnlockShipFeatureRequest>(String(req.body));
|
||||
|
||||
await unlockShipFeature(inventory, request.Feature);
|
||||
await inventory.save();
|
||||
res.send([]);
|
||||
};
|
||||
interface IUnlockShipFeatureRequest {
|
||||
Feature: string;
|
||||
KeyChain: string;
|
||||
ChainStage: number;
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ export const updateChallengeProgressController: RequestHandler = async (req, res
|
||||
|
||||
const inventory = await getInventory(
|
||||
account._id.toString(),
|
||||
"ChallengesFixVersion ChallengeProgress SeasonChallengeHistory Affiliations CalendarProgress"
|
||||
"ChallengesFixVersion ChallengeProgress SeasonChallengeHistory Affiliations CalendarProgress nightwaveStandingMultiplier"
|
||||
);
|
||||
let affiliationMods: IAffiliationMods[] = [];
|
||||
if (challenges.ChallengeProgress) {
|
||||
|
||||
@ -96,10 +96,15 @@ export const upgradesController: RequestHandler = async (req, res) => {
|
||||
case "/Lotus/Types/Items/MiscItems/WeaponPrimaryArcaneUnlocker":
|
||||
case "/Lotus/Types/Items/MiscItems/WeaponSecondaryArcaneUnlocker":
|
||||
case "/Lotus/Types/Items/MiscItems/WeaponMeleeArcaneUnlocker":
|
||||
case "/Lotus/Types/Items/MiscItems/WeaponAmpArcaneUnlocker": {
|
||||
case "/Lotus/Types/Items/MiscItems/WeaponAmpArcaneUnlocker":
|
||||
case "/Lotus/Types/Items/MiscItems/WeaponArchGunArcaneUnlocker": {
|
||||
const item = inventory[payload.ItemCategory].id(payload.ItemId.$oid)!;
|
||||
item.Features ??= 0;
|
||||
item.Features |= EquipmentFeatures.ARCANE_SLOT;
|
||||
if (operation.OperationType == "UOT_ARCANE_UNLOCK_1") {
|
||||
item.Features |= EquipmentFeatures.SECOND_ARCANE_SLOT;
|
||||
} else {
|
||||
item.Features |= EquipmentFeatures.ARCANE_SLOT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "/Lotus/Types/Items/MiscItems/ValenceAdapter": {
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
||||
import { getInventory } from "../../services/inventoryService.ts";
|
||||
import type { RequestHandler } from "express";
|
||||
import { getGuildForRequestEx, hasGuildPermission } from "../../services/guildService.ts";
|
||||
import { GuildPermission } from "../../types/guildTypes.ts";
|
||||
import type { ITypeCount } from "../../types/commonTypes.ts";
|
||||
|
||||
export const addVaultDecoRecipeController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const requests = req.body as ITypeCount[];
|
||||
const inventory = await getInventory(accountId, "GuildId");
|
||||
const guild = await getGuildForRequestEx(req, inventory);
|
||||
if (!(await hasGuildPermission(guild, accountId, GuildPermission.Architect))) {
|
||||
res.status(400).send("-1").end();
|
||||
return;
|
||||
}
|
||||
guild.VaultDecoRecipes ??= [];
|
||||
for (const request of requests) {
|
||||
const index = guild.VaultDecoRecipes.findIndex(x => x.ItemType === request.ItemType);
|
||||
|
||||
if (index == -1) {
|
||||
guild.VaultDecoRecipes.push({
|
||||
ItemType: request.ItemType,
|
||||
ItemCount: request.ItemCount
|
||||
});
|
||||
} else {
|
||||
guild.VaultDecoRecipes[index].ItemCount += request.ItemCount;
|
||||
|
||||
if (guild.VaultDecoRecipes[index].ItemCount < 1) {
|
||||
guild.VaultDecoRecipes.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
await guild.save();
|
||||
res.end();
|
||||
};
|
||||
43
src/controllers/custom/addVaultTypeCountController.ts
Normal file
43
src/controllers/custom/addVaultTypeCountController.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
||||
import { getInventory } from "../../services/inventoryService.ts";
|
||||
import type { RequestHandler } from "express";
|
||||
import { getGuildForRequestEx, hasGuildPermission } from "../../services/guildService.ts";
|
||||
import { GuildPermission } from "../../types/guildTypes.ts";
|
||||
import type { ITypeCount } from "../../types/commonTypes.ts";
|
||||
|
||||
export const addVaultTypeCountController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const { vaultType, items } = req.body as {
|
||||
vaultType: keyof typeof vaultConfig;
|
||||
items: ITypeCount[];
|
||||
};
|
||||
const inventory = await getInventory(accountId, "GuildId");
|
||||
const guild = await getGuildForRequestEx(req, inventory);
|
||||
if (!(await hasGuildPermission(guild, accountId, vaultConfig[vaultType]))) {
|
||||
res.status(400).send("-1").end();
|
||||
return;
|
||||
}
|
||||
guild[vaultType] ??= [];
|
||||
for (const item of items) {
|
||||
const index = guild[vaultType].findIndex(x => x.ItemType === item.ItemType);
|
||||
if (index === -1) {
|
||||
guild[vaultType].push({
|
||||
ItemType: item.ItemType,
|
||||
ItemCount: item.ItemCount
|
||||
});
|
||||
} else {
|
||||
guild[vaultType][index].ItemCount += item.ItemCount;
|
||||
if (guild[vaultType][index].ItemCount < 1) {
|
||||
guild[vaultType].splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await guild.save();
|
||||
res.end();
|
||||
};
|
||||
const vaultConfig = {
|
||||
VaultShipDecorations: GuildPermission.Treasurer,
|
||||
VaultMiscItems: GuildPermission.Treasurer,
|
||||
VaultDecoRecipes: GuildPermission.Architect
|
||||
} as const;
|
||||
@ -38,6 +38,7 @@ interface ListedItem {
|
||||
parazon?: boolean;
|
||||
alwaysAvailable?: boolean;
|
||||
maxLevelCap?: number;
|
||||
eligibleForVault?: boolean;
|
||||
}
|
||||
|
||||
interface ItemLists {
|
||||
@ -141,6 +142,12 @@ const getItemListsController: RequestHandler = (req, response) => {
|
||||
}
|
||||
]*/
|
||||
};
|
||||
const eligibleForVault = new Set<string>([
|
||||
...Object.values(ExportDojoRecipes.research).flatMap(r => r.ingredients.map(i => i.ItemType)),
|
||||
...Object.values(ExportDojoRecipes.fabrications).flatMap(f => f.ingredients.map(i => i.ItemType)),
|
||||
...Object.values(ExportDojoRecipes.rooms).flatMap(r => r.ingredients.map(i => i.ItemType)),
|
||||
...Object.values(ExportDojoRecipes.decos).flatMap(d => d.ingredients.map(i => i.ItemType))
|
||||
]);
|
||||
for (const [uniqueName, item] of Object.entries(ExportWarframes)) {
|
||||
res[item.productCategory].push({
|
||||
uniqueName,
|
||||
@ -246,7 +253,8 @@ const getItemListsController: RequestHandler = (req, response) => {
|
||||
res.miscitems.push({
|
||||
uniqueName: uniqueName,
|
||||
name: name,
|
||||
subtype: "Resource"
|
||||
subtype: "Resource",
|
||||
...(eligibleForVault.has(uniqueName) && { eligibleForVault: true })
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ export const manageQuestsController: RequestHandler = async (req, res) => {
|
||||
|
||||
if (currentStage + 1 == questManifest.chainStages?.length) {
|
||||
logger.debug(`Trying to complete last stage with nextStage, calling completeQuest instead`);
|
||||
await completeQuest(inventory, questKey.ItemType);
|
||||
await completeQuest(inventory, questKey.ItemType, true);
|
||||
} else {
|
||||
if (run > 0) {
|
||||
questKey.Progress[currentStage + 1].c = run;
|
||||
|
||||
24
src/controllers/custom/removeIsNewController.ts
Normal file
24
src/controllers/custom/removeIsNewController.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { getInventory } from "../../services/inventoryService.ts";
|
||||
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
||||
import type { RequestHandler } from "express";
|
||||
import { equipmentKeys } from "../../types/inventoryTypes/inventoryTypes.ts";
|
||||
import { broadcastInventoryUpdate } from "../../services/wsService.ts";
|
||||
|
||||
export const removeIsNewController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const filteredEquipmentKeys = equipmentKeys.filter(k => k !== "CrewShipWeapons" && k !== "CrewShipSalvagedWeapons");
|
||||
const inventory = await getInventory(accountId, [...filteredEquipmentKeys, "WeaponSkins"].join(" "));
|
||||
for (const key of filteredEquipmentKeys) {
|
||||
if (key in inventory) {
|
||||
for (const equipment of inventory[key]) {
|
||||
if (equipment.IsNew) equipment.IsNew = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const equipment of inventory.WeaponSkins) {
|
||||
if (equipment.IsNew) equipment.IsNew = false;
|
||||
}
|
||||
await inventory.save();
|
||||
res.end();
|
||||
broadcastInventoryUpdate(req);
|
||||
};
|
||||
@ -1,16 +1,9 @@
|
||||
import type { RequestHandler } from "express";
|
||||
import type { ITunables } from "../../types/bootstrapperTypes.ts";
|
||||
|
||||
// This endpoint is specific to the OpenWF Bootstrapper: https://openwf.io/bootstrapper-manual
|
||||
|
||||
interface ITunables {
|
||||
prohibit_skip_mission_start_timer?: boolean;
|
||||
prohibit_fov_override?: boolean;
|
||||
prohibit_freecam?: boolean;
|
||||
prohibit_teleport?: boolean;
|
||||
prohibit_scripts?: boolean;
|
||||
}
|
||||
|
||||
const tunablesController: RequestHandler = (_req, res) => {
|
||||
export const tunablesController: RequestHandler = (_req, res) => {
|
||||
const tunables: ITunables = {};
|
||||
//tunables.prohibit_skip_mission_start_timer = true;
|
||||
//tunables.prohibit_fov_override = true;
|
||||
@ -19,5 +12,3 @@ const tunablesController: RequestHandler = (_req, res) => {
|
||||
//tunables.prohibit_scripts = true;
|
||||
res.json(tunables);
|
||||
};
|
||||
|
||||
export { tunablesController };
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
import type { RequestHandler } from "express";
|
||||
import { getAccountForRequest } from "../../services/loginService.ts";
|
||||
import { version_compare } from "../../helpers/inventoryHelpers.ts";
|
||||
|
||||
export const getSkuCatalogController: RequestHandler = (_req, res) => {
|
||||
res.sendFile("static/fixed_responses/getSkuCatalog.json", { root: "./" });
|
||||
export const getSkuCatalogController: RequestHandler = async (req, res) => {
|
||||
const account = await getAccountForRequest(req);
|
||||
if (!account.BuildLabel || version_compare(account.BuildLabel, "2025.10.14.16.10") >= 0) {
|
||||
res.sendFile("static/fixed_responses/getSkuCatalogU40.json", { root: "./" });
|
||||
} else {
|
||||
res.sendFile("static/fixed_responses/getSkuCatalog.json", { root: "./" });
|
||||
}
|
||||
};
|
||||
|
||||
@ -8,7 +8,6 @@ import { logger } from "../utils/logger.ts";
|
||||
import { addMiscItems, combineInventoryChanges } from "../services/inventoryService.ts";
|
||||
import { handleStoreItemAcquisition } from "../services/purchaseService.ts";
|
||||
import type { IInventoryChanges } from "../types/purchaseTypes.ts";
|
||||
import { config } from "../services/configService.ts";
|
||||
|
||||
export const crackRelic = async (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
@ -29,10 +28,10 @@ export const crackRelic = async (
|
||||
ExportRewards[relic.rewardManifest][0] as { type: string; itemCount: number; rarity: TRarity }[], // rarity is nullable in PE+ typings, but always present for relics
|
||||
weights
|
||||
)!;
|
||||
if (config.relicRewardItemCountMultiplier !== undefined && (config.relicRewardItemCountMultiplier ?? 1) != 1) {
|
||||
if (inventory.relicRewardItemCountMultiplier && inventory.relicRewardItemCountMultiplier != 1) {
|
||||
reward = {
|
||||
...reward,
|
||||
itemCount: reward.itemCount * config.relicRewardItemCountMultiplier
|
||||
itemCount: reward.itemCount * inventory.relicRewardItemCountMultiplier
|
||||
};
|
||||
}
|
||||
logger.debug(`relic rolled`, reward);
|
||||
|
||||
12
src/index.ts
12
src/index.ts
@ -19,6 +19,7 @@ logger.info("Starting up...");
|
||||
// Proceed with normal startup: bring up config watcher service, validate config, connect to MongoDB, and finally start listening for HTTP.
|
||||
import mongoose from "mongoose";
|
||||
import path from "path";
|
||||
import child_process from "child_process";
|
||||
import { JSONStringify } from "json-with-bigint";
|
||||
import { startWebServer } from "./services/webService.ts";
|
||||
import { validateConfig } from "./services/configWatcherService.ts";
|
||||
@ -43,6 +44,17 @@ mongoose
|
||||
|
||||
startWebServer();
|
||||
|
||||
if (config.ircExecutable) {
|
||||
logger.info(`Starting IRC server: ${config.ircExecutable}`);
|
||||
child_process.execFile(config.ircExecutable, (error, _stdout, _stderr) => {
|
||||
if (error) {
|
||||
logger.warn(`Failed to start IRC server`, error);
|
||||
} else {
|
||||
logger.warn(`IRC server terminated unexpectedly`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void updateWorldStateCollections();
|
||||
setInterval(() => {
|
||||
void updateWorldStateCollections();
|
||||
|
||||
@ -88,7 +88,9 @@ import type {
|
||||
IGoalProgressDatabase,
|
||||
IGoalProgressClient,
|
||||
IKubrowPetPrintClient,
|
||||
IKubrowPetPrintDatabase
|
||||
IKubrowPetPrintDatabase,
|
||||
INokkoColony,
|
||||
IJournalEntry
|
||||
} from "../../types/inventoryTypes/inventoryTypes.ts";
|
||||
import { equipmentKeys } from "../../types/inventoryTypes/inventoryTypes.ts";
|
||||
import type { IOid, ITypeCount } from "../../types/commonTypes.ts";
|
||||
@ -146,7 +148,8 @@ const focusUpgradeSchema = new Schema<IFocusUpgrade>(
|
||||
{
|
||||
ItemType: String,
|
||||
Level: Number,
|
||||
IsUniversal: Boolean
|
||||
IsUniversal: Boolean,
|
||||
IsActive: Number
|
||||
},
|
||||
{ _id: false }
|
||||
);
|
||||
@ -1423,6 +1426,22 @@ const hubNpcCustomizationSchema = new Schema<IHubNpcCustomization>(
|
||||
{ _id: false }
|
||||
);
|
||||
|
||||
const journalEntrySchema = new Schema<IJournalEntry>(
|
||||
{
|
||||
EntryType: String,
|
||||
Progress: Number
|
||||
},
|
||||
{ _id: false }
|
||||
);
|
||||
|
||||
const nokkoColonySchema = new Schema<INokkoColony>(
|
||||
{
|
||||
FeedLevel: Number,
|
||||
JournalEntries: [journalEntrySchema]
|
||||
},
|
||||
{ _id: false }
|
||||
);
|
||||
|
||||
const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
||||
{
|
||||
accountOwnerId: Schema.Types.ObjectId,
|
||||
@ -1468,6 +1487,9 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
||||
nemesisHintProgressMultiplierGrineer: Number,
|
||||
nemesisHintProgressMultiplierCorpus: Number,
|
||||
nemesisExtraWeapon: Number,
|
||||
spoofMasteryRank: { type: Number, default: -1 },
|
||||
relicRewardItemCountMultiplier: { type: Number, default: 1 },
|
||||
nightwaveStandingMultiplier: { type: Number, default: 1 },
|
||||
|
||||
SubscribedToEmails: { type: Number, default: 0 },
|
||||
SubscribedToEmailsPersonalized: { type: Number, default: 0 },
|
||||
@ -1542,6 +1564,8 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
||||
FocusAbility: String,
|
||||
//The treeways of the Focus school.(Active and passive Ability)
|
||||
FocusUpgrades: [focusUpgradeSchema],
|
||||
//Focus 2.0 Pool
|
||||
FocusCapacity: Number,
|
||||
|
||||
//Achievement
|
||||
ChallengeProgress: [challengeProgressSchema],
|
||||
@ -1834,7 +1858,9 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
||||
|
||||
ClaimedJunctionChallengeRewards: { type: [String], default: undefined },
|
||||
|
||||
SpecialItemRewardAttenuation: { type: [rewardAttenutationSchema], default: undefined }
|
||||
SpecialItemRewardAttenuation: { type: [rewardAttenutationSchema], default: undefined },
|
||||
|
||||
NokkoColony: { type: nokkoColonySchema, default: undefined }
|
||||
},
|
||||
{ timestamps: { createdAt: "Created", updatedAt: false } }
|
||||
);
|
||||
|
||||
@ -50,6 +50,7 @@ import { dronesController } from "../controllers/api/dronesController.ts";
|
||||
import { endlessXpController } from "../controllers/api/endlessXpController.ts";
|
||||
import { entratiLabConquestModeController } from "../controllers/api/entratiLabConquestModeController.ts";
|
||||
import { evolveWeaponController } from "../controllers/api/evolveWeaponController.ts";
|
||||
import { feedPrinceController } from "../controllers/api/feedPrinceController.ts";
|
||||
import { findSessionsController } from "../controllers/api/findSessionsController.ts";
|
||||
import { fishmongerController } from "../controllers/api/fishmongerController.ts";
|
||||
import { focusController } from "../controllers/api/focusController.ts";
|
||||
@ -116,6 +117,7 @@ import { removeFromGuildController } from "../controllers/api/removeFromGuildCon
|
||||
import { removeIgnoredUserController } from "../controllers/api/removeIgnoredUserController.ts";
|
||||
import { renamePetController } from "../controllers/api/renamePetController.ts";
|
||||
import { rerollRandomModController } from "../controllers/api/rerollRandomModController.ts";
|
||||
import { researchMushroomController } from "../controllers/api/researchMushroomController.ts";
|
||||
import { resetQuestProgressController } from "../controllers/api/resetQuestProgressController.ts";
|
||||
import { retrievePetFromStasisController } from "../controllers/api/retrievePetFromStasisController.ts";
|
||||
import { saveDialogueController } from "../controllers/api/saveDialogueController.ts";
|
||||
@ -271,6 +273,7 @@ apiRouter.post("/drones.php", dronesController);
|
||||
apiRouter.post("/endlessXp.php", endlessXpController);
|
||||
apiRouter.post("/entratiLabConquestMode.php", entratiLabConquestModeController);
|
||||
apiRouter.post("/evolveWeapon.php", evolveWeaponController);
|
||||
apiRouter.post("/feedPrince.php", feedPrinceController);
|
||||
apiRouter.post("/findSessions.php", findSessionsController);
|
||||
apiRouter.post("/fishmonger.php", fishmongerController);
|
||||
apiRouter.post("/focus.php", focusController);
|
||||
@ -318,6 +321,7 @@ apiRouter.post("/removeFromGuild.php", removeFromGuildController);
|
||||
apiRouter.post("/removeIgnoredUser.php", removeIgnoredUserController);
|
||||
apiRouter.post("/renamePet.php", renamePetController);
|
||||
apiRouter.post("/rerollRandomMod.php", rerollRandomModController);
|
||||
apiRouter.post("/researchMushroom.php", researchMushroomController);
|
||||
apiRouter.post("/retrievePetFromStasis.php", retrievePetFromStasisController);
|
||||
apiRouter.post("/saveDialogue.php", saveDialogueController);
|
||||
apiRouter.post("/saveLoadout.php", saveLoadoutController);
|
||||
|
||||
@ -22,6 +22,7 @@ import { unlockAllScansController } from "../controllers/custom/unlockAllScansCo
|
||||
import { unlockAllShipFeaturesController } from "../controllers/custom/unlockAllShipFeaturesController.ts";
|
||||
import { unlockAllCapturaScenesController } from "../controllers/custom/unlockAllCapturaScenesController.ts";
|
||||
import { removeCustomizationController } from "../controllers/custom/removeCustomizationController.ts";
|
||||
import { removeIsNewController } from "../controllers/custom/removeIsNewController.ts";
|
||||
|
||||
import { abilityOverrideController } from "../controllers/custom/abilityOverrideController.ts";
|
||||
import { createAccountController } from "../controllers/custom/createAccountController.ts";
|
||||
@ -34,7 +35,7 @@ import {
|
||||
fundTechProjectController,
|
||||
removeTechProjectController
|
||||
} from "../controllers/custom/techProjectController.ts";
|
||||
import { addVaultDecoRecipeController } from "../controllers/custom/addVaultDecoRecipeController.ts";
|
||||
import { addVaultTypeCountController } from "../controllers/custom/addVaultTypeCountController.ts";
|
||||
import { addXpController } from "../controllers/custom/addXpController.ts";
|
||||
import { importController } from "../controllers/custom/importController.ts";
|
||||
import { manageQuestsController } from "../controllers/custom/manageQuestsController.ts";
|
||||
@ -73,6 +74,7 @@ customRouter.get("/unlockAllScans", unlockAllScansController);
|
||||
customRouter.get("/unlockAllShipFeatures", unlockAllShipFeaturesController);
|
||||
customRouter.get("/unlockAllCapturaScenes", unlockAllCapturaScenesController);
|
||||
customRouter.get("/removeCustomization", removeCustomizationController);
|
||||
customRouter.get("/removeIsNew", removeIsNewController);
|
||||
|
||||
customRouter.post("/abilityOverride", abilityOverrideController);
|
||||
customRouter.post("/createAccount", createAccountController);
|
||||
@ -81,7 +83,7 @@ customRouter.post("/addCurrency", addCurrencyController);
|
||||
customRouter.post("/addItems", addItemsController);
|
||||
customRouter.post("/addTechProject", addTechProjectController);
|
||||
customRouter.post("/removeTechProject", removeTechProjectController);
|
||||
customRouter.post("/addVaultDecoRecipe", addVaultDecoRecipeController);
|
||||
customRouter.post("/addVaultTypeCount", addVaultTypeCountController);
|
||||
customRouter.post("/fundTechProject", fundTechProjectController);
|
||||
customRouter.post("/completeTechProject", completeTechProjectsController);
|
||||
customRouter.post("/addXp", addXpController);
|
||||
|
||||
@ -15,6 +15,7 @@ export interface IConfig {
|
||||
bindAddress?: string;
|
||||
httpPort?: number;
|
||||
httpsPort?: number;
|
||||
ircExecutable?: string;
|
||||
ircAddress?: string;
|
||||
hubAddress?: string;
|
||||
nrsAddress?: string;
|
||||
@ -24,9 +25,6 @@ export interface IConfig {
|
||||
unlockAllSkins?: boolean;
|
||||
fullyStockedVendors?: boolean;
|
||||
skipClanKeyCrafting?: boolean;
|
||||
spoofMasteryRank?: number;
|
||||
relicRewardItemCountMultiplier?: number;
|
||||
nightwaveStandingMultiplier?: number;
|
||||
unfaithfulBugFixes?: {
|
||||
ignore1999LastRegionPlayed?: boolean;
|
||||
fixXtraCheeseTimer?: boolean;
|
||||
@ -41,7 +39,7 @@ export interface IConfig {
|
||||
baroAlwaysAvailable?: boolean;
|
||||
baroFullyStocked?: boolean;
|
||||
varziaFullyStocked?: boolean;
|
||||
wolfHunt?: boolean;
|
||||
wolfHunt?: number;
|
||||
orphixVenom?: boolean;
|
||||
longShadow?: boolean;
|
||||
hallowedFlame?: boolean;
|
||||
@ -83,6 +81,21 @@ export interface IConfig {
|
||||
}
|
||||
|
||||
export const configRemovedOptionsKeys = [
|
||||
"unlockallShipFeatures",
|
||||
"testQuestKey",
|
||||
"lockTime",
|
||||
"starDays",
|
||||
"platformCDNs",
|
||||
"completeAllQuests",
|
||||
"worldSeed",
|
||||
"unlockAllQuests",
|
||||
"unlockAllMissions",
|
||||
"version",
|
||||
"matchmakingBuildId",
|
||||
"buildLabel",
|
||||
"infiniteResources",
|
||||
"testMission",
|
||||
"skipStoryModeChoice",
|
||||
"NRS",
|
||||
"myIrcAddresses",
|
||||
"skipAllDialogue",
|
||||
@ -134,7 +147,10 @@ export const configRemovedOptionsKeys = [
|
||||
"fastClanAscension",
|
||||
"unlockAllFlavourItems",
|
||||
"unlockAllShipDecorations",
|
||||
"unlockAllDecoRecipes"
|
||||
"unlockAllDecoRecipes",
|
||||
"spoofMasteryRank",
|
||||
"relicRewardItemCountMultiplier",
|
||||
"nightwaveStandingMultiplier"
|
||||
];
|
||||
|
||||
export const configPath = path.join(repoDir, args.configPath ?? "config.json");
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import type { IFriendInfo } from "../types/friendTypes.ts";
|
||||
import { getInventory } from "./inventoryService.ts";
|
||||
import { config } from "./configService.ts";
|
||||
import { Account } from "../models/loginModel.ts";
|
||||
import type { Types } from "mongoose";
|
||||
import { Friendship } from "../models/friendModel.ts";
|
||||
@ -13,8 +12,8 @@ export const addAccountDataToFriendInfo = async (info: IFriendInfo): Promise<voi
|
||||
};
|
||||
|
||||
export const addInventoryDataToFriendInfo = async (info: IFriendInfo): Promise<void> => {
|
||||
const inventory = await getInventory(fromOid(info._id), "PlayerLevel ActiveAvatarImageType");
|
||||
info.PlayerLevel = config.spoofMasteryRank == -1 ? inventory.PlayerLevel : config.spoofMasteryRank;
|
||||
const inventory = await getInventory(fromOid(info._id), "PlayerLevel ActiveAvatarImageType spoofMasteryRank");
|
||||
info.PlayerLevel = inventory.spoofMasteryRank == -1 ? inventory.PlayerLevel : inventory.spoofMasteryRank;
|
||||
info.ActiveAvatarImageType = inventory.ActiveAvatarImageType;
|
||||
};
|
||||
|
||||
|
||||
@ -117,6 +117,7 @@ export const createInventory = async (
|
||||
inventory.PlayedParkourTutorial = true;
|
||||
await addStartingGear(inventory);
|
||||
await completeQuest(inventory, "/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain");
|
||||
await completeQuest(inventory, "/Lotus/Types/Keys/ModQuest/ModQuestKeyChain");
|
||||
|
||||
const completedMissions = ["SolNode27", "SolNode89", "SolNode63", "SolNode85", "SolNode15", "SolNode79"];
|
||||
|
||||
@ -134,16 +135,6 @@ export const createInventory = async (
|
||||
}
|
||||
};
|
||||
|
||||
//TODO: RawUpgrades might need to return a LastAdded
|
||||
const awakeningRewards = [
|
||||
"/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem1",
|
||||
"/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem2",
|
||||
"/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem3",
|
||||
"/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem4",
|
||||
"/Lotus/Types/Restoratives/LisetAutoHack",
|
||||
"/Lotus/Upgrades/Mods/Warframe/AvatarShieldMaxMod"
|
||||
];
|
||||
|
||||
export const addStartingGear = async (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
startingGear?: TPartialStartingGear
|
||||
@ -196,6 +187,14 @@ export const addStartingGear = async (
|
||||
inventory.RegularCredits = 3000;
|
||||
inventoryChanges.RegularCredits = 3000;
|
||||
|
||||
const awakeningRewards = [
|
||||
"/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem1",
|
||||
"/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem2",
|
||||
"/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem3",
|
||||
"/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem4",
|
||||
"/Lotus/Types/Restoratives/LisetAutoHack"
|
||||
];
|
||||
|
||||
for (const item of awakeningRewards) {
|
||||
const inventoryDelta = await addItem(inventory, item);
|
||||
combineInventoryChanges(inventoryChanges, inventoryDelta);
|
||||
@ -389,7 +388,7 @@ export const addItem = async (
|
||||
};
|
||||
} else if (ExportResources[typeName].productCategory == "CrewShips") {
|
||||
return {
|
||||
...addCrewShip(inventory, typeName),
|
||||
...(await addCrewShip(inventory, typeName)),
|
||||
// fix to unlock railjack modding, item bellow supposed to be obtained from archwing quest
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
...(!inventory.CrewShipHarnesses?.length
|
||||
@ -1392,7 +1391,10 @@ export const addStanding = (
|
||||
|
||||
// TODO: AffiliationMods support (Nightwave).
|
||||
export const updateGeneric = async (data: IGenericUpdate, accountId: string): Promise<IUpdateNodeIntrosResponse> => {
|
||||
const inventory = await getInventory(accountId, "NodeIntrosCompleted MiscItems ShipDecorations");
|
||||
const inventory = await getInventory(
|
||||
accountId,
|
||||
"NodeIntrosCompleted MiscItems ShipDecorations FlavourItems WeaponSkins"
|
||||
);
|
||||
|
||||
// Make it an array for easier parsing.
|
||||
if (typeof data.NodeIntrosCompleted === "string") {
|
||||
@ -1401,6 +1403,12 @@ export const updateGeneric = async (data: IGenericUpdate, accountId: string): Pr
|
||||
|
||||
const inventoryChanges: IInventoryChanges = {};
|
||||
for (const node of data.NodeIntrosCompleted) {
|
||||
if (inventory.NodeIntrosCompleted.indexOf(node) != -1) {
|
||||
continue;
|
||||
}
|
||||
inventory.NodeIntrosCompleted.push(node);
|
||||
logger.debug(`completed dialogue/cutscene for ${node}`);
|
||||
|
||||
if (node == "TC2025") {
|
||||
inventoryChanges.ShipDecorations = [
|
||||
{
|
||||
@ -1421,16 +1429,15 @@ export const updateGeneric = async (data: IGenericUpdate, accountId: string): Pr
|
||||
await addEmailItem(inventory, "/Lotus/Types/Items/EmailItems/BeatCaliberChicksEmailItem", inventoryChanges);
|
||||
} else if (node == "ClearedFiveLoops") {
|
||||
await addEmailItem(inventory, "/Lotus/Types/Items/EmailItems/ClearedFiveLoopsEmailItem", inventoryChanges);
|
||||
} else if (node == "NokkoVisions_AllCompleted") {
|
||||
addCustomization(
|
||||
inventory,
|
||||
"/Lotus/Types/StoreItems/AvatarImages/Warframes/NokkoBabySecretGlyph",
|
||||
inventoryChanges
|
||||
);
|
||||
addSkin(inventory, "/Lotus/Upgrades/Skins/Clan/NokkoBabySecretEmblemItem", inventoryChanges);
|
||||
}
|
||||
}
|
||||
|
||||
// Combine the two arrays into one.
|
||||
data.NodeIntrosCompleted = inventory.NodeIntrosCompleted.concat(data.NodeIntrosCompleted);
|
||||
|
||||
// Remove duplicate entries.
|
||||
const nodes = [...new Set(data.NodeIntrosCompleted)];
|
||||
|
||||
inventory.NodeIntrosCompleted = nodes;
|
||||
await inventory.save();
|
||||
|
||||
return {
|
||||
@ -1544,17 +1551,31 @@ export const addCrewShipSalvagedWeaponSkin = (
|
||||
return inventoryChanges;
|
||||
};
|
||||
|
||||
const addCrewShip = (
|
||||
const addCrewShip = async (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
typeName: string,
|
||||
inventoryChanges: IInventoryChanges = {}
|
||||
): IInventoryChanges => {
|
||||
): Promise<IInventoryChanges> => {
|
||||
if (inventory.CrewShips.length != 0) {
|
||||
logger.warn("refusing to add CrewShip because account already has one");
|
||||
} else {
|
||||
const index = inventory.CrewShips.push({ ItemType: typeName }) - 1;
|
||||
inventoryChanges.CrewShips ??= [];
|
||||
inventoryChanges.CrewShips.push(inventory.CrewShips[index].toJSON<IEquipmentClient>());
|
||||
const railjackQuest = inventory.QuestKeys.find(
|
||||
qk => qk.ItemType === "/Lotus/Types/Keys/RailJackBuildQuest/RailjackBuildQuestKeyChain"
|
||||
);
|
||||
if (!railjackQuest || !railjackQuest.Completed) {
|
||||
const questChanges = await completeQuest(
|
||||
inventory,
|
||||
"/Lotus/Types/Keys/RailJackBuildQuest/RailjackBuildQuestKeyChain",
|
||||
false
|
||||
);
|
||||
if (questChanges) {
|
||||
inventoryChanges.QuestKeys ??= [];
|
||||
inventoryChanges.QuestKeys.push(questChanges);
|
||||
}
|
||||
}
|
||||
}
|
||||
return inventoryChanges;
|
||||
};
|
||||
@ -2131,7 +2152,7 @@ export const addChallenges = async (
|
||||
];
|
||||
}
|
||||
|
||||
const standingToAdd = meta.standing! * (config.nightwaveStandingMultiplier ?? 1);
|
||||
const standingToAdd = meta.standing! * (inventory.nightwaveStandingMultiplier ?? 1);
|
||||
affiliation.Standing += standingToAdd;
|
||||
if (affiliationMods.length == 0) {
|
||||
affiliationMods.push({ Tag: nightwaveSyndicateTag });
|
||||
@ -2159,7 +2180,7 @@ export const addMissionComplete = (inventory: TInventoryDatabaseDocument, { Tag,
|
||||
|
||||
if (itemIndex !== -1) {
|
||||
Missions[itemIndex].Completes += Completes;
|
||||
if (Tier) {
|
||||
if (Completes && Tier) {
|
||||
Missions[itemIndex].Tier = Tier;
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -81,7 +81,8 @@ export const getRecipe = (uniqueName: string): IRecipe | undefined => {
|
||||
ItemCount: 600
|
||||
}
|
||||
],
|
||||
excludeFromMarket: true
|
||||
excludeFromMarket: true,
|
||||
tradable: false
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -65,7 +65,7 @@ export const createPersonalRooms = async (accountId: Types.ObjectId, shipId: Typ
|
||||
activeShipId: shipId
|
||||
});
|
||||
if (config.skipTutorial) {
|
||||
// unlocked during Vor's Prize
|
||||
// unlocked during Vor's Prize and The Teacher quests
|
||||
const defaultFeatures = [
|
||||
"/Lotus/Types/Items/ShipFeatureItems/MercuryNavigationFeatureItem",
|
||||
"/Lotus/Types/Items/ShipFeatureItems/ArsenalFeatureItem",
|
||||
|
||||
@ -8,6 +8,7 @@ import {
|
||||
ExportAnimals,
|
||||
ExportEnemies,
|
||||
ExportFusionBundles,
|
||||
ExportKeys,
|
||||
ExportRegions,
|
||||
ExportRelics,
|
||||
ExportRewards
|
||||
@ -242,7 +243,7 @@ export const addMissionInventoryUpdates = async (
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inventoryUpdates.MissionStatus == "GS_SUCCESS" && inventoryUpdates.RewardInfo.jobId) {
|
||||
if (inventoryUpdates.RewardInfo.jobId) {
|
||||
// e.g. for Profit-Taker Phase 1:
|
||||
// JobTier: -6,
|
||||
// jobId: '/Lotus/Types/Gameplay/Venus/Jobs/Heists/HeistProfitTakerBountyOne_-6_SolarisUnitedHub1_663a71c80000000000000025_EudicoHeists',
|
||||
@ -250,7 +251,10 @@ export const addMissionInventoryUpdates = async (
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [bounty, tier, hub, id, tag] = inventoryUpdates.RewardInfo.jobId.split("_");
|
||||
if (tag == "EudicoHeists") {
|
||||
if (
|
||||
(tag == "EudicoHeists" && inventoryUpdates.MissionStatus == "GS_SUCCESS") ||
|
||||
(tag == "NokkoColony" && inventoryUpdates.RewardInfo.JobStage == 4)
|
||||
) {
|
||||
inventory.CompletedJobChains ??= [];
|
||||
let chain = inventory.CompletedJobChains.find(x => x.LocationTag == tag);
|
||||
if (!chain) {
|
||||
@ -309,6 +313,9 @@ export const addMissionInventoryUpdates = async (
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "Missions":
|
||||
addMissionComplete(inventory, value);
|
||||
break;
|
||||
case "LastRegionPlayed":
|
||||
if (!(config.unfaithfulBugFixes?.ignore1999LastRegionPlayed && value === "1999MapName")) {
|
||||
inventory.LastRegionPlayed = value;
|
||||
@ -1125,7 +1132,8 @@ export const addMissionRewards = async (
|
||||
RegularCredits: creditDrops,
|
||||
VoidTearParticipantsCurrWave: voidTearWave,
|
||||
StrippedItems: strippedItems,
|
||||
AffiliationChanges: AffiliationMods
|
||||
AffiliationChanges: AffiliationMods,
|
||||
InvasionProgress: invasionProgress
|
||||
}: IMissionInventoryUpdateRequest,
|
||||
firstCompletion: boolean
|
||||
): Promise<AddMissionRewardsReturnType> => {
|
||||
@ -1141,6 +1149,7 @@ export const addMissionRewards = async (
|
||||
const MissionRewards: IMissionReward[] = getRandomMissionDrops(
|
||||
inventory,
|
||||
rewardInfo,
|
||||
levelKeyName,
|
||||
missions,
|
||||
wagerTier,
|
||||
firstCompletion
|
||||
@ -1174,6 +1183,19 @@ export const addMissionRewards = async (
|
||||
|
||||
//inventory change is what the client has not rewarded itself, also the client needs to know the credit changes for display
|
||||
|
||||
if (invasionProgress) {
|
||||
for (const clientProgress of invasionProgress) {
|
||||
const dbProgress = inventory.QualifyingInvasions.find(x => x.invasionId.equals(clientProgress._id.$oid));
|
||||
if (dbProgress) {
|
||||
const run =
|
||||
(clientProgress.AttackerScore > clientProgress.DefenderScore
|
||||
? dbProgress.AttackerScore
|
||||
: dbProgress.DefenderScore) - 1;
|
||||
missionCompletionCredits += 1000 * Math.min(run, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rewardInfo.goalId) {
|
||||
const goal = getWorldState().Goals.find(x => x._id.$oid == rewardInfo.goalId);
|
||||
if (goal) {
|
||||
@ -1226,9 +1248,6 @@ export const addMissionRewards = async (
|
||||
if (missions && missions.Tag in ExportRegions) {
|
||||
const node = ExportRegions[missions.Tag];
|
||||
|
||||
// cannot add this with normal updates because { Tier: 1 } would mark the SP node as completed even on a failure
|
||||
addMissionComplete(inventory, missions);
|
||||
|
||||
//node based credit rewards for mission completion
|
||||
if (isEligibleForCreditReward(rewardInfo, missions, node)) {
|
||||
const levelCreditReward = getLevelCreditRewards(node);
|
||||
@ -1498,7 +1517,7 @@ export const addMissionRewards = async (
|
||||
syndicateEntry = Goals.find(m => m._id.$oid === syndicateMissionId);
|
||||
if (syndicateEntry) syndicateEntry.Tag = syndicateEntry.JobAffiliationTag!;
|
||||
}
|
||||
if (syndicateEntry && syndicateEntry.Jobs) {
|
||||
if (syndicateEntry && syndicateEntry.Jobs && !jobType.startsWith("/Lotus/Types/Gameplay/NokkoColony/Jobs")) {
|
||||
let currentJob = syndicateEntry.Jobs[rewardInfo.JobTier!];
|
||||
if (
|
||||
[
|
||||
@ -1688,8 +1707,8 @@ export const addCredits = async (
|
||||
finalCredits.TotalCredits[1] += finalCredits.TotalCredits[1];
|
||||
}
|
||||
if ((inventory.Boosters.find(x => x.ItemType == "/Lotus/Types/Boosters/CreditBlessing")?.ExpiryDate ?? 0) > now) {
|
||||
inventory.RegularCredits += finalCredits.TotalCredits[1];
|
||||
finalCredits.TotalCredits[1] += finalCredits.TotalCredits[1];
|
||||
inventory.RegularCredits += finalCredits.TotalCredits[1] * 0.25;
|
||||
finalCredits.TotalCredits[1] += finalCredits.TotalCredits[1] * 0.25;
|
||||
}
|
||||
|
||||
return finalCredits;
|
||||
@ -1756,6 +1775,7 @@ function getLevelCreditRewards(node: IRegion): number {
|
||||
function getRandomMissionDrops(
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
RewardInfo: IRewardInfo,
|
||||
levelKeyName: string | undefined,
|
||||
mission: IMission | undefined,
|
||||
tierOverride: number | undefined,
|
||||
firstCompletion: boolean
|
||||
@ -2005,6 +2025,19 @@ function getRandomMissionDrops(
|
||||
xpAmounts: [1000]
|
||||
};
|
||||
RewardInfo.Q = false; // Just in case
|
||||
} else if (jobType.startsWith("/Lotus/Types/Gameplay/NokkoColony/Jobs/NokkoJob")) {
|
||||
job = {
|
||||
rewards: jobType
|
||||
.replace("SteelPath", "Steel")
|
||||
.replace(
|
||||
"/Lotus/Types/Gameplay/NokkoColony/Jobs/NokkoJob",
|
||||
"Lotus/Types/Game/MissionDecks/NokkoColonyRewards/NokkoColonyRewards"
|
||||
),
|
||||
masteryReq: 0,
|
||||
minEnemyLevel: 30,
|
||||
maxEnemyLevel: 40,
|
||||
xpAmounts: [0, 0, 0, 0, 0]
|
||||
};
|
||||
} else {
|
||||
const tierMap = {
|
||||
Two: "B",
|
||||
@ -2048,14 +2081,22 @@ function getRandomMissionDrops(
|
||||
} else if (totalStage == 5 && curentStage == 4) {
|
||||
tableIndex = 2;
|
||||
}
|
||||
|
||||
rotations = [tableIndex];
|
||||
if (jobType.startsWith("/Lotus/Types/Gameplay/NokkoColony/Jobs/NokkoJob")) {
|
||||
if (RewardInfo.JobStage === job.xpAmounts.length - 1) {
|
||||
rotations = [0, 1, 2];
|
||||
} else {
|
||||
rewardManifests = [];
|
||||
}
|
||||
} else {
|
||||
rotations = [tableIndex];
|
||||
}
|
||||
} else {
|
||||
rotations = [0];
|
||||
}
|
||||
if (
|
||||
RewardInfo.Q &&
|
||||
(RewardInfo.JobStage === job.xpAmounts.length - 1 || jobType.endsWith("VaultBounty")) &&
|
||||
!jobType.startsWith("/Lotus/Types/Gameplay/NokkoColony/Jobs/NokkoJob") &&
|
||||
!isEndlessJob
|
||||
) {
|
||||
rotations.push(ExportRewards[job.rewards].length - 1);
|
||||
@ -2193,7 +2234,7 @@ function getRandomMissionDrops(
|
||||
}
|
||||
}
|
||||
|
||||
if (region.cacheRewardManifest && RewardInfo.EnemyCachesFound) {
|
||||
if (region.cacheRewardManifest && RewardInfo.EnemyCachesFound && !RewardInfo.goalId) {
|
||||
const deck = ExportRewards[region.cacheRewardManifest];
|
||||
for (let rotation = 0; rotation != RewardInfo.EnemyCachesFound; ++rotation) {
|
||||
const drop = getRandomRewardByChance(deck[rotation]);
|
||||
@ -2259,6 +2300,71 @@ function getRandomMissionDrops(
|
||||
}
|
||||
}
|
||||
|
||||
if (RewardInfo.EnemyCachesFound) {
|
||||
if (RewardInfo.goalId) {
|
||||
const goal = getWorldState().Goals.find(x => x._id.$oid == RewardInfo.goalId);
|
||||
if (goal) {
|
||||
let currentMissionKey: string | undefined;
|
||||
if (RewardInfo.node == goal.Node) {
|
||||
currentMissionKey = goal.MissionKeyName;
|
||||
} else if (goal.ConcurrentNodes && goal.ConcurrentMissionKeyNames) {
|
||||
for (let i = 0; i < goal.ConcurrentNodes.length; i++) {
|
||||
if (RewardInfo.node == goal.ConcurrentNodes[i]) {
|
||||
currentMissionKey = goal.ConcurrentMissionKeyNames[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (currentMissionKey) {
|
||||
const keyMeta = ExportKeys[currentMissionKey];
|
||||
if (keyMeta.cacheRewardManifest) {
|
||||
const deck = ExportRewards[keyMeta.cacheRewardManifest];
|
||||
for (let rotation = 0; rotation != RewardInfo.EnemyCachesFound; ++rotation) {
|
||||
const drop = getRandomRewardByChance(deck[rotation]);
|
||||
if (drop) {
|
||||
drops.push({
|
||||
StoreItem: drop.type,
|
||||
ItemCount: drop.itemCount,
|
||||
FromEnemyCache: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (RewardInfo.alertId) {
|
||||
const alert = getWorldState().Alerts.find(x => x._id.$oid == RewardInfo.alertId);
|
||||
if (alert && alert.MissionInfo.enemyCacheOverride) {
|
||||
const deck = ExportRewards[alert.MissionInfo.enemyCacheOverride];
|
||||
for (let rotation = 0; rotation != RewardInfo.EnemyCachesFound; ++rotation) {
|
||||
const drop = getRandomRewardByChance(deck[rotation]);
|
||||
if (drop) {
|
||||
drops.push({
|
||||
StoreItem: drop.type,
|
||||
ItemCount: drop.itemCount,
|
||||
FromEnemyCache: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (levelKeyName) {
|
||||
const keyMeta = ExportKeys[levelKeyName];
|
||||
if (keyMeta.cacheRewardManifest) {
|
||||
const deck = ExportRewards[keyMeta.cacheRewardManifest];
|
||||
for (let rotation = 0; rotation != RewardInfo.EnemyCachesFound; ++rotation) {
|
||||
const drop = getRandomRewardByChance(deck[rotation]);
|
||||
if (drop) {
|
||||
drops.push({
|
||||
StoreItem: drop.type,
|
||||
ItemCount: drop.itemCount,
|
||||
FromEnemyCache: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inventory.missionsCanGiveAllRelics) {
|
||||
for (const drop of drops) {
|
||||
const itemType = fromStoreItem(drop.StoreItem);
|
||||
@ -2479,6 +2585,18 @@ const goalMessagesByKey: Record<string, { sndr: string; msg: string; sub: string
|
||||
sub: "/Lotus/Language/Inbox/WaterFightRewardSubjectD",
|
||||
icon: "/Lotus/Interface/Icons/Npcs/Grineer/KelaDeThaym.png"
|
||||
},
|
||||
"/Lotus/Types/Keys/WolfTacAlertA": {
|
||||
sndr: "/Lotus/Language/Bosses/NoraNight",
|
||||
msg: "/Lotus/Language/Inbox/WolfTacAlertBody",
|
||||
sub: "/Lotus/Language/Inbox/WolfTacAlertTitle",
|
||||
icon: "/Lotus/Interface/Icons/Npcs/Seasonal/NoraNight.png"
|
||||
},
|
||||
"/Lotus/Types/Keys/WolfTacAlertxB": {
|
||||
sndr: "/Lotus/Language/Bosses/NoraNight",
|
||||
msg: "/Lotus/Language/Inbox/WolfTacAlertHardBody",
|
||||
sub: "/Lotus/Language/Inbox/WolfTacAlertHardTitle",
|
||||
icon: "/Lotus/Interface/Icons/Npcs/Seasonal/NoraNight.png"
|
||||
},
|
||||
"/Lotus/Types/Keys/WolfTacAlertReduxA": {
|
||||
sndr: "/Lotus/Language/Bosses/NoraNight",
|
||||
msg: "/Lotus/Language/Inbox/WolfTacAlertBody",
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { PersonalRooms } from "../models/personalRoomsModel.ts";
|
||||
import { addItem, getInventory } from "./inventoryService.ts";
|
||||
import { addItem } from "./inventoryService.ts";
|
||||
import type { IGardeningDatabase, TPersonalRoomsDatabaseDocument } from "../types/personalRoomsTypes.ts";
|
||||
import { getRandomElement } from "./rngService.ts";
|
||||
import type { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel.ts";
|
||||
import { logger } from "../utils/logger.ts";
|
||||
|
||||
export const getPersonalRooms = async (
|
||||
accountId: string,
|
||||
@ -15,19 +17,17 @@ export const getPersonalRooms = async (
|
||||
return personalRooms;
|
||||
};
|
||||
|
||||
export const updateShipFeature = async (accountId: string, shipFeature: string): Promise<void> => {
|
||||
const personalRooms = await getPersonalRooms(accountId);
|
||||
export const unlockShipFeature = async (inventory: TInventoryDatabaseDocument, shipFeature: string): Promise<void> => {
|
||||
const personalRooms = await getPersonalRooms(inventory.accountOwnerId.toString());
|
||||
|
||||
if (personalRooms.Ship.Features.includes(shipFeature)) {
|
||||
throw new Error(`ship feature ${shipFeature} already unlocked`);
|
||||
logger.warn(`ship feature ${shipFeature} already unlocked`);
|
||||
} else {
|
||||
personalRooms.Ship.Features.push(shipFeature);
|
||||
await personalRooms.save();
|
||||
}
|
||||
|
||||
personalRooms.Ship.Features.push(shipFeature);
|
||||
await personalRooms.save();
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
await addItem(inventory, shipFeature, -1);
|
||||
await inventory.save();
|
||||
const miscItem = inventory.MiscItems.find(x => x.ItemType === shipFeature);
|
||||
if (miscItem && miscItem.ItemCount > 0) await addItem(inventory, shipFeature, miscItem.ItemCount * -1);
|
||||
};
|
||||
|
||||
export const createGarden = (): IGardeningDatabase => {
|
||||
|
||||
@ -11,9 +11,10 @@ import { addFixedLevelRewards } from "./missionInventoryUpdateService.ts";
|
||||
import type { IInventoryChanges } from "../types/purchaseTypes.ts";
|
||||
import questCompletionItems from "../../static/fixed_responses/questCompletionRewards.json" with { type: "json" };
|
||||
import type { ITypeCount } from "../types/commonTypes.ts";
|
||||
import { addString } from "../helpers/stringHelpers.ts";
|
||||
|
||||
export interface IUpdateQuestRequest {
|
||||
QuestKeys: Omit<IQuestKeyDatabase, "CompletionDate">[];
|
||||
QuestKeys: IQuestKeyClient[];
|
||||
PS: string;
|
||||
questCompletion: boolean;
|
||||
PlayerShipEvents: unknown[];
|
||||
@ -36,6 +37,7 @@ export const updateQuestKey = async (
|
||||
throw new Error(`quest key ${questKeyUpdate[0].ItemType} not found`);
|
||||
}
|
||||
|
||||
delete questKeyUpdate[0].CompletionDate;
|
||||
inventory.QuestKeys[questKeyIndex].overwrite(questKeyUpdate[0]);
|
||||
|
||||
const inventoryChanges: IInventoryChanges = {};
|
||||
@ -115,7 +117,11 @@ export const addQuestKey = (
|
||||
return inventory.QuestKeys[index - 1].toJSON<IQuestKeyClient>();
|
||||
};
|
||||
|
||||
export const completeQuest = async (inventory: TInventoryDatabaseDocument, questKey: string): Promise<void> => {
|
||||
export const completeQuest = async (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
questKey: string,
|
||||
sendMessages: boolean = false
|
||||
): Promise<void | IQuestKeyClient> => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
const chainStages = ExportKeys[questKey]?.chainStages;
|
||||
|
||||
@ -133,8 +139,8 @@ export const completeQuest = async (inventory: TInventoryDatabaseDocument, quest
|
||||
unlock: true,
|
||||
Progress: Array.from({ length: chainStageTotal }, () => ({
|
||||
c: 0,
|
||||
i: false,
|
||||
m: false,
|
||||
i: true,
|
||||
m: true,
|
||||
b: []
|
||||
}))
|
||||
};
|
||||
@ -161,7 +167,7 @@ export const completeQuest = async (inventory: TInventoryDatabaseDocument, quest
|
||||
const stage = existingQuestKey.Progress[i];
|
||||
if (stage.c <= run) {
|
||||
stage.c = run;
|
||||
await giveKeyChainStageTriggered(inventory, { KeyChain: questKey, ChainStage: i });
|
||||
await giveKeyChainStageTriggered(inventory, { KeyChain: questKey, ChainStage: i }, sendMessages);
|
||||
await giveKeyChainMissionReward(inventory, { KeyChain: questKey, ChainStage: i });
|
||||
}
|
||||
}
|
||||
@ -170,7 +176,14 @@ export const completeQuest = async (inventory: TInventoryDatabaseDocument, quest
|
||||
existingQuestKey.Completed = true;
|
||||
existingQuestKey.CompletionDate = new Date();
|
||||
await handleQuestCompletion(inventory, questKey, undefined, run > 0);
|
||||
|
||||
if (questKey == "/Lotus/Types/Keys/ModQuest/ModQuestKeyChain") {
|
||||
// This would be set by the client during the equilogue, but since we're cheating through, we have to do it ourselves.
|
||||
addString(inventory.NodeIntrosCompleted, "ModQuestTeshinAccess");
|
||||
}
|
||||
}
|
||||
|
||||
return existingQuestKey.toJSON<IQuestKeyClient>();
|
||||
};
|
||||
|
||||
const getQuestCompletionItems = (questKey: string): ITypeCount[] | undefined => {
|
||||
@ -327,7 +340,8 @@ export const giveKeyChainItem = async (
|
||||
export const giveKeyChainMessage = async (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
keyChainInfo: IKeyChainRequest,
|
||||
questKey: IQuestKeyDatabase
|
||||
questKey: IQuestKeyDatabase,
|
||||
sendMessage: boolean = true
|
||||
): Promise<void> => {
|
||||
const keyChainMessage = getKeyChainMessage(keyChainInfo);
|
||||
|
||||
@ -336,7 +350,12 @@ export const giveKeyChainMessage = async (
|
||||
keyChainMessage.countedAtt = [];
|
||||
}
|
||||
|
||||
await createMessage(inventory.accountOwnerId, [keyChainMessage]);
|
||||
if (sendMessage) {
|
||||
await createMessage(inventory.accountOwnerId, [keyChainMessage]);
|
||||
} else {
|
||||
if (keyChainMessage.countedAtt?.length) await addItems(inventory, keyChainMessage.countedAtt);
|
||||
if (keyChainMessage.att?.length) await addItems(inventory, keyChainMessage.att);
|
||||
}
|
||||
|
||||
updateQuestStage(inventory, keyChainInfo, { m: true });
|
||||
};
|
||||
@ -384,7 +403,8 @@ export const giveKeyChainMissionReward = async (
|
||||
|
||||
export const giveKeyChainStageTriggered = async (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
keyChainInfo: IKeyChainRequest
|
||||
keyChainInfo: IKeyChainRequest,
|
||||
sendMessage: boolean = true
|
||||
): Promise<void> => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
const chainStages = ExportKeys[keyChainInfo.KeyChain]?.chainStages;
|
||||
@ -396,7 +416,7 @@ export const giveKeyChainStageTriggered = async (
|
||||
}
|
||||
|
||||
if (chainStages[keyChainInfo.ChainStage].messageToSendWhenTriggered) {
|
||||
await giveKeyChainMessage(inventory, keyChainInfo, questKey);
|
||||
await giveKeyChainMessage(inventory, keyChainInfo, questKey, sendMessage);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -35,7 +35,8 @@ import type {
|
||||
IVoidTrader,
|
||||
IVoidTraderOffer,
|
||||
IWorldState,
|
||||
TCircuitGameMode
|
||||
TCircuitGameMode,
|
||||
IFlashSale
|
||||
} from "../types/worldStateTypes.ts";
|
||||
import { toMongoDate, toOid, version_compare } from "../helpers/inventoryHelpers.ts";
|
||||
import { logger } from "../utils/logger.ts";
|
||||
@ -62,7 +63,7 @@ const sortieBosses = [
|
||||
|
||||
type TSortieBoss = (typeof sortieBosses)[number];
|
||||
|
||||
const sortieBossToFaction: Record<TSortieBoss, string> = {
|
||||
const sortieBossToFaction: Record<TSortieBoss, TFaction> = {
|
||||
SORTIE_BOSS_HYENA: "FC_CORPUS",
|
||||
SORTIE_BOSS_KELA: "FC_GRINEER",
|
||||
SORTIE_BOSS_VOR: "FC_GRINEER",
|
||||
@ -375,6 +376,11 @@ export const getSortie = (day: number): ISortie => {
|
||||
const selectedNodes: ISortieMission[] = [];
|
||||
const missionTypes = new Set();
|
||||
|
||||
if (enemyFaction == "FC_INFESTATION") {
|
||||
// MT_RETRIEVAL may not be chosen for infested enemies (https://onlyg.it/OpenWF/SpaceNinjaServer/issues/2907)
|
||||
missionTypes.add("MT_RETRIEVAL");
|
||||
}
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const randomIndex = rng.randomInt(0, nodes.length - 1);
|
||||
const node = nodes[randomIndex];
|
||||
@ -1580,21 +1586,16 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
||||
}
|
||||
|
||||
if (config.worldState?.qtccAlerts) {
|
||||
const activationTimeStamp = "1759327200000";
|
||||
const expiryTimeStamp = "2000000000000";
|
||||
|
||||
worldState.Alerts.push(
|
||||
{
|
||||
_id: {
|
||||
$oid: "68dc23c42e9d3acfa708ff3b"
|
||||
},
|
||||
Activation: {
|
||||
$date: {
|
||||
$numberLong: "1759327200000"
|
||||
}
|
||||
},
|
||||
Expiry: {
|
||||
$date: {
|
||||
$numberLong: "2000000000000"
|
||||
}
|
||||
},
|
||||
Activation: { $date: { $numberLong: activationTimeStamp } },
|
||||
Expiry: { $date: { $numberLong: expiryTimeStamp } },
|
||||
MissionInfo: {
|
||||
location: "SolNode123",
|
||||
missionType: "MT_SURVIVAL",
|
||||
@ -1618,16 +1619,8 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
||||
_id: {
|
||||
$oid: "68dc2466e298b4f04206687a"
|
||||
},
|
||||
Activation: {
|
||||
$date: {
|
||||
$numberLong: "1759327200000"
|
||||
}
|
||||
},
|
||||
Expiry: {
|
||||
$date: {
|
||||
$numberLong: "2000000000000"
|
||||
}
|
||||
},
|
||||
Activation: { $date: { $numberLong: activationTimeStamp } },
|
||||
Expiry: { $date: { $numberLong: expiryTimeStamp } },
|
||||
MissionInfo: {
|
||||
location: "SolNode149",
|
||||
missionType: "MT_DEFENSE",
|
||||
@ -1651,16 +1644,8 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
||||
_id: {
|
||||
$oid: "68dc26865e7cb56b820b4252"
|
||||
},
|
||||
Activation: {
|
||||
$date: {
|
||||
$numberLong: "1759327200000"
|
||||
}
|
||||
},
|
||||
Expiry: {
|
||||
$date: {
|
||||
$numberLong: "2000000000000"
|
||||
}
|
||||
},
|
||||
Activation: { $date: { $numberLong: activationTimeStamp } },
|
||||
Expiry: { $date: { $numberLong: expiryTimeStamp } },
|
||||
MissionInfo: {
|
||||
location: "SolNode39",
|
||||
missionType: "MT_EXCAVATE",
|
||||
@ -1681,6 +1666,72 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
||||
ForceUnlock: true
|
||||
}
|
||||
);
|
||||
|
||||
const storeItems: (Partial<IFlashSale> & { TypeName: string })[] = [
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/ImageConquera2021D", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Operator/Tattoos/TattooTennoI", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Operator/Tattoos/TattooTennoH", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Clan/QTCC2024EmblemItem", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/Conquera2024Display", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageConqueraGlyphVII", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageConqueraGlyphVI", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Interface/Graphics/CustomUI/ConqueraStyle", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Interface/Graphics/CustomUI/Backgrounds/ConqueraBackground", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/Conquera2021Deco", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/ImageConquera2022A", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/ImageConquera2021B", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/ImageConquera2021A", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Scarves/TnCharityRibbonSyandana", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/ImageConquera2021C", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/Venus/Conquera2023CommunityDisplay", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageConqueraGlyphUpdated", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/ImageConquera", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Sigils/QTCC2023ConqueraSigil", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Sigils/ConqueraSigil", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Effects/Conquera2022Ephemera", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Effects/ConqueraEphemera", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Armor/TnCharityRibbonArmor/ConqueraArmorL", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Armor/TnCharityRibbonArmor/ConqueraArmorA", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Armor/TnCharityRibbonArmor/ConqueraChestRibbon", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/Plushies/PlushyProtectorStalker", PremiumOverride: 35 }
|
||||
];
|
||||
|
||||
worldState.FlashSales.push(
|
||||
...storeItems.map(item => ({
|
||||
...{
|
||||
StartDate: { $date: { $numberLong: activationTimeStamp } },
|
||||
EndDate: { $date: { $numberLong: expiryTimeStamp } },
|
||||
ProductExpiryOverride: { $date: { $numberLong: expiryTimeStamp } },
|
||||
ShowInMarket: item.ShowInMarket ?? true,
|
||||
HideFromMarket: item.HideFromMarket ?? false,
|
||||
SupporterPack: item.SupporterPack ?? false,
|
||||
Discount: item.Discount ?? 0,
|
||||
BogoBuy: item.BogoBuy ?? 0,
|
||||
BogoGet: item.BogoGet ?? 0,
|
||||
RegularOverride: item.RegularOverride ?? 0,
|
||||
PremiumOverride: item.PremiumOverride ?? 0
|
||||
},
|
||||
...item
|
||||
}))
|
||||
);
|
||||
|
||||
const seasonalItems = storeItems.map(item => item.TypeName);
|
||||
|
||||
const seasonalCategory = worldState.InGameMarket.LandingPage.Categories.find(
|
||||
c => c.CategoryName == "COMMUNITY"
|
||||
);
|
||||
if (seasonalCategory) {
|
||||
seasonalCategory.Items ??= [];
|
||||
seasonalCategory.Items.push(...seasonalItems);
|
||||
} else {
|
||||
worldState.InGameMarket.LandingPage.Categories.push({
|
||||
CategoryName: "COMMUNITY",
|
||||
Name: "/Lotus/Language/Store/CommunityCategoryTitle",
|
||||
Icon: "community",
|
||||
AddToMenu: true,
|
||||
Items: seasonalItems
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const isFebruary = date.getUTCMonth() == 1;
|
||||
@ -1747,7 +1798,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
||||
Personal: true,
|
||||
Bounty: true,
|
||||
ClampNodeScores: true,
|
||||
Node: "EventNode28", // Incompatible with Wolf Hunt (2025), Orphix Venom, Warframe Anniversary
|
||||
Node: "EventNode28", // Incompatible with Wolf Hunt, Orphix Venom, Warframe Anniversary
|
||||
MissionKeyName: "/Lotus/Types/Keys/GalleonRobberyAlertB",
|
||||
Desc: "/Lotus/Language/Events/GalleonRobberyEventMissionTitle",
|
||||
Icon: "/Lotus/Interface/Icons/Player/GalleonRobberiesEvent.png",
|
||||
@ -2048,82 +2099,39 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
||||
NightLevel: "/Lotus/Levels/GrineerBeach/GrineerBeachEventNight.level"
|
||||
});
|
||||
|
||||
const baseStoreItem = {
|
||||
ShowInMarket: true,
|
||||
HideFromMarket: false,
|
||||
SupporterPack: false,
|
||||
Discount: 0,
|
||||
BogoBuy: 0,
|
||||
BogoGet: 0,
|
||||
StartDate: { $date: { $numberLong: activationTimeStamp } },
|
||||
EndDate: { $date: { $numberLong: expiryTimeStamp } },
|
||||
ProductExpiryOverride: { $date: { $numberLong: expiryTimeStamp } }
|
||||
};
|
||||
|
||||
const storeItems = [
|
||||
{
|
||||
TypeName: "/Lotus/Types/StoreItems/Packages/WaterFightNoggleBundle",
|
||||
PremiumOverride: 240,
|
||||
RegularOverride: 0
|
||||
},
|
||||
{
|
||||
TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFBeastMasterBobbleHead",
|
||||
PremiumOverride: 35,
|
||||
RegularOverride: 0
|
||||
},
|
||||
{
|
||||
TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFChargerBobbleHead",
|
||||
PremiumOverride: 35,
|
||||
RegularOverride: 0
|
||||
},
|
||||
{
|
||||
TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFEngineerBobbleHead",
|
||||
PremiumOverride: 35,
|
||||
RegularOverride: 0
|
||||
},
|
||||
{
|
||||
TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFGruntBobbleHead",
|
||||
PremiumOverride: 35,
|
||||
RegularOverride: 0
|
||||
},
|
||||
{
|
||||
TypeName: "/Lotus/Types/StoreItems/AvatarImages/ImagePopsicleGrineerPurple",
|
||||
PremiumOverride: 0,
|
||||
RegularOverride: 1
|
||||
},
|
||||
{
|
||||
TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFHealerBobbleHead",
|
||||
PremiumOverride: 35,
|
||||
RegularOverride: 0
|
||||
},
|
||||
{
|
||||
TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFHeavyBobbleHead",
|
||||
PremiumOverride: 35,
|
||||
RegularOverride: 0
|
||||
},
|
||||
{
|
||||
TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFHellionBobbleHead",
|
||||
PremiumOverride: 35,
|
||||
RegularOverride: 0
|
||||
},
|
||||
{
|
||||
TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFSniperBobbleHead",
|
||||
PremiumOverride: 35,
|
||||
RegularOverride: 0
|
||||
},
|
||||
{
|
||||
TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFTankBobbleHead",
|
||||
PremiumOverride: 35,
|
||||
RegularOverride: 0
|
||||
},
|
||||
{
|
||||
TypeName: "/Lotus/Types/StoreItems/SuitCustomizations/ColourPickerRollers",
|
||||
PremiumOverride: 75,
|
||||
RegularOverride: 0
|
||||
}
|
||||
const storeItems: (Partial<IFlashSale> & { TypeName: string })[] = [
|
||||
{ TypeName: "/Lotus/Types/StoreItems/Packages/WaterFightNoggleBundle", PremiumOverride: 240 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFBeastMasterBobbleHead", PremiumOverride: 35 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFChargerBobbleHead", PremiumOverride: 35 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFEngineerBobbleHead", PremiumOverride: 35 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFGruntBobbleHead", PremiumOverride: 35 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/ImagePopsicleGrineerPurple", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFHealerBobbleHead", PremiumOverride: 35 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFHeavyBobbleHead", PremiumOverride: 35 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFHellionBobbleHead", PremiumOverride: 35 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFSniperBobbleHead", PremiumOverride: 35 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/Events/WFTankBobbleHead", PremiumOverride: 35 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/SuitCustomizations/ColourPickerRollers", PremiumOverride: 75 }
|
||||
];
|
||||
|
||||
worldState.FlashSales.push(...storeItems.map(item => ({ ...baseStoreItem, ...item })));
|
||||
worldState.FlashSales.push(
|
||||
...storeItems.map(item => ({
|
||||
...{
|
||||
StartDate: { $date: { $numberLong: activationTimeStamp } },
|
||||
EndDate: { $date: { $numberLong: expiryTimeStamp } },
|
||||
ProductExpiryOverride: { $date: { $numberLong: expiryTimeStamp } },
|
||||
ShowInMarket: item.ShowInMarket ?? true,
|
||||
HideFromMarket: item.HideFromMarket ?? false,
|
||||
SupporterPack: item.SupporterPack ?? false,
|
||||
Discount: item.Discount ?? 0,
|
||||
BogoBuy: item.BogoBuy ?? 0,
|
||||
BogoGet: item.BogoGet ?? 0,
|
||||
RegularOverride: item.RegularOverride ?? 0,
|
||||
PremiumOverride: item.PremiumOverride ?? 0
|
||||
},
|
||||
...item
|
||||
}))
|
||||
);
|
||||
|
||||
const seasonalItems = storeItems.map(item => item.TypeName);
|
||||
|
||||
@ -2144,7 +2152,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
||||
}
|
||||
|
||||
if (config.worldState?.anniversary != undefined) {
|
||||
// Incompatible with: Use Tag from Warframe Anniversary for old Events, Wolf Hunt (2025), Galleon Of Ghouls, Hallowed Flame, Hallowed Nightmares, Dog Days, Proxy Rebellion, Long Shadow
|
||||
// Incompatible with: Use Tag from Warframe Anniversary for old Events, Wolf Hunt, Galleon Of Ghouls, Hallowed Flame, Hallowed Nightmares, Dog Days, Proxy Rebellion, Long Shadow
|
||||
const goalsByWeek: Partial<IGoal>[][] = [
|
||||
[
|
||||
{
|
||||
@ -2363,65 +2371,108 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
||||
});
|
||||
}
|
||||
|
||||
if (config.worldState?.wolfHunt) {
|
||||
worldState.Goals.push({
|
||||
_id: {
|
||||
$oid: "67ed7672798d6466172e3b9d"
|
||||
},
|
||||
Activation: {
|
||||
$date: {
|
||||
$numberLong: "1743616800000"
|
||||
}
|
||||
},
|
||||
Expiry: {
|
||||
$date: {
|
||||
$numberLong: "2000000000000"
|
||||
}
|
||||
},
|
||||
Count: 0,
|
||||
Goal: 3,
|
||||
InterimGoals: [1, 2],
|
||||
BonusGoal: 4,
|
||||
Success: 0,
|
||||
Personal: true,
|
||||
Bounty: true,
|
||||
ClampNodeScores: true,
|
||||
Node: "EventNode29",
|
||||
ConcurrentMissionKeyNames: [
|
||||
"/Lotus/Types/Keys/WolfTacAlertReduxB",
|
||||
"/Lotus/Types/Keys/WolfTacAlertReduxC",
|
||||
"/Lotus/Types/Keys/WolfTacAlertReduxD"
|
||||
],
|
||||
ConcurrentNodeReqs: [1, 2, 3],
|
||||
ConcurrentNodes: ["EventNode28", "EventNode39", "EventNode40"], // Incompatible with Galleon Of Ghouls, Orphix Venom, Warframe Anniversary
|
||||
MissionKeyName: "/Lotus/Types/Keys/WolfTacAlertReduxA",
|
||||
Faction: "FC_GRINEER",
|
||||
Desc: "/Lotus/Language/Alerts/WolfAlert",
|
||||
Icon: "/Lotus/Interface/Icons/Npcs/Seasonal/WolfStalker.png",
|
||||
Tag: "WolfHuntRedux",
|
||||
InterimRewards: [
|
||||
{
|
||||
credits: 50000,
|
||||
items: ["/Lotus/StoreItems/Types/Recipes/Weapons/WeaponParts/ThrowingHammerHandle"]
|
||||
if (config.worldState?.wolfHunt != undefined) {
|
||||
if (config.worldState.wolfHunt == 0) {
|
||||
worldState.Goals.push({
|
||||
_id: {
|
||||
$oid: "67ed7672798d6466172e3b9c"
|
||||
},
|
||||
{
|
||||
credits: 50000,
|
||||
items: ["/Lotus/StoreItems/Types/Recipes/Weapons/WeaponParts/ThrowingHammerHead"]
|
||||
Activation: {
|
||||
$date: {
|
||||
$numberLong: "1743616800000"
|
||||
}
|
||||
},
|
||||
Expiry: {
|
||||
$date: {
|
||||
$numberLong: "2000000000000"
|
||||
}
|
||||
},
|
||||
Count: 0,
|
||||
Goal: 1,
|
||||
BonusGoal: 2,
|
||||
Success: 0,
|
||||
Personal: true,
|
||||
Bounty: true,
|
||||
ClampNodeScores: true,
|
||||
Node: "EventNode29",
|
||||
ConcurrentMissionKeyNames: ["/Lotus/Types/Keys/WolfTacAlertB"],
|
||||
ConcurrentNodeReqs: [1],
|
||||
ConcurrentNodes: ["EventNode28"], // Incompatible with Galleon Of Ghouls, Orphix Venom, Warframe Anniversary
|
||||
MissionKeyName: "/Lotus/Types/Keys/WolfTacAlertA",
|
||||
Faction: "FC_GRINEER",
|
||||
Desc: "/Lotus/Language/Alerts/WolfAlert",
|
||||
Icon: "/Lotus/Interface/Icons/Npcs/Seasonal/WolfStalker.png",
|
||||
Tag: "WolfHuntRedux", // unfaithful
|
||||
Reward: {
|
||||
countedItems: [{ ItemType: "/Lotus/Types/Items/MiscItems/Alertium", ItemCount: 10 }]
|
||||
},
|
||||
BonusReward: {
|
||||
items: [
|
||||
"/Lotus/StoreItems/Upgrades/Mods/Randomized/RawRifleRandomMod",
|
||||
"/Lotus/StoreItems/Upgrades/Skins/Clan/BountyHunterBadgeItem"
|
||||
]
|
||||
}
|
||||
],
|
||||
Reward: {
|
||||
credits: 50000,
|
||||
items: ["/Lotus/StoreItems/Types/Recipes/Weapons/WeaponParts/ThrowingHammerMotor"]
|
||||
},
|
||||
BonusReward: {
|
||||
credits: 50000,
|
||||
items: [
|
||||
"/Lotus/StoreItems/Types/Recipes/Weapons/ThrowingHammerBlueprint",
|
||||
"/Lotus/StoreItems/Types/Items/MiscItems/OrokinCatalyst",
|
||||
"/Lotus/StoreItems/Upgrades/Skins/Clan/BountyHunterBadgeItem"
|
||||
]
|
||||
}
|
||||
});
|
||||
});
|
||||
} else if (config.worldState.wolfHunt == 1) {
|
||||
worldState.Goals.push({
|
||||
_id: {
|
||||
$oid: "67ed7672798d6466172e3b9d"
|
||||
},
|
||||
Activation: {
|
||||
$date: {
|
||||
$numberLong: "1743616800000"
|
||||
}
|
||||
},
|
||||
Expiry: {
|
||||
$date: {
|
||||
$numberLong: "2000000000000"
|
||||
}
|
||||
},
|
||||
Count: 0,
|
||||
Goal: 3,
|
||||
InterimGoals: [1, 2],
|
||||
BonusGoal: 4,
|
||||
Success: 0,
|
||||
Personal: true,
|
||||
Bounty: true,
|
||||
ClampNodeScores: true,
|
||||
Node: "EventNode29",
|
||||
ConcurrentMissionKeyNames: [
|
||||
"/Lotus/Types/Keys/WolfTacAlertReduxB",
|
||||
"/Lotus/Types/Keys/WolfTacAlertReduxC",
|
||||
"/Lotus/Types/Keys/WolfTacAlertReduxD"
|
||||
],
|
||||
ConcurrentNodeReqs: [1, 2, 3],
|
||||
ConcurrentNodes: ["EventNode28", "EventNode39", "EventNode40"], // Incompatible with Galleon Of Ghouls, Orphix Venom, Warframe Anniversary
|
||||
MissionKeyName: "/Lotus/Types/Keys/WolfTacAlertReduxA",
|
||||
Faction: "FC_GRINEER",
|
||||
Desc: "/Lotus/Language/Alerts/WolfAlert",
|
||||
Icon: "/Lotus/Interface/Icons/Npcs/Seasonal/WolfStalker.png",
|
||||
Tag: "WolfHuntRedux",
|
||||
InterimRewards: [
|
||||
{
|
||||
credits: 50000,
|
||||
items: ["/Lotus/StoreItems/Types/Recipes/Weapons/WeaponParts/ThrowingHammerHandle"]
|
||||
},
|
||||
{
|
||||
credits: 50000,
|
||||
items: ["/Lotus/StoreItems/Types/Recipes/Weapons/WeaponParts/ThrowingHammerHead"]
|
||||
}
|
||||
],
|
||||
Reward: {
|
||||
credits: 50000,
|
||||
items: ["/Lotus/StoreItems/Types/Recipes/Weapons/WeaponParts/ThrowingHammerMotor"]
|
||||
},
|
||||
BonusReward: {
|
||||
credits: 50000,
|
||||
items: [
|
||||
"/Lotus/StoreItems/Types/Recipes/Weapons/ThrowingHammerBlueprint",
|
||||
"/Lotus/StoreItems/Types/Items/MiscItems/OrokinCatalyst",
|
||||
"/Lotus/StoreItems/Upgrades/Skins/Clan/BountyHunterBadgeItem"
|
||||
]
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const tagsForOlderGoals: string[] = [
|
||||
@ -2719,22 +2770,18 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
||||
|
||||
const isOctober = date.getUTCMonth() == 9; // October = month index 9
|
||||
if (config.worldState?.naberusNightsOverride ?? isOctober) {
|
||||
const activationTimeStamp = config.worldState?.naberusNightsOverride
|
||||
? "1727881200000"
|
||||
: Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1).toString();
|
||||
|
||||
const expiryTimeStamp = config.worldState?.naberusNightsOverride
|
||||
? "2000000000000"
|
||||
: Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 1).toString();
|
||||
|
||||
worldState.Goals.push({
|
||||
_id: { $oid: "66fd602de1778d583419e8e7" },
|
||||
Activation: {
|
||||
$date: {
|
||||
$numberLong: config.worldState?.naberusNightsOverride
|
||||
? "1727881200000"
|
||||
: Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1).toString()
|
||||
}
|
||||
},
|
||||
Expiry: {
|
||||
$date: {
|
||||
$numberLong: config.worldState?.naberusNightsOverride
|
||||
? "2000000000000"
|
||||
: Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 1).toString()
|
||||
}
|
||||
},
|
||||
Activation: { $date: { $numberLong: activationTimeStamp } },
|
||||
Expiry: { $date: { $numberLong: expiryTimeStamp } },
|
||||
Count: 0,
|
||||
Goal: 0,
|
||||
Success: 0,
|
||||
@ -2745,6 +2792,181 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
||||
Tag: "DeimosHalloween",
|
||||
Node: "DeimosHub"
|
||||
});
|
||||
|
||||
const storeItems: (Partial<IFlashSale> & { TypeName: string })[] = [
|
||||
{ TypeName: "/Lotus/Types/StoreItems/Packages/Halloween2023GlyphBundleA", PremiumOverride: 65 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/Packages/Halloween2021GlyphBundle", PremiumOverride: 65 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/Packages/Halloween2019GlyphBundleA", PremiumOverride: 65 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/Packages/Halloween2019GlyphBundleB", PremiumOverride: 65 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/Packages/HalloweenGlyphBundle", PremiumOverride: 65 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/Packages/Halloween2023ArmorBundle", PremiumOverride: 125 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/Packages/HalloweenCrpCircArmorPack", PremiumOverride: 100 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/Packages/HalloweenScarfBundleB", PremiumOverride: 80 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/Packages/HalloweenSkinPack", PremiumOverride: 175 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/Packages/HalloweenShipSkinBundle", PremiumOverride: 80 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/Packages/HalloweenSkinPackC", PremiumOverride: 175 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/Packages/HalloweenSkinPackII", PremiumOverride: 145 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/Packages/HalloweenScarfBundle", PremiumOverride: 130 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/Packages/AcolyteNoggleBundle", PremiumOverride: 160 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/AcolyteAreaCasterBobbleHead", PremiumOverride: 35 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/AcolyteDuellistBobbleHead", PremiumOverride: 35 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/AcolyteControlBobbleHead", PremiumOverride: 35 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/AcolyteHeavyBobbleHead", PremiumOverride: 35 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/AcolyteRogueBobbleHead", PremiumOverride: 35 },
|
||||
{ TypeName: "/Lotus/Types/Items/ShipDecos/AcolyteStrikerBobbleHead", PremiumOverride: 35 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/SuitCustomizations/ColourPickerHalloweenItemA", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Armor/Halloween2014Wings/Halloween2014ArmArmor", PremiumOverride: 50 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Festivities/PumpkinHead", RegularOverride: 1 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenRegorAxeShield", PremiumOverride: 20 },
|
||||
{
|
||||
TypeName: "/Lotus/Types/StoreItems/AvatarImages/Seasonal/Halloween2019CheshireKavat",
|
||||
PremiumOverride: 20
|
||||
},
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenAkvasto", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenAngstrum", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenBoltor", PremiumOverride: 20 },
|
||||
{
|
||||
TypeName: "/Lotus/Types/StoreItems/AvatarImages/Seasonal/Halloween2019GhostChibiWisp",
|
||||
PremiumOverride: 20
|
||||
},
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenBraton", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageHalloween2016A", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageHalloween2016C", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageHalloween2016B", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenBuzlok", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageHalloween2016D", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/Seasonal/Halloween2019CreepyClem", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenDaikyu", PremiumOverride: 20 },
|
||||
{
|
||||
TypeName: "/Lotus/Types/StoreItems/AvatarImages/Seasonal/AvatarImageHalloween2021Dethcube",
|
||||
PremiumOverride: 20
|
||||
},
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenDragonNikana", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenDualZoren", PremiumOverride: 20 },
|
||||
{
|
||||
TypeName: "/Lotus/Types/StoreItems/AvatarImages/Seasonal/Halloween2019FrankenCorpus",
|
||||
PremiumOverride: 20
|
||||
},
|
||||
{
|
||||
TypeName: "/Lotus/Types/StoreItems/AvatarImages/Seasonal/AvatarImageHalloween2021Grineer",
|
||||
PremiumOverride: 20
|
||||
},
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenGlaive", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenGalatine", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenGrakata", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenGorgon", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenGlaxion", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenTwinGremlins", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenGrinlok", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Scarves/HalloweenFireFlyScarf", PremiumOverride: 90 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenImperator", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenKronen", PremiumOverride: 20 },
|
||||
{
|
||||
TypeName: "/Lotus/Types/StoreItems/AvatarImages/Seasonal/AvatarImageHalloween2021Lotus",
|
||||
PremiumOverride: 20
|
||||
},
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenJatKittag", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Scarves/HalloweenKyropteraScarf", PremiumOverride: 50 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenKunai", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Liset/LisetSkinHalloween", PremiumOverride: 50 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Liset/LisetInsectSkinHalloween", PremiumOverride: 50 },
|
||||
{
|
||||
TypeName: "/Lotus/Types/StoreItems/AvatarImages/Seasonal/AvatarImageChillingGlyphFour",
|
||||
PremiumOverride: 20
|
||||
},
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenMarelok", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenNikana", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenNukor", PremiumOverride: 20 },
|
||||
{
|
||||
TypeName: "/Lotus/Types/StoreItems/AvatarImages/Seasonal/AvatarImageHalloween2021Loid",
|
||||
PremiumOverride: 20
|
||||
},
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenOpticor", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenOrthos", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenParis", PremiumOverride: 20 },
|
||||
{
|
||||
TypeName: "/Lotus/Types/StoreItems/AvatarImages/Seasonal/AvatarImageChillingGlyphTwo",
|
||||
PremiumOverride: 20
|
||||
},
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Armor/CrpCircleArmour/HalloweenCrpCircC", PremiumOverride: 45 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Armor/CrpCircleArmour/HalloweenCrpCircA", PremiumOverride: 50 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Armor/CrpCircleArmour/HalloweenCrpCircL", PremiumOverride: 35 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenScindo", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/Seasonal/Halloween2019GhoulGrave", PremiumOverride: 20 },
|
||||
{
|
||||
TypeName: "/Lotus/Types/StoreItems/AvatarImages/Seasonal/AvatarImageHalloween2021Pumpkin",
|
||||
PremiumOverride: 20
|
||||
},
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenSarpa", PremiumOverride: 20 },
|
||||
{
|
||||
TypeName: "/Lotus/Types/StoreItems/AvatarImages/Seasonal/AvatarImageChillingGlyphThree",
|
||||
PremiumOverride: 20
|
||||
},
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenSilvaAndAegis", PremiumOverride: 20 },
|
||||
{
|
||||
TypeName: "/Lotus/Types/StoreItems/AvatarImages/Seasonal/AvatarImageChillingGlyphOne",
|
||||
PremiumOverride: 20
|
||||
},
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenSoma", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenSkana", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/Seasonal/Halloween2019SlimeLoki", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenSobek", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenSonicor", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenSimulor", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenTonkor", PremiumOverride: 20 },
|
||||
{
|
||||
TypeName: "/Lotus/Types/StoreItems/AvatarImages/Seasonal/Halloween2019TrickOrBalas",
|
||||
PremiumOverride: 20
|
||||
},
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenSpira", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenStradavar", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenTwinGrakatas", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenArchSword", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenLato", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/AvatarImages/Seasonal/Halloween2019Werefested", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Scarves/HalloweenErosionCape", PremiumOverride: 50 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenVasto", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenDarkSplitSword", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenDarkDagger", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Scarves/HalloweenGrnBannerScarf", PremiumOverride: 75 },
|
||||
{ TypeName: "/Lotus/Upgrades/Skins/Halloween/HalloweenAmprex", PremiumOverride: 20 },
|
||||
{ TypeName: "/Lotus/Types/StoreItems/Packages/HalloweenSkinPackD", PremiumOverride: 180 }
|
||||
];
|
||||
|
||||
worldState.FlashSales.push(
|
||||
...storeItems.map(item => ({
|
||||
...{
|
||||
StartDate: { $date: { $numberLong: activationTimeStamp } },
|
||||
EndDate: { $date: { $numberLong: expiryTimeStamp } },
|
||||
ProductExpiryOverride: { $date: { $numberLong: expiryTimeStamp } },
|
||||
ShowInMarket: item.ShowInMarket ?? true,
|
||||
HideFromMarket: item.HideFromMarket ?? false,
|
||||
SupporterPack: item.SupporterPack ?? false,
|
||||
Discount: item.Discount ?? 0,
|
||||
BogoBuy: item.BogoBuy ?? 0,
|
||||
BogoGet: item.BogoGet ?? 0,
|
||||
RegularOverride: item.RegularOverride ?? 0,
|
||||
PremiumOverride: item.PremiumOverride ?? 0
|
||||
},
|
||||
...item
|
||||
}))
|
||||
);
|
||||
|
||||
const seasonalItems = storeItems.map(item => item.TypeName);
|
||||
const seasonalCategory = worldState.InGameMarket.LandingPage.Categories.find(c => c.CategoryName == "SEASONAL");
|
||||
|
||||
if (seasonalCategory) {
|
||||
seasonalCategory.Items ??= [];
|
||||
seasonalCategory.Items.push(...seasonalItems);
|
||||
} else {
|
||||
worldState.InGameMarket.LandingPage.Categories.push({
|
||||
CategoryName: "SEASONAL",
|
||||
Name: "/Lotus/Language/Store/SeasonalCategoryTitle",
|
||||
Icon: "seasonal",
|
||||
AddToMenu: true,
|
||||
Items: seasonalItems
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (config.worldState?.bellyOfTheBeast) {
|
||||
@ -2822,7 +3044,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
||||
Success: 0,
|
||||
Personal: true,
|
||||
Best: true,
|
||||
Node: "EventNode28", // Incompatible with Galleon Of Ghouls, Wolf Hunt (2025)
|
||||
Node: "EventNode28", // Incompatible with Galleon Of Ghouls, Wolf Hunt
|
||||
MissionKeyName: "/Lotus/Types/Keys/MechSurvivalGrineerGalleon",
|
||||
Faction: "FC_SENTIENT",
|
||||
Desc: "/Lotus/Language/Events/MechEventMissionTier2",
|
||||
@ -3481,7 +3703,8 @@ export const getLiteSortie = (week: number): ILiteSortie => {
|
||||
value.missionType != "MT_ASSASSINATION" &&
|
||||
value.missionType != "MT_JUNCTION" &&
|
||||
value.missionType != "MT_LANDSCAPE" &&
|
||||
value.missionType != "MT_RAILJACK"
|
||||
value.missionType != "MT_RAILJACK" &&
|
||||
key != "SolNode63" // This node uses GrineerForestTilesetCaves which only supports MT_CAPTURE, which is not valid for LiteSorties.
|
||||
) {
|
||||
nodes.push(key);
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import type { IDatabaseAccountJson } from "../types/loginTypes.ts";
|
||||
import type { HydratedDocument } from "mongoose";
|
||||
import { logError, logger } from "../utils/logger.ts";
|
||||
import type { Request } from "express";
|
||||
import type { ITunables } from "../types/bootstrapperTypes.ts";
|
||||
|
||||
let wsServer: WebSocketServer | undefined;
|
||||
let wssServer: WebSocketServer | undefined;
|
||||
@ -89,8 +90,9 @@ interface IWsMsgToClient {
|
||||
logged_out?: boolean;
|
||||
have_game_ws?: boolean;
|
||||
|
||||
// to game
|
||||
// to game/bootstrapper (https://openwf.io/bootstrapper-manual)
|
||||
sync_inventory?: boolean;
|
||||
tunables?: ITunables;
|
||||
}
|
||||
|
||||
const wsOnConnect = (ws: WebSocket, req: http.IncomingMessage): void => {
|
||||
|
||||
9
src/types/bootstrapperTypes.ts
Normal file
9
src/types/bootstrapperTypes.ts
Normal file
@ -0,0 +1,9 @@
|
||||
// This is specific to the OpenWF Bootstrapper: https://openwf.io/bootstrapper-manual
|
||||
export interface ITunables {
|
||||
token?: string;
|
||||
prohibit_skip_mission_start_timer?: boolean;
|
||||
prohibit_fov_override?: boolean;
|
||||
prohibit_freecam?: boolean;
|
||||
prohibit_teleport?: boolean;
|
||||
prohibit_scripts?: boolean;
|
||||
}
|
||||
@ -25,6 +25,7 @@ export enum EquipmentFeatures {
|
||||
GRAVIMAG_INSTALLED = 4,
|
||||
GILDED = 8,
|
||||
ARCANE_SLOT = 32,
|
||||
SECOND_ARCANE_SLOT = 64,
|
||||
INCARNON_GENESIS = 512,
|
||||
VALENCE_SWAP = 1024
|
||||
}
|
||||
|
||||
@ -61,6 +61,9 @@ export interface IAccountCheats {
|
||||
nemesisHintProgressMultiplierGrineer?: number;
|
||||
nemesisHintProgressMultiplierCorpus?: number;
|
||||
nemesisExtraWeapon?: number;
|
||||
spoofMasteryRank?: number;
|
||||
relicRewardItemCountMultiplier?: number;
|
||||
nightwaveStandingMultiplier?: number;
|
||||
}
|
||||
|
||||
export interface IInventoryDatabase
|
||||
@ -340,6 +343,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
|
||||
EmailItems: ITypeCount[];
|
||||
CompletedSyndicates: string[];
|
||||
FocusXP?: IFocusXP;
|
||||
FocusCapacity?: number;
|
||||
Wishlist: string[];
|
||||
Alignment?: IAlignment;
|
||||
CompletedSorties: string[];
|
||||
@ -432,6 +436,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
|
||||
Ship?: IOrbiterClient; // U22 and below, response only
|
||||
ClaimedJunctionChallengeRewards?: string[]; // U39
|
||||
SpecialItemRewardAttenuation?: IRewardAttenuation[]; // Baro's Void Surplus
|
||||
NokkoColony?: INokkoColony; // Field Guide
|
||||
}
|
||||
|
||||
export interface IAffiliation {
|
||||
@ -638,6 +643,7 @@ export interface IFocusUpgrade {
|
||||
ItemType: string;
|
||||
Level?: number;
|
||||
IsUniversal?: boolean;
|
||||
IsActive?: number; // Focus 2.0
|
||||
}
|
||||
|
||||
export interface IFocusXP {
|
||||
@ -1215,3 +1221,13 @@ export interface IHubNpcCustomization {
|
||||
Pattern: string;
|
||||
Tag: string;
|
||||
}
|
||||
|
||||
export interface IJournalEntry {
|
||||
EntryType: string;
|
||||
Progress: number;
|
||||
}
|
||||
|
||||
export interface INokkoColony {
|
||||
FeedLevel: number;
|
||||
JournalEntries: IJournalEntry[];
|
||||
}
|
||||
|
||||
@ -9,7 +9,8 @@ import type {
|
||||
TEquipmentKey,
|
||||
ICrewMemberClient,
|
||||
IKubrowPetPrintClient,
|
||||
IUpgradeClient
|
||||
IUpgradeClient,
|
||||
IQuestKeyClient
|
||||
} from "./inventoryTypes/inventoryTypes.ts";
|
||||
|
||||
export enum PurchaseSource {
|
||||
@ -83,6 +84,7 @@ export type IInventoryChanges = {
|
||||
CrewMembers?: ICrewMemberClient[];
|
||||
KubrowPetPrints?: IKubrowPetPrintClient[];
|
||||
Upgrades?: IUpgradeClient[]; // TOVERIFY
|
||||
QuestKeys?: IQuestKeyClient[];
|
||||
} & Record<
|
||||
Exclude<
|
||||
string,
|
||||
|
||||
@ -234,11 +234,6 @@ export interface IUpgradeOperation {
|
||||
PolarizeValue: ArtifactPolarity;
|
||||
PolarityRemap: IPolarity[];
|
||||
}
|
||||
export interface IUnlockShipFeatureRequest {
|
||||
Feature: string;
|
||||
KeyChain: string;
|
||||
ChainStage: number;
|
||||
}
|
||||
|
||||
export interface IVoidTearParticipantInfo {
|
||||
AccountId: string;
|
||||
|
||||
@ -58,6 +58,7 @@ export interface IAlertMissionInfo {
|
||||
maxEnemyLevel?: number;
|
||||
maxWaveNum?: number;
|
||||
descText?: string;
|
||||
enemyCacheOverride?: string;
|
||||
|
||||
maxRotations?: number; // SNS specific field
|
||||
}
|
||||
|
||||
@ -136,5 +136,7 @@
|
||||
"ConquestSetupIntro",
|
||||
"EntratiLabConquestHardModeUnlocked",
|
||||
"/Lotus/Language/Npcs/KonzuPostNewWar",
|
||||
"/Lotus/Language/SolarisVenus/EudicoPostNewWar"
|
||||
"/Lotus/Language/SolarisVenus/EudicoPostNewWar",
|
||||
"/Lotus/Language/NokkoColony/NokkoVendorName",
|
||||
"NokkoVisions_FirstVisit"
|
||||
]
|
||||
|
||||
409
static/fixed_responses/getSkuCatalogU40.json
Normal file
409
static/fixed_responses/getSkuCatalogU40.json
Normal file
@ -0,0 +1,409 @@
|
||||
{
|
||||
"Skus": [
|
||||
{
|
||||
"productId": 17,
|
||||
"listPrice": {
|
||||
"formatted": "4.99 USD",
|
||||
"raw": "4.99",
|
||||
"value": 4.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "4.99 USD",
|
||||
"raw": "4.99",
|
||||
"value": 4.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 18,
|
||||
"listPrice": {
|
||||
"formatted": "9.99 USD",
|
||||
"raw": "9.99",
|
||||
"value": 9.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "9.99 USD",
|
||||
"raw": "9.99",
|
||||
"value": 9.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 160,
|
||||
"listPrice": {
|
||||
"formatted": "19.99 USD",
|
||||
"raw": "19.99",
|
||||
"value": 19.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "19.99 USD",
|
||||
"raw": "19.99",
|
||||
"value": 19.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 257,
|
||||
"listPrice": {
|
||||
"formatted": "199.99 USD",
|
||||
"raw": "199.99",
|
||||
"value": 199.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "199.99 USD",
|
||||
"raw": "199.99",
|
||||
"value": 199.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 258,
|
||||
"listPrice": {
|
||||
"formatted": "99.99 USD",
|
||||
"raw": "99.99",
|
||||
"value": 99.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "99.99 USD",
|
||||
"raw": "99.99",
|
||||
"value": 99.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 259,
|
||||
"listPrice": {
|
||||
"formatted": "49.99 USD",
|
||||
"raw": "49.99",
|
||||
"value": 49.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "49.99 USD",
|
||||
"raw": "49.99",
|
||||
"value": 49.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 785,
|
||||
"listPrice": {
|
||||
"formatted": "19.99 USD",
|
||||
"raw": "19.99",
|
||||
"value": 19.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "19.99 USD",
|
||||
"raw": "19.99",
|
||||
"value": 19.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 786,
|
||||
"listPrice": {
|
||||
"formatted": "39.99 USD",
|
||||
"raw": "39.99",
|
||||
"value": 39.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "39.99 USD",
|
||||
"raw": "39.99",
|
||||
"value": 39.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 787,
|
||||
"listPrice": {
|
||||
"formatted": "79.99 USD",
|
||||
"raw": "79.99",
|
||||
"value": 79.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "79.99 USD",
|
||||
"raw": "79.99",
|
||||
"value": 79.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 979,
|
||||
"listPrice": {
|
||||
"formatted": "4.99 USD",
|
||||
"raw": "4.99",
|
||||
"value": 4.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "4.99 USD",
|
||||
"raw": "4.99",
|
||||
"value": 4.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 10037,
|
||||
"listPrice": {
|
||||
"formatted": "54.99 USD",
|
||||
"raw": "54.99",
|
||||
"value": 54.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "54.99 USD",
|
||||
"raw": "54.99",
|
||||
"value": 54.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 10054,
|
||||
"listPrice": {
|
||||
"formatted": "49.99 USD",
|
||||
"raw": "49.99",
|
||||
"value": 49.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "49.99 USD",
|
||||
"raw": "49.99",
|
||||
"value": 49.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 10061,
|
||||
"listPrice": {
|
||||
"formatted": "0.99 USD",
|
||||
"raw": "0.99",
|
||||
"value": 0.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "0.99 USD",
|
||||
"raw": "0.99",
|
||||
"value": 0.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 10076,
|
||||
"listPrice": {
|
||||
"formatted": "29.99 USD",
|
||||
"raw": "29.99",
|
||||
"value": 29.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "29.99 USD",
|
||||
"raw": "29.99",
|
||||
"value": 29.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 10078,
|
||||
"listPrice": {
|
||||
"formatted": "24.99 USD",
|
||||
"raw": "24.99",
|
||||
"value": 24.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "24.99 USD",
|
||||
"raw": "24.99",
|
||||
"value": 24.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 10080,
|
||||
"listPrice": {
|
||||
"formatted": "49.99 USD",
|
||||
"raw": "49.99",
|
||||
"value": 49.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "49.99 USD",
|
||||
"raw": "49.99",
|
||||
"value": 49.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 10081,
|
||||
"listPrice": {
|
||||
"formatted": "79.99 USD",
|
||||
"raw": "79.99",
|
||||
"value": 79.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "79.99 USD",
|
||||
"raw": "79.99",
|
||||
"value": 79.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 10082,
|
||||
"listPrice": {
|
||||
"formatted": "139.99 USD",
|
||||
"raw": "139.99",
|
||||
"value": 139.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "139.99 USD",
|
||||
"raw": "139.99",
|
||||
"value": 139.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 10084,
|
||||
"listPrice": {
|
||||
"formatted": "49.99 USD",
|
||||
"raw": "49.99",
|
||||
"value": 49.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "49.99 USD",
|
||||
"raw": "49.99",
|
||||
"value": 49.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 10085,
|
||||
"listPrice": {
|
||||
"formatted": "30.00 USD",
|
||||
"raw": "30.00",
|
||||
"value": 30
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "30.00 USD",
|
||||
"raw": "30.00",
|
||||
"value": 30
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 10086,
|
||||
"listPrice": {
|
||||
"formatted": "60.00 USD",
|
||||
"raw": "60.00",
|
||||
"value": 60
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "60.00 USD",
|
||||
"raw": "60.00",
|
||||
"value": 60
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 10087,
|
||||
"listPrice": {
|
||||
"formatted": "90.00 USD",
|
||||
"raw": "90.00",
|
||||
"value": 90
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "90.00 USD",
|
||||
"raw": "90.00",
|
||||
"value": 90
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 10088,
|
||||
"listPrice": {
|
||||
"formatted": "90.00 USD",
|
||||
"raw": "90.00",
|
||||
"value": 90
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "90.00 USD",
|
||||
"raw": "90.00",
|
||||
"value": 90
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 10089,
|
||||
"listPrice": {
|
||||
"formatted": "40.01 USD",
|
||||
"raw": "40.01",
|
||||
"value": 40.01
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "40.01 USD",
|
||||
"raw": "40.01",
|
||||
"value": 40.01
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 10090,
|
||||
"listPrice": {
|
||||
"formatted": "10.01 USD",
|
||||
"raw": "10.01",
|
||||
"value": 10.01
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "10.01 USD",
|
||||
"raw": "10.01",
|
||||
"value": 10.01
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 10094,
|
||||
"listPrice": {
|
||||
"formatted": "24.99 USD",
|
||||
"raw": "24.99",
|
||||
"value": 24.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "24.99 USD",
|
||||
"raw": "24.99",
|
||||
"value": 24.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
},
|
||||
{
|
||||
"productId": 10095,
|
||||
"listPrice": {
|
||||
"formatted": "14.99 USD",
|
||||
"raw": "14.99",
|
||||
"value": 14.99
|
||||
},
|
||||
"basePrice": {
|
||||
"formatted": "14.99 USD",
|
||||
"raw": "14.99",
|
||||
"value": 14.99
|
||||
},
|
||||
"currencyCode": "USD",
|
||||
"owned": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,10 +1,4 @@
|
||||
{
|
||||
"/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain": [
|
||||
{
|
||||
"ItemType": "/Lotus/Types/NeutralCreatures/ErsatzHorse/ErsatzHorsePowerSuit",
|
||||
"ItemCount": 1
|
||||
}
|
||||
],
|
||||
"/Lotus/Types/Keys/InfestedMicroplanetQuest/InfestedMicroplanetQuestKeyChain": [{ "ItemType": "/Lotus/Types/Recipes/WarframeRecipes/BrokenFrameBlueprint", "ItemCount": 1 }],
|
||||
"/Lotus/Types/Keys/OrokinMoonQuest/OrokinMoonQuestKeyChain": [
|
||||
{
|
||||
|
||||
@ -83,7 +83,7 @@
|
||||
<p data-loc="login_description"></p>
|
||||
<form onsubmit="doLogin();return false;">
|
||||
<label for="email" data-loc="login_emailLabel"></label>
|
||||
<input class="form-control" type="email" id="email" required />
|
||||
<input class="form-control" type="text" id="email" required />
|
||||
<br />
|
||||
<label for="password" data-loc="login_passwordLabel"></label>
|
||||
<input class="form-control" type="password" id="password" required />
|
||||
@ -110,7 +110,7 @@
|
||||
<div class="tab-pane" id="miscItems-tab-content">
|
||||
<form class="card-body input-group" onsubmit="doAcquireCountItems('miscitems');return false;">
|
||||
<input class="form-control" id="miscitems-count" type="number" value="1" />
|
||||
<input class="form-control w-50" id="acquire-type-miscitems" list="datalist-miscitems" />
|
||||
<input class="form-control w-50" id="acquire-type-miscitems" list="datalist-miscitems" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
</div>
|
||||
@ -182,7 +182,7 @@
|
||||
<h5 class="card-header" data-loc="inventory_suits"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('Suits');return false;">
|
||||
<input class="form-control" id="acquire-type-Suits" list="datalist-Suits" />
|
||||
<input class="form-control" id="acquire-type-Suits" list="datalist-Suits" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
@ -198,13 +198,13 @@
|
||||
<h5 class="card-header" data-loc="inventory_longGuns"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="handleModularSelection('LongGuns');return false;">
|
||||
<input class="form-control" id="acquire-type-LongGuns" list="datalist-LongGuns" />
|
||||
<input class="form-control" id="acquire-type-LongGuns" list="datalist-LongGuns" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<form class="input-group mb-3 d-none" id="modular-LongGuns">
|
||||
<input class="form-control" id="acquire-type-LongGuns-GUN_BARREL" list="datalist-ModularParts-GUN_BARREL" />
|
||||
<input class="form-control" id="acquire-type-LongGuns-GUN_PRIMARY_HANDLE" list="datalist-ModularParts-GUN_PRIMARY_HANDLE" />
|
||||
<input class="form-control" id="acquire-type-LongGuns-GUN_CLIP" list="datalist-ModularParts-GUN_CLIP" />
|
||||
<input class="form-control" id="acquire-type-LongGuns-GUN_BARREL" list="datalist-ModularParts-GUN_BARREL" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-LongGuns-GUN_PRIMARY_HANDLE" list="datalist-ModularParts-GUN_PRIMARY_HANDLE" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-LongGuns-GUN_CLIP" list="datalist-ModularParts-GUN_CLIP" autocomplete="off" />
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
<table class="table table-hover w-100">
|
||||
@ -221,13 +221,13 @@
|
||||
<h5 class="card-header" data-loc="inventory_pistols"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="handleModularSelection('Pistols');return false;">
|
||||
<input class="form-control" id="acquire-type-Pistols" list="datalist-Pistols" />
|
||||
<input class="form-control" id="acquire-type-Pistols" list="datalist-Pistols" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<form class="input-group mb-3 d-none" id="modular-Pistols">
|
||||
<input class="form-control" id="acquire-type-Pistols-GUN_BARREL" list="datalist-ModularParts-GUN_BARREL" />
|
||||
<input class="form-control" id="acquire-type-Pistols-GUN_SECONDARY_HANDLE" list="datalist-ModularParts-GUN_SECONDARY_HANDLE" />
|
||||
<input class="form-control" id="acquire-type-Pistols-GUN_CLIP" list="datalist-ModularParts-GUN_CLIP" />
|
||||
<input class="form-control" id="acquire-type-Pistols-GUN_BARREL" list="datalist-ModularParts-GUN_BARREL" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-Pistols-GUN_SECONDARY_HANDLE" list="datalist-ModularParts-GUN_SECONDARY_HANDLE" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-Pistols-GUN_CLIP" list="datalist-ModularParts-GUN_CLIP" autocomplete="off" />
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
<table class="table table-hover w-100">
|
||||
@ -242,13 +242,13 @@
|
||||
<h5 class="card-header" data-loc="inventory_melee"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="handleModularSelection('Melee');return false;">
|
||||
<input class="form-control" id="acquire-type-Melee" list="datalist-Melee" />
|
||||
<input class="form-control" id="acquire-type-Melee" list="datalist-Melee" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<form class="input-group mb-3 d-none" id="modular-Melee">
|
||||
<input class="form-control" id="acquire-type-Melee-BLADE" list="datalist-ModularParts-BLADE" />
|
||||
<input class="form-control" id="acquire-type-Melee-HILT" list="datalist-ModularParts-HILT" />
|
||||
<input class="form-control" id="acquire-type-Melee-HILT_WEIGHT" list="datalist-ModularParts-HILT_WEIGHT" />
|
||||
<input class="form-control" id="acquire-type-Melee-BLADE" list="datalist-ModularParts-BLADE" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-Melee-HILT" list="datalist-ModularParts-HILT" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-Melee-HILT_WEIGHT" list="datalist-ModularParts-HILT_WEIGHT" autocomplete="off" />
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
<table class="table table-hover w-100">
|
||||
@ -265,7 +265,7 @@
|
||||
<h5 class="card-header" data-loc="inventory_spaceSuits"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceSuits');return false;">
|
||||
<input class="form-control" id="acquire-type-SpaceSuits" list="datalist-SpaceSuits" />
|
||||
<input class="form-control" id="acquire-type-SpaceSuits" list="datalist-SpaceSuits" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
@ -281,7 +281,7 @@
|
||||
<h5 class="card-header" data-loc="inventory_spaceGuns"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceGuns');return false;">
|
||||
<input class="form-control" id="acquire-type-SpaceGuns" list="datalist-SpaceGuns" />
|
||||
<input class="form-control" id="acquire-type-SpaceGuns" list="datalist-SpaceGuns" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
@ -299,7 +299,7 @@
|
||||
<h5 class="card-header" data-loc="inventory_spaceMelee"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceMelee');return false;">
|
||||
<input class="form-control" id="acquire-type-SpaceMelee" list="datalist-SpaceMelee" />
|
||||
<input class="form-control" id="acquire-type-SpaceMelee" list="datalist-SpaceMelee" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
@ -315,7 +315,7 @@
|
||||
<h5 class="card-header" data-loc="inventory_mechSuits"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('MechSuits');return false;">
|
||||
<input class="form-control" id="acquire-type-MechSuits" list="datalist-MechSuits" />
|
||||
<input class="form-control" id="acquire-type-MechSuits" list="datalist-MechSuits" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
@ -333,7 +333,7 @@
|
||||
<h5 class="card-header" data-loc="inventory_sentinels"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('Sentinels');return false;">
|
||||
<input class="form-control" id="acquire-type-Sentinels" list="datalist-Sentinels" />
|
||||
<input class="form-control" id="acquire-type-Sentinels" list="datalist-Sentinels" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
@ -349,20 +349,20 @@
|
||||
<h5 class="card-header" data-loc="inventory_moaPets"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="handleModularSelection('MoaPets');return false;">
|
||||
<input class="form-control" id="acquire-type-MoaPets" list="datalist-MoaPets" />
|
||||
<input class="form-control" id="acquire-type-MoaPets" list="datalist-MoaPets" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<form class="input-group mb-3 d-none" id="modular-MoaPets-Moa">
|
||||
<input class="form-control" id="acquire-type-MoaPets-MOA_ENGINE" list="datalist-ModularParts-MOA_ENGINE" />
|
||||
<input class="form-control" id="acquire-type-MoaPets-MOA_PAYLOAD" list="datalist-ModularParts-MOA_PAYLOAD" />
|
||||
<input class="form-control" id="acquire-type-MoaPets-MOA_HEAD" list="datalist-ModularParts-MOA_HEAD" />
|
||||
<input class="form-control" id="acquire-type-MoaPets-MOA_LEG" list="datalist-ModularParts-MOA_LEG" />
|
||||
<input class="form-control" id="acquire-type-MoaPets-MOA_ENGINE" list="datalist-ModularParts-MOA_ENGINE" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-MoaPets-MOA_PAYLOAD" list="datalist-ModularParts-MOA_PAYLOAD" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-MoaPets-MOA_HEAD" list="datalist-ModularParts-MOA_HEAD" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-MoaPets-MOA_LEG" list="datalist-ModularParts-MOA_LEG" autocomplete="off" />
|
||||
</form>
|
||||
<form class="input-group mb-3 d-none" id="modular-MoaPets-Zanuka">
|
||||
<input class="form-control" id="acquire-type-MoaPets-ZANUKA_HEAD" list="datalist-ModularParts-ZANUKA_HEAD" />
|
||||
<input class="form-control" id="acquire-type-MoaPets-ZANUKA_BODY" list="datalist-ModularParts-ZANUKA_BODY" />
|
||||
<input class="form-control" id="acquire-type-MoaPets-ZANUKA_LEG" list="datalist-ModularParts-ZANUKA_LEG" />
|
||||
<input class="form-control" id="acquire-type-MoaPets-ZANUKA_TAIL" list="datalist-ModularParts-ZANUKA_TAIL" />
|
||||
<input class="form-control" id="acquire-type-MoaPets-ZANUKA_HEAD" list="datalist-ModularParts-ZANUKA_HEAD" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-MoaPets-ZANUKA_BODY" list="datalist-ModularParts-ZANUKA_BODY" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-MoaPets-ZANUKA_LEG" list="datalist-ModularParts-ZANUKA_LEG" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-MoaPets-ZANUKA_TAIL" list="datalist-ModularParts-ZANUKA_TAIL" autocomplete="off" />
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
<table class="table table-hover w-100">
|
||||
@ -379,16 +379,16 @@
|
||||
<h5 class="card-header" data-loc="inventory_kubrowPets"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="handleModularSelection('KubrowPets');return false;">
|
||||
<input class="form-control" id="acquire-type-KubrowPets" list="datalist-KubrowPets" />
|
||||
<input class="form-control" id="acquire-type-KubrowPets" list="datalist-KubrowPets" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<form class="input-group mb-3 d-none" id="modular-KubrowPets-Catbrow">
|
||||
<input class="form-control" id="acquire-type-KubrowPets-CATBROW_ANTIGEN" list="datalist-ModularParts-CATBROW_ANTIGEN" />
|
||||
<input class="form-control" id="acquire-type-KubrowPets-CATBROW_MUTAGEN" list="datalist-ModularParts-CATBROW_MUTAGEN" />
|
||||
<input class="form-control" id="acquire-type-KubrowPets-CATBROW_ANTIGEN" list="datalist-ModularParts-CATBROW_ANTIGEN" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-KubrowPets-CATBROW_MUTAGEN" list="datalist-ModularParts-CATBROW_MUTAGEN" autocomplete="off" />
|
||||
</form>
|
||||
<form class="input-group mb-3 d-none" id="modular-KubrowPets-Kubrow">
|
||||
<input class="form-control" id="acquire-type-KubrowPets-KUBROW_ANTIGEN" list="datalist-ModularParts-KUBROW_ANTIGEN" />
|
||||
<input class="form-control" id="acquire-type-KubrowPets-KUBROW_MUTAGEN" list="datalist-ModularParts-KUBROW_MUTAGEN" />
|
||||
<input class="form-control" id="acquire-type-KubrowPets-KUBROW_ANTIGEN" list="datalist-ModularParts-KUBROW_ANTIGEN" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-KubrowPets-KUBROW_MUTAGEN" list="datalist-ModularParts-KUBROW_MUTAGEN" autocomplete="off" />
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
<table class="table table-hover w-100">
|
||||
@ -403,7 +403,7 @@
|
||||
<h5 class="card-header" data-loc="inventory_sentinelWeapons"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SentinelWeapons');return false;">
|
||||
<input class="form-control" id="acquire-type-SentinelWeapons" list="datalist-SentinelWeapons" />
|
||||
<input class="form-control" id="acquire-type-SentinelWeapons" list="datalist-SentinelWeapons" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
@ -421,13 +421,13 @@
|
||||
<h5 class="card-header" data-loc="inventory_operatorAmps"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="handleModularSelection('OperatorAmps');return false;">
|
||||
<input class="form-control" id="acquire-type-OperatorAmps" list="datalist-OperatorAmps" />
|
||||
<input class="form-control" id="acquire-type-OperatorAmps" list="datalist-OperatorAmps" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<form class="input-group mb-3 d-none" id="modular-OperatorAmps">
|
||||
<input class="form-control" id="acquire-type-OperatorAmps-AMP_OCULUS" list="datalist-ModularParts-AMP_OCULUS" />
|
||||
<input class="form-control" id="acquire-type-OperatorAmps-AMP_CORE" list="datalist-ModularParts-AMP_CORE" />
|
||||
<input class="form-control" id="acquire-type-OperatorAmps-AMP_BRACE" list="datalist-ModularParts-AMP_BRACE" />
|
||||
<input class="form-control" id="acquire-type-OperatorAmps-AMP_OCULUS" list="datalist-ModularParts-AMP_OCULUS" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-OperatorAmps-AMP_CORE" list="datalist-ModularParts-AMP_CORE" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-OperatorAmps-AMP_BRACE" list="datalist-ModularParts-AMP_BRACE" autocomplete="off" />
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
<table class="table table-hover w-100">
|
||||
@ -442,10 +442,10 @@
|
||||
<h5 class="card-header" data-loc="inventory_hoverboards"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="doAcquireModularEquipment('Hoverboards');return false;">
|
||||
<input class="form-control" id="acquire-type-Hoverboards-HB_DECK" list="datalist-ModularParts-HB_DECK" />
|
||||
<input class="form-control" id="acquire-type-Hoverboards-HB_ENGINE" list="datalist-ModularParts-HB_ENGINE" />
|
||||
<input class="form-control" id="acquire-type-Hoverboards-HB_FRONT" list="datalist-ModularParts-HB_FRONT" />
|
||||
<input class="form-control" id="acquire-type-Hoverboards-HB_JET" list="datalist-ModularParts-HB_JET" />
|
||||
<input class="form-control" id="acquire-type-Hoverboards-HB_DECK" list="datalist-ModularParts-HB_DECK" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-Hoverboards-HB_ENGINE" list="datalist-ModularParts-HB_ENGINE" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-Hoverboards-HB_FRONT" list="datalist-ModularParts-HB_FRONT" autocomplete="off" />
|
||||
<input class="form-control" id="acquire-type-Hoverboards-HB_JET" list="datalist-ModularParts-HB_JET" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
@ -463,7 +463,7 @@
|
||||
<h5 class="card-header" data-loc="inventory_evolutionProgress"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="doAcquireEvolution();return false;">
|
||||
<input class="form-control" id="acquire-type-EvolutionProgress" list="datalist-EvolutionProgress" />
|
||||
<input class="form-control" id="acquire-type-EvolutionProgress" list="datalist-EvolutionProgress" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
@ -479,7 +479,7 @@
|
||||
<h5 class="card-header" data-loc="inventory_boosters"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="doAcquireBooster();return false;">
|
||||
<input class="form-control" id="acquire-type-Boosters" list="datalist-Boosters" />
|
||||
<input class="form-control" id="acquire-type-Boosters" list="datalist-Boosters" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
@ -497,7 +497,7 @@
|
||||
<h5 class="card-header" data-loc="inventory_flavourItems"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('FlavourItems');return false;">
|
||||
<input class="form-control" id="acquire-type-FlavourItems" list="datalist-FlavourItems" />
|
||||
<input class="form-control" id="acquire-type-FlavourItems" list="datalist-FlavourItems" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
@ -514,7 +514,7 @@
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="doAcquireCountItems('ShipDecorations');return false;">
|
||||
<input class="form-control" id="ShipDecorations-count" type="number" value="1" />
|
||||
<input class="form-control w-50" id="acquire-type-ShipDecorations" list="datalist-ShipDecorations" />
|
||||
<input class="form-control w-50" id="acquire-type-ShipDecorations" list="datalist-ShipDecorations" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
@ -532,7 +532,7 @@
|
||||
<h5 class="card-header" data-loc="inventory_weaponSkins"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('WeaponSkins');return false;">
|
||||
<input class="form-control" id="acquire-type-WeaponSkins" list="datalist-WeaponSkins" />
|
||||
<input class="form-control" id="acquire-type-WeaponSkins" list="datalist-WeaponSkins" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
@ -558,6 +558,7 @@
|
||||
<button class="btn btn-primary" onclick="debounce(addMissingEquipment, ['ShipDecorations']);" data-loc="inventory_bulkAddShipDecorations"></button>
|
||||
<button class="btn btn-primary" onclick="debounce(addMissingEquipment, ['WeaponSkins']);" data-loc="inventory_bulkAddWeaponSkins"></button>
|
||||
<button class="btn btn-primary" onclick="debounce(addMissingEvolutionProgress);" data-loc="inventory_bulkAddEvolutionProgress"></button>
|
||||
<button class="btn btn-primary" onclick="removeIsNew();" data-loc="inventory_removeIsNew"></button>
|
||||
</div>
|
||||
<div class="mb-2 d-flex flex-wrap gap-2">
|
||||
<button class="btn btn-success" onclick="debounce(maxRankAllEquipment, ['Suits']);" data-loc="inventory_bulkRankUpSuits"></button>
|
||||
@ -609,7 +610,7 @@
|
||||
<h5 class="card-header" data-loc="guildView_techProjects"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form id="techProjects-form" class="input-group mb-3 d-none" onsubmit="addGuildTechProject();return false;">
|
||||
<input class="form-control" id="acquire-type-TechProjects" list="datalist-TechProjects" />
|
||||
<input class="form-control" id="acquire-type-TechProjects" list="datalist-TechProjects" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
@ -624,8 +625,8 @@
|
||||
<div class="card" style="height: 400px;">
|
||||
<h5 class="card-header" data-loc="guildView_vaultDecoRecipes"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form id="vaultDecoRecipes-form" class="input-group mb-3 d-none" onsubmit="addVaultDecoRecipe();return false;">
|
||||
<input class="form-control" id="acquire-type-VaultDecoRecipes" list="datalist-VaultDecoRecipes" />
|
||||
<form id="vaultDecoRecipes-form" class="input-group mb-3 d-none" onsubmit="addVaultItem('VaultDecoRecipes');return false;">
|
||||
<input class="form-control" id="acquire-type-VaultDecoRecipes" list="datalist-VaultDecoRecipes" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
@ -637,6 +638,42 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-lg-6">
|
||||
<div class="card" style="height: 400px;">
|
||||
<h5 class="card-header" data-loc="guildView_vaultMiscItems"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form id="vaultMiscItems-form" class="input-group mb-3 d-none" onsubmit="addVaultItem('VaultMiscItems');return false;">
|
||||
<input class="form-control" id="VaultMiscItems-count" type="number" value="1" />
|
||||
<input class="form-control w-50" id="acquire-type-VaultMiscItems" list="datalist-VaultMiscItems" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
<table class="table table-hover w-100">
|
||||
<tbody id="VaultMiscItems-list"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="card" style="height: 400px;">
|
||||
<h5 class="card-header" data-loc="guildView_vaultShipDecorations"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form id="vaultShipDecorations-form" class="input-group mb-3 d-none" onsubmit="addVaultItem('VaultShipDecorations');return false;">
|
||||
<input class="form-control" id="VaultShipDecorations-count" type="number" value="1" />
|
||||
<input class="form-control w-50" id="acquire-type-VaultShipDecorations" list="datalist-ShipDecorations" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
<table class="table table-hover w-100">
|
||||
<tbody id="VaultShipDecorations-list"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-lg-6">
|
||||
<div class="card" style="height: 400px;">
|
||||
@ -666,7 +703,8 @@
|
||||
<div class="card-body" id="guild-actions">
|
||||
<div class="mb-2 d-flex flex-wrap gap-2">
|
||||
<button class="btn btn-primary" onclick="debounce(addMissingTechProjects);" data-loc="guildView_bulkAddTechProjects"></button>
|
||||
<button class="btn btn-primary" onclick="debounce(addMissingVaultDecoRecipes);" data-loc="guildView_bulkAddVaultDecoRecipes"></button>
|
||||
<button class="btn btn-primary" onclick="debounce(addMissingVaultItems, ['VaultDecoRecipes']);" data-loc="guildView_bulkAddVaultDecoRecipes"></button>
|
||||
<button class="btn btn-primary" onclick="debounce(addMissingVaultItems, ['VaultShipDecorations']);" data-loc="guildView_bulkAddVaultShipDecorations"></button>
|
||||
</div>
|
||||
<div class="mb-2 d-flex flex-wrap gap-2">
|
||||
<button class="btn btn-success" onclick="debounce(fundAllTechProjects);" data-loc="guildView_bulkFundTechProjects"></button>
|
||||
@ -729,7 +767,7 @@
|
||||
<form class="input-group mb-3" onsubmit="doPushArchonCrystalUpgrade();return false;">
|
||||
<input type="number" id="archon-crystal-add-count" min="1" max="10000" value="1" class="form-control" style="max-width:100px" />
|
||||
<span class="input-group-text">x</span>
|
||||
<input class="form-control" list="datalist-archonCrystalUpgrades" />
|
||||
<input class="form-control" list="datalist-archonCrystalUpgrades" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<table class="table table-hover w-100">
|
||||
@ -839,7 +877,7 @@
|
||||
<div class="card-body">
|
||||
<form class="input-group mb-3" onsubmit="doAcquireMod();return false;">
|
||||
<input class="form-control" id="mod-count" type="number" value="1"/>
|
||||
<input class="form-control w-50" id="mod-to-acquire" list="datalist-mods" />
|
||||
<input class="form-control w-50" id="mod-to-acquire" list="datalist-mods" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
<button class="btn btn-success" onclick="window.maxed=true" data-loc="mods_addMax"></button>
|
||||
</form>
|
||||
@ -867,7 +905,7 @@
|
||||
<h5 class="card-header" data-loc="quests_list"></h5>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('QuestKeys');return false;">
|
||||
<input class="form-control" id="acquire-type-QuestKeys" list="datalist-QuestKeys" />
|
||||
<input class="form-control" id="acquire-type-QuestKeys" list="datalist-QuestKeys" autocomplete="off" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<div class="overflow-auto">
|
||||
@ -1034,6 +1072,20 @@
|
||||
<input class="form-check-input" type="checkbox" id="finishInvasionsInOneMission" />
|
||||
<label class="form-check-label" for="finishInvasionsInOneMission" data-loc="cheats_finishInvasionsInOneMission"></label>
|
||||
</div>
|
||||
<form class="form-group mt-2" onsubmit="doChangeSupportedSyndicate(); return false;">
|
||||
<label class="form-label" for="changeSyndicate" data-loc="cheats_changeSupportedSyndicate"></label>
|
||||
<div class="input-group">
|
||||
<select class="form-control" id="changeSyndicate"></select>
|
||||
<button class="btn btn-secondary" type="submit" data-loc="cheats_changeButton"></button>
|
||||
</div>
|
||||
</form>
|
||||
<form class="form-group mt-2">
|
||||
<label class="form-label" for="spoofMasteryRank" data-loc="cheats_spoofMasteryRank"></label>
|
||||
<div class="input-group">
|
||||
<input class="form-control" id="spoofMasteryRank" type="number" min="-1" max="65535" data-default="-1" />
|
||||
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
|
||||
</div>
|
||||
</form>
|
||||
<form class="form-group mt-2">
|
||||
<label class="form-label" for="nemesisHenchmenKillsMultiplierGrineer" data-loc="cheats_nemesisHenchmenKillsMultiplierGrineer"></label>
|
||||
<div class="input-group">
|
||||
@ -1076,6 +1128,20 @@
|
||||
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
|
||||
</div>
|
||||
</form>
|
||||
<form class="form-group mt-2">
|
||||
<label class="form-label" for="relicRewardItemCountMultiplier" data-loc="cheats_relicRewardItemCountMultiplier"></label>
|
||||
<div class="input-group">
|
||||
<input class="form-control" id="relicRewardItemCountMultiplier" type="number" min="1" max="1000000" data-default="1" />
|
||||
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
|
||||
</div>
|
||||
</form>
|
||||
<form class="form-group mt-2">
|
||||
<label class="form-label" for="nightwaveStandingMultiplier" data-loc="cheats_nightwaveStandingMultiplier"></label>
|
||||
<div class="input-group">
|
||||
<input class="form-control" id="nightwaveStandingMultiplier" type="number" min="1" max="1000000" data-default="1" />
|
||||
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="mt-2 mb-2 d-flex flex-wrap gap-2">
|
||||
<button class="btn btn-primary" onclick="debounce(doUnlockAllShipFeatures);" data-loc="cheats_unlockAllShipFeatures"></button>
|
||||
<button class="btn btn-primary" onclick="debounce(unlockAllMissions);" data-loc="cheats_unlockAllMissions"></button>
|
||||
@ -1090,13 +1156,6 @@
|
||||
<button class="btn btn-primary" onclick="debounce(unlockAllProfitTakerStages);" data-loc="cheats_unlockAllProfitTakerStages"></button>
|
||||
<button class="btn btn-primary" onclick="debounce(unlockAllSimarisResearchEntries);" data-loc="cheats_unlockAllSimarisResearchEntries"></button>
|
||||
</div>
|
||||
<form class="mt-2" onsubmit="doChangeSupportedSyndicate(); return false;">
|
||||
<label class="form-label" for="changeSyndicate" data-loc="cheats_changeSupportedSyndicate"></label>
|
||||
<div class="input-group">
|
||||
<select class="form-control" id="changeSyndicate"></select>
|
||||
<button class="btn btn-secondary" type="submit" data-loc="cheats_changeButton"></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1124,27 +1183,6 @@
|
||||
<input class="form-check-input" type="checkbox" id="skipClanKeyCrafting" />
|
||||
<label class="form-check-label" for="skipClanKeyCrafting" data-loc="cheats_skipClanKeyCrafting"></label>
|
||||
</div>
|
||||
<form class="form-group mt-2" onsubmit="doSaveConfigInt('spoofMasteryRank'); return false;">
|
||||
<label class="form-label" for="spoofMasteryRank" data-loc="cheats_spoofMasteryRank"></label>
|
||||
<div class="input-group">
|
||||
<input class="form-control" id="spoofMasteryRank" type="number" min="-1" max="65535" data-default="-1" />
|
||||
<button class="btn btn-secondary" type="submit" data-loc="cheats_save"></button>
|
||||
</div>
|
||||
</form>
|
||||
<form class="form-group mt-2" onsubmit="doSaveConfigInt('relicRewardItemCountMultiplier'); return false;">
|
||||
<label class="form-label" for="relicRewardItemCountMultiplier" data-loc="cheats_relicRewardItemCountMultiplier"></label>
|
||||
<div class="input-group">
|
||||
<input class="form-control" id="relicRewardItemCountMultiplier" type="number" min="1" max="1000000" data-default="1" />
|
||||
<button class="btn btn-secondary" type="submit" data-loc="cheats_save"></button>
|
||||
</div>
|
||||
</form>
|
||||
<form class="form-group mt-2" onsubmit="doSaveConfigInt('nightwaveStandingMultiplier'); return false;">
|
||||
<label class="form-label" for="nightwaveStandingMultiplier" data-loc="cheats_nightwaveStandingMultiplier"></label>
|
||||
<div class="input-group">
|
||||
<input class="form-control" id="nightwaveStandingMultiplier" type="number" min="1" max="1000000" data-default="1" />
|
||||
<button class="btn btn-secondary" type="submit" data-loc="cheats_save"></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1188,11 +1226,6 @@
|
||||
<label class="form-check-label" for="unfaithfulBugFixes.useAnniversaryTagForOldGoals" data-loc="worldState_useAnniversaryTagForOldGoals"></label>
|
||||
<abbr data-loc-inc="worldState_anniversary"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="worldState.wolfHunt" />
|
||||
<label class="form-check-label" for="worldState.wolfHunt" data-loc="worldState_wolfHunt"></label>
|
||||
<abbr data-loc-inc="worldState_galleonOfGhouls|worldState_orphixVenom|worldState_anniversary"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="worldState.orphixVenom" />
|
||||
<label class="form-check-label" for="worldState.orphixVenom" data-loc="worldState_orphixVenom"></label>
|
||||
@ -1212,6 +1245,15 @@
|
||||
<input class="form-check-input" type="checkbox" id="worldState.qtccAlerts" />
|
||||
<label class="form-check-label" for="worldState.qtccAlerts" data-loc="worldState_qtccAlerts"></label>
|
||||
</div>
|
||||
<div class="form-group mt-2">
|
||||
<label class="form-label" for="worldState.wolfHunt" data-loc="worldState_wolfHunt"></label>
|
||||
<abbr data-loc-inc="worldState_galleonOfGhouls|worldState_orphixVenom|worldState_anniversary"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
|
||||
<select class="form-control" id="worldState.wolfHunt" data-default="null">
|
||||
<option value="null" data-loc="disabled"></option>
|
||||
<option value="1" data-loc="worldState_from_year" data-loc-replace="2025"></option>
|
||||
<option value="0" data-loc="worldState_from_year" data-loc-replace="2019"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group mt-2 d-flex gap-2">
|
||||
<div class="flex-fill">
|
||||
<label class="form-label" for="worldState.hallowedNightmares" data-loc="worldState_hallowedNightmares"></label>
|
||||
@ -1465,7 +1507,7 @@
|
||||
<form class="form-group mt-2" onsubmit="doSaveConfigStringArray('worldState.circuitGameModes'); return false;">
|
||||
<label class="form-label" for="worldState.circuitGameModes" data-loc="worldState_theCircuitOverride"></label>
|
||||
<div class="input-group">
|
||||
<input id="worldState.circuitGameModes" type="text" class="form-control tags-input" list="datalist-circuitGameModes" />
|
||||
<input id="worldState.circuitGameModes" type="text" class="form-control tags-input" list="datalist-circuitGameModes" autocomplete="off" />
|
||||
<button class="btn btn-secondary" type="submit" data-loc="cheats_save"></button>
|
||||
</div>
|
||||
</form>
|
||||
@ -1548,6 +1590,7 @@
|
||||
<datalist id="datalist-FlavourItems"></datalist>
|
||||
<datalist id="datalist-ShipDecorations"></datalist>
|
||||
<datalist id="datalist-WeaponSkins"></datalist>
|
||||
<datalist id="datalist-VaultMiscItems"></datalist>
|
||||
<datalist id="datalist-circuitGameModes">
|
||||
<option>Survival</option>
|
||||
<option>VoidFlood</option>
|
||||
|
||||
@ -559,7 +559,7 @@ function fetchItemList() {
|
||||
});
|
||||
} else if (type == "Syndicates") {
|
||||
items.forEach(item => {
|
||||
if (item.uniqueName === "ConclaveSyndicate") {
|
||||
if (["ConclaveSyndicate", "NightcapJournalSyndicate"].includes(item.uniqueName)) {
|
||||
return;
|
||||
}
|
||||
if (item.uniqueName.startsWith("RadioLegion")) {
|
||||
@ -711,6 +711,10 @@ function fetchItemList() {
|
||||
option.value += " (" + item.subtype + ")";
|
||||
}
|
||||
document.getElementById("datalist-" + type).appendChild(option);
|
||||
if (item.eligibleForVault) {
|
||||
const vaultOption = option.cloneNode(true);
|
||||
document.getElementById("datalist-VaultMiscItems").appendChild(vaultOption);
|
||||
}
|
||||
} else {
|
||||
//console.log(`Not adding ${item.uniqueName} to datalist for ${type} due to duplicate display name: ${item.name}`);
|
||||
}
|
||||
@ -828,7 +832,7 @@ function updateInventory() {
|
||||
const td = document.createElement("td");
|
||||
td.classList = "text-end text-nowrap";
|
||||
|
||||
let maxXP = Math.pow(itemMap[item.ItemType].maxLevelCap ?? 30, 2) * 1000;
|
||||
let maxXP = Math.pow(itemMap[item.ItemType]?.maxLevelCap ?? 30, 2) * 1000;
|
||||
if (
|
||||
category != "Suits" &&
|
||||
category != "SpaceSuits" &&
|
||||
@ -855,7 +859,7 @@ function updateInventory() {
|
||||
}
|
||||
}
|
||||
if (
|
||||
itemMap[item.ItemType].maxLevelCap > 30 &&
|
||||
itemMap[item.ItemType]?.maxLevelCap > 30 &&
|
||||
(item.Polarized ?? 0) < (itemMap[item.ItemType].maxLevelCap - 30) / 2
|
||||
) {
|
||||
const a = document.createElement("a");
|
||||
@ -1802,6 +1806,8 @@ function updateInventory() {
|
||||
document.getElementById("VaultRegularCredits-owned").classList.remove("mb-0");
|
||||
document.getElementById("vaultPremiumCredits-form").classList.remove("d-none");
|
||||
document.getElementById("VaultPremiumCredits-owned").classList.remove("mb-0");
|
||||
document.getElementById("vaultMiscItems-form").classList.remove("d-none");
|
||||
document.getElementById("vaultShipDecorations-form").classList.remove("d-none");
|
||||
}
|
||||
if (userGuildMember.Rank <= 1) {
|
||||
document.querySelectorAll("#guild-actions button").forEach(btn => {
|
||||
@ -1892,42 +1898,55 @@ function updateInventory() {
|
||||
document.getElementById("TechProjects-list").appendChild(tr);
|
||||
});
|
||||
|
||||
document.getElementById("VaultDecoRecipes-list").innerHTML = "";
|
||||
guildData.VaultDecoRecipes ??= [];
|
||||
guildData.VaultDecoRecipes.forEach(item => {
|
||||
const datalist = document.getElementById("datalist-VaultDecoRecipes");
|
||||
const optionToRemove = datalist.querySelector(`option[data-key="${item.ItemType}"]`);
|
||||
if (optionToRemove) {
|
||||
datalist.removeChild(optionToRemove);
|
||||
}
|
||||
const tr = document.createElement("tr");
|
||||
tr.setAttribute("data-item-type", item.ItemType);
|
||||
{
|
||||
const td = document.createElement("td");
|
||||
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
|
||||
tr.appendChild(td);
|
||||
}
|
||||
{
|
||||
const td = document.createElement("td");
|
||||
td.classList = "text-end text-nowrap";
|
||||
|
||||
if (userGuildMember && userGuildMember.Rank <= 1) {
|
||||
const a = document.createElement("a");
|
||||
a.href = "#";
|
||||
a.onclick = function (event) {
|
||||
event.preventDefault();
|
||||
reAddToItemList(itemMap, "VaultDecoRecipes", item.ItemType);
|
||||
removeVaultDecoRecipe(item.ItemType);
|
||||
};
|
||||
a.title = loc("code_remove");
|
||||
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M135.2 17.7L128 32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H320l-7.2-14.3C307.4 6.8 296.3 0 284.2 0H163.8c-12.1 0-23.2 6.8-28.6 17.7zM416 128H32L53.2 467c1.6 25.3 22.6 45 47.9 45H346.9c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>`;
|
||||
td.appendChild(a);
|
||||
["VaultDecoRecipes", "VaultMiscItems", "VaultShipDecorations"].forEach(vaultKey => {
|
||||
document.getElementById(vaultKey + "-list").innerHTML = "";
|
||||
(guildData[vaultKey] ??= []).forEach(item => {
|
||||
if (vaultKey == "VaultDecoRecipes") {
|
||||
const datalist = document.getElementById("datalist-VaultDecoRecipes");
|
||||
const optionToRemove = datalist.querySelector(
|
||||
`option[data-key="${item.ItemType}"]`
|
||||
);
|
||||
if (optionToRemove) {
|
||||
datalist.removeChild(optionToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
tr.appendChild(td);
|
||||
}
|
||||
const tr = document.createElement("tr");
|
||||
tr.setAttribute("data-item-type", item.ItemType);
|
||||
{
|
||||
const td = document.createElement("td");
|
||||
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
|
||||
if (item.ItemCount > 1) {
|
||||
td.innerHTML += ` <span title='${loc("code_count")}'>🗍 ${parseInt(item.ItemCount)}</span>`;
|
||||
}
|
||||
tr.appendChild(td);
|
||||
}
|
||||
{
|
||||
const td = document.createElement("td");
|
||||
td.classList = "text-end text-nowrap";
|
||||
const canRemove =
|
||||
vaultKey === "VaultDecoRecipes"
|
||||
? userGuildMember && userGuildMember.Rank <= 1
|
||||
: userGuildPermissions && userGuildPermissions & 64;
|
||||
if (canRemove) {
|
||||
const a = document.createElement("a");
|
||||
a.href = "#";
|
||||
a.title = loc("code_remove");
|
||||
a.onclick = e => {
|
||||
e.preventDefault();
|
||||
if (vaultKey == "VaultDecoRecipes") {
|
||||
reAddToItemList(itemMap, vaultKey, item.ItemType);
|
||||
}
|
||||
removeVaultItem(vaultKey, item.ItemType, item.ItemCount * -1);
|
||||
};
|
||||
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M135.2 17.7L128 32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H320l-7.2-14.3C307.4 6.8 296.3 0 284.2 0H163.8c-12.1 0-23.2 6.8-28.6 17.7zM416 128H32L53.2 467c1.6 25.3 22.6 45 47.9 45H346.9c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>`;
|
||||
td.appendChild(a);
|
||||
}
|
||||
tr.appendChild(td);
|
||||
}
|
||||
|
||||
document.getElementById("VaultDecoRecipes-list").appendChild(tr);
|
||||
document.getElementById(vaultKey + "-list").appendChild(tr);
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById("Members-list").innerHTML = "";
|
||||
@ -2158,6 +2177,15 @@ function removeCustomization(uniqueName) {
|
||||
});
|
||||
}
|
||||
|
||||
function removeIsNew() {
|
||||
revalidateAuthz().then(() => {
|
||||
const req = $.get("/custom/removeIsNew?" + window.authz);
|
||||
req.done(() => {
|
||||
updateInventory();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getRequiredParts(category, WeaponType) {
|
||||
switch (category) {
|
||||
case "Hoverboards":
|
||||
@ -2346,41 +2374,52 @@ function addMissingEquipment(categories) {
|
||||
}
|
||||
}
|
||||
|
||||
function addVaultDecoRecipe() {
|
||||
const uniqueName = getKey(document.getElementById("acquire-type-VaultDecoRecipes"));
|
||||
if (!uniqueName) {
|
||||
$("#acquire-type-VaultDecoRecipes").addClass("is-invalid").focus();
|
||||
function addVaultItem(vaultType) {
|
||||
const ItemType = getKey(document.getElementById(`acquire-type-${vaultType}`));
|
||||
if (!ItemType) {
|
||||
$(`#acquire-type-${vaultType}`).addClass("is-invalid").focus();
|
||||
return;
|
||||
}
|
||||
revalidateAuthz().then(() => {
|
||||
const req = $.post({
|
||||
url: "/custom/addVaultDecoRecipe?" + window.authz + "&guildId=" + window.guildId,
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify([
|
||||
{
|
||||
ItemType: uniqueName,
|
||||
ItemCount: 1
|
||||
}
|
||||
])
|
||||
const ItemCount = ["VaultMiscItems", "VaultShipDecorations"].includes(vaultType)
|
||||
? parseInt($(`#${vaultType}-count`).val())
|
||||
: 1;
|
||||
if (ItemCount != 0) {
|
||||
revalidateAuthz().then(() => {
|
||||
const req = $.post({
|
||||
url: "/custom/addVaultTypeCount?" + window.authz + "&guildId=" + window.guildId,
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify({
|
||||
vaultType,
|
||||
items: [
|
||||
{
|
||||
ItemType,
|
||||
ItemCount
|
||||
}
|
||||
]
|
||||
})
|
||||
});
|
||||
req.done(() => {
|
||||
document.getElementById(`acquire-type-${vaultType}`).value = "";
|
||||
updateInventory();
|
||||
});
|
||||
});
|
||||
req.done(() => {
|
||||
document.getElementById("acquire-type-VaultDecoRecipes").value = "";
|
||||
updateInventory();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function removeVaultDecoRecipe(uniqueName) {
|
||||
function removeVaultItem(vaultType, ItemType, ItemCount) {
|
||||
revalidateAuthz().then(() => {
|
||||
const req = $.post({
|
||||
url: "/custom/addVaultDecoRecipe?" + window.authz + "&guildId=" + window.guildId,
|
||||
url: "/custom/addVaultTypeCount?" + window.authz + "&guildId=" + window.guildId,
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify([
|
||||
{
|
||||
ItemType: uniqueName,
|
||||
ItemCount: -1
|
||||
}
|
||||
])
|
||||
data: JSON.stringify({
|
||||
vaultType,
|
||||
items: [
|
||||
{
|
||||
ItemType,
|
||||
ItemCount
|
||||
}
|
||||
]
|
||||
})
|
||||
});
|
||||
req.done(() => {
|
||||
updateInventory();
|
||||
@ -2462,13 +2501,16 @@ function fundGuildTechProject(uniqueName) {
|
||||
});
|
||||
}
|
||||
|
||||
function dispatchAddVaultDecoRecipesBatch(requests) {
|
||||
function dispatchAddVaultItemsBatch(requests, vaultType) {
|
||||
return new Promise(resolve => {
|
||||
revalidateAuthz().then(() => {
|
||||
const req = $.post({
|
||||
url: "/custom/addVaultDecoRecipe?" + window.authz + "&guildId=" + window.guildId,
|
||||
url: "/custom/addVaultItems?" + window.authz + "&guildId=" + window.guildId,
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify(requests)
|
||||
data: JSON.stringify({
|
||||
vaultType,
|
||||
items: requests
|
||||
})
|
||||
});
|
||||
req.done(() => {
|
||||
updateInventory();
|
||||
@ -2478,20 +2520,23 @@ function dispatchAddVaultDecoRecipesBatch(requests) {
|
||||
});
|
||||
}
|
||||
|
||||
function addMissingVaultDecoRecipes() {
|
||||
function addMissingVaultItems(vaultType) {
|
||||
const requests = [];
|
||||
|
||||
document.querySelectorAll("#datalist-VaultDecoRecipes" + " option").forEach(elm => {
|
||||
if (!document.querySelector("#VaultDecoRecipes-list [data-item-type='" + elm.getAttribute("data-key") + "']")) {
|
||||
requests.push({ ItemType: elm.getAttribute("data-key"), ItemCount: 1 });
|
||||
document.querySelectorAll(`#datalist-${vaultType} option`).forEach(elm => {
|
||||
const datalist = vaultType === "VaultShipDecorations" ? "ShipDecorations" : vaultType;
|
||||
if (!document.querySelector(`#${datalist}-list [data-item-type='${elm.getAttribute("data-key")}']`)) {
|
||||
let ItemCount = 1;
|
||||
if (category == "VaultShipDecorations") ItemCount = 999999;
|
||||
requests.push({ ItemType: elm.getAttribute("data-key"), ItemCount });
|
||||
}
|
||||
});
|
||||
|
||||
if (
|
||||
requests.length != 0 &&
|
||||
window.confirm(loc("code_addDecoRecipesConfirm").split("|COUNT|").join(requests.length))
|
||||
window.confirm(loc("code_addVaultItemsConfirm").split("|COUNT|").join(requests.length))
|
||||
) {
|
||||
return dispatchAddVaultDecoRecipesBatch(requests);
|
||||
return dispatchAddVaultItemsBatch(requests, vaultType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3240,13 +3285,13 @@ function unlockFocusSchool(upgradeType) {
|
||||
return new Promise(resolve => {
|
||||
// Deselect current FocusAbility so we will be able to unlock the way for free
|
||||
$.post({
|
||||
url: "/api/focus.php?" + window.authz + "&op=5",
|
||||
url: "/api/focus.php?" + window.authz + "&op=ActivateWay",
|
||||
contentType: "text/plain",
|
||||
data: JSON.stringify({ FocusType: null })
|
||||
}).done(function () {
|
||||
// Unlock the way now
|
||||
$.post({
|
||||
url: "/api/focus.php?" + window.authz + "&op=2",
|
||||
url: "/api/focus.php?" + window.authz + "&op=UnlockWay",
|
||||
contentType: "text/plain",
|
||||
data: JSON.stringify({
|
||||
FocusType: upgradeType
|
||||
@ -3445,6 +3490,12 @@ single.getRoute("#guild-route").on("beforeload", function () {
|
||||
document.getElementById("VaultDecoRecipes-list").innerHTML = "";
|
||||
document.getElementById("vaultDecoRecipes-form").classList.add("d-none");
|
||||
document.getElementById("acquire-type-VaultDecoRecipes").value = "";
|
||||
document.getElementById("VaultMiscItems-list").innerHTML = "";
|
||||
document.getElementById("vaultMiscItems-form").classList.add("d-none");
|
||||
document.getElementById("acquire-type-VaultMiscItems").value = "";
|
||||
document.getElementById("VaultShipDecorations-list").innerHTML = "";
|
||||
document.getElementById("vaultShipDecorations-form").classList.add("d-none");
|
||||
document.getElementById("acquire-type-VaultShipDecorations").value = "";
|
||||
document.getElementById("Alliance-list").innerHTML = "";
|
||||
document.getElementById("guildView-alliance").textContent = "";
|
||||
document.getElementById("Members-list").innerHTML = "";
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
// German translation by Animan8000
|
||||
dict = {
|
||||
general_inventoryUpdateNote: `Hinweis: Um Änderungen im Spiel zu sehen, musst du dein Inventar neu synchronisieren, z. B. mit dem /sync Befehl des Bootstrappers, durch Besuch eines Dojo/Relais oder durch erneutes Einloggen.`,
|
||||
general_inventoryUpdateNoteGameWs: `[UNTRANSLATED] Note: You may need to reopen any menu you are on for changes to be reflected.`,
|
||||
general_inventoryUpdateNote: `Hinweis: Um Änderungen im Spiel zu sehen, musst du dein Inventar neu synchronisieren, z. B. mit dem /sync Befehl des Bootstrappers im Spielchat, durch Besuch eines Dojo/Relais oder durch erneutes Einloggen.`,
|
||||
general_inventoryUpdateNoteGameWs: `Hinweis: Möglicherweise musst du ein Menü neu öffnen, damit die Änderungen sichtbar werden.`,
|
||||
general_addButton: `Hinzufügen`,
|
||||
general_setButton: `Festlegen`,
|
||||
general_none: `Keines`,
|
||||
general_none: `Nichts`,
|
||||
general_bulkActions: `Massenaktionen`,
|
||||
general_loading: `Lädt...`,
|
||||
|
||||
code_loginFail: `Anmeldung fehlgeschlagen. Bitte überprüfe deine Angaben.`,
|
||||
code_regFail: `Registrierung fehlgeschlagen. Account existiert bereits?`,
|
||||
code_changeNameConfirm: `In welchen Namen möchtest du deinen Account umbenennen?`,
|
||||
code_changeNameRetry: `[UNTRANSLATED] |NAME| is already taken.`,
|
||||
code_changeNameRetry: `|NAME| ist bereits vergeben.`,
|
||||
code_deleteAccountConfirm: `Bist du sicher, dass du deinen Account |DISPLAYNAME| (|EMAIL|) löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden.`,
|
||||
code_archgun: `Arch-Gewehr`,
|
||||
code_melee: `Nahkampf`,
|
||||
@ -32,8 +32,8 @@ dict = {
|
||||
code_renamePrompt: `Neuen benutzerdefinierten Namen eingeben:`,
|
||||
code_remove: `Entfernen`,
|
||||
code_addItemsConfirm: `Bist du sicher, dass du |COUNT| Gegenstände zu deinem Account hinzufügen möchtest?`,
|
||||
code_addTechProjectsConfirm: `[UNTRANSLATED] Are you sure you want to add |COUNT| research to your clan?`,
|
||||
code_addDecoRecipesConfirm: `[UNTRANSLATED] Are you sure you want to add |COUNT| deco recipes to your clan?`,
|
||||
code_addTechProjectsConfirm: `Bist du sicher, dass du |COUNT| Forschungen zu deinem Clan hinzufügen möchtest?`,
|
||||
code_addVaultItemsConfirm: `Bist du sicher, dass du |COUNT| Gegenstände zu deinem Clan-Tresor hinzufügen möchtest?`,
|
||||
code_succRankUp: `Erfolgreich aufgestiegen.`,
|
||||
code_noEquipmentToRankUp: `Keine Ausstattung zum Rangaufstieg verfügbar.`,
|
||||
code_succAdded: `Erfolgreich hinzugefügt.`,
|
||||
@ -45,10 +45,10 @@ dict = {
|
||||
code_rank: `Rang`,
|
||||
code_rankUp: `Rang erhöhen`,
|
||||
code_rankDown: `Rang verringern`,
|
||||
code_unlockLevelCap: `[UNTRANSLATED] Unlock level cap`,
|
||||
code_unlockLevelCap: `Level-Cap freischalten`,
|
||||
code_count: `Anzahl`,
|
||||
code_focusAllUnlocked: `Alle Fokus-Schulen sind bereits freigeschaltet.`,
|
||||
code_focusUnlocked: `|COUNT| neue Fokus-Schulen freigeschaltet! Ein Inventar-Update wird benötigt, damit die Änderungen im Spiel sichtbar werden. Die Sternenkarte zu besuchen, sollte der einfachste Weg sein, dies auszulösen.`,
|
||||
code_focusUnlocked: `|COUNT| neue Fokus-Schulen freigeschaltet! Ein Inventar-Update wird benötigt, damit die Änderungen im Spiel sichtbar werden.`,
|
||||
code_addModsConfirm: `Bist du sicher, dass du |COUNT| Mods zu deinem Account hinzufügen möchtest?`,
|
||||
code_succImport: `Erfolgreich importiert.`,
|
||||
code_succRelog: `Fertig. Bitte beachte, dass du dich neu einloggen musst, um Änderungen im Spiel zu sehen.`,
|
||||
@ -65,22 +65,22 @@ dict = {
|
||||
code_completed: `Abgeschlossen`,
|
||||
code_active: `Aktiv`,
|
||||
code_pigment: `Pigment`,
|
||||
code_controller: `[UNTRANSLATED] Controller cursor`,
|
||||
code_mouseLine: `[UNTRANSLATED] Line cursor`,
|
||||
code_mouse: `[UNTRANSLATED] Cursor`,
|
||||
code_controller: `Controller-Cursor`,
|
||||
code_mouseLine: `Linien-Cursor`,
|
||||
code_mouse: `Cursor`,
|
||||
code_itemColorPalette: `|ITEM| Farbpalette`,
|
||||
code_mature: `Für den Kampf auswachsen lassen`,
|
||||
code_unmature: `Genetisches Altern zurücksetzen`,
|
||||
code_fund: `[UNTRANSLATED] Fund`,
|
||||
code_funded: `[UNTRANSLATED] Funded`,
|
||||
code_replays: `[UNTRANSLATED] Replays`,
|
||||
code_fund: `Spenden`,
|
||||
code_funded: `Gespendet`,
|
||||
code_replays: `Wiederholungen`,
|
||||
code_stalker: `Stalker`,
|
||||
code_cutName: `Frisur: |INDEX|`,
|
||||
code_drifterBeardName: `Drifter-Bart: |INDEX|`,
|
||||
code_drifterFaceName: `Drifter-Gesicht: |INDEX|`,
|
||||
code_operatorFaceName: `Operator-Gesicht: |INDEX|`,
|
||||
code_succChange: `Erfolgreich geändert.`,
|
||||
code_requiredInvigorationUpgrade: `[UNTRANSLATED] You must select both an offensive & utility upgrade.`,
|
||||
code_requiredInvigorationUpgrade: `Du musst sowohl ein Offensiv- als auch ein Support-Upgrade auswählen.`,
|
||||
login_description: `Melde dich mit deinem OpenWF-Account an (denselben Angaben wie im Spiel, wenn du dich mit diesem Server verbindest).`,
|
||||
login_emailLabel: `E-Mail-Adresse`,
|
||||
login_passwordLabel: `Passwort`,
|
||||
@ -96,8 +96,8 @@ dict = {
|
||||
navbar_cheats: `Cheats`,
|
||||
navbar_import: `Importieren`,
|
||||
inventory_addItems: `Gegenstände hinzufügen`,
|
||||
inventory_addItemByItemType: `[UNTRANSLATED] Raw`,
|
||||
inventory_addItemByItemType_warning: `[UNTRANSLATED] Use this feature at your own risk. It may break your inventory, and you will need to remove items manually if something goes wrong.`,
|
||||
inventory_addItemByItemType: `Roh`,
|
||||
inventory_addItemByItemType_warning: `Verwende diese Funktion auf eigene Gefahr. Sie kann dein Inventar beschädigen und du musst Gegenstände manuell entfernen, falls etwas schiefgeht.`,
|
||||
inventory_suits: `Warframes`,
|
||||
inventory_longGuns: `Primärwaffen`,
|
||||
inventory_pistols: `Sekundärwaffen`,
|
||||
@ -123,10 +123,10 @@ dict = {
|
||||
inventory_bulkAddSpaceWeapons: `Fehlende Archwing-Waffen hinzufügen`,
|
||||
inventory_bulkAddSentinels: `Fehlende Wächter hinzufügen`,
|
||||
inventory_bulkAddSentinelWeapons: `Fehlende Wächter-Waffen hinzufügen`,
|
||||
inventory_bulkAddFlavourItems: `[UNTRANSLATED] Add Missing Flavour Items`,
|
||||
inventory_bulkAddShipDecorations: `[UNTRANSLATED] Add Missing Ship Decorations`,
|
||||
inventory_bulkAddFlavourItems: `Fehlende Sammlerstücke hinzufügen`,
|
||||
inventory_bulkAddShipDecorations: `Fehlende Schiffsdekorationen hinzufügen`,
|
||||
inventory_bulkAddEvolutionProgress: `Fehlende Incarnon-Entwicklungsfortschritte hinzufügen`,
|
||||
inventory_bulkAddWeaponSkins: `[UNTRANSLATED] Add Missing Skins`,
|
||||
inventory_bulkAddWeaponSkins: `Fehlende Skins hinzufügen`,
|
||||
inventory_bulkRankUpSuits: `Alle Warframes auf Max. Rang`,
|
||||
inventory_bulkRankUpWeapons: `Alle Waffen auf Max. Rang`,
|
||||
inventory_bulkRankUpSpaceSuits: `Alle Archwings auf Max. Rang`,
|
||||
@ -135,6 +135,7 @@ dict = {
|
||||
inventory_bulkRankUpSentinelWeapons: `Alle Wächter-Waffen auf Max. Rang`,
|
||||
inventory_bulkRankUpEvolutionProgress: `Alle Incarnon-Entwicklungsfortschritte auf Max. Rang`,
|
||||
inventory_maxPlexus: `Plexus auf Max. Rang`,
|
||||
inventory_removeIsNew: `[UNTRANSLATED] Remove New Equipment Exclamation Icon`,
|
||||
|
||||
quests_list: `Quests`,
|
||||
quests_completeAll: `Alle Quests abschließen`,
|
||||
@ -179,8 +180,8 @@ dict = {
|
||||
invigorations_utility_EnergyRegen: `+2 Energieregeneration pro Sekunde`,
|
||||
|
||||
detailedView_invigorationOffensiveLabel: `Offensives Upgrade`,
|
||||
detailedView_invigorationUtilityLabel: `[UNTRANSLATED] Utility Upgrade`,
|
||||
detailedView_invigorationExpiryLabel: `[UNTRANSLATED] Invigoration Expiry (optional)`,
|
||||
detailedView_invigorationUtilityLabel: `Support Upgrade`,
|
||||
detailedView_invigorationExpiryLabel: `Kräftigungs-Ablaufdatum (optional)`,
|
||||
|
||||
abilityOverride_label: `Fähigkeitsüberschreibung`,
|
||||
abilityOverride_onSlot: `auf Slot`,
|
||||
@ -199,7 +200,7 @@ dict = {
|
||||
cheats_skipTutorial: `Tutorial überspringen`,
|
||||
cheats_skipAllDialogue: `Alle Dialoge überspringen`,
|
||||
cheats_unlockAllScans: `Alle Scans freischalten`,
|
||||
cheats_unlockSuccRelog: `[UNTRANSLATED] Success. Please note that you'll need to relog for the client to refresh this.`,
|
||||
cheats_unlockSuccRelog: `Erfolgreich. Bitte beachte, dass du dich neu einloggen musst, damit der Client dies aktualisiert.`,
|
||||
cheats_unlockAllMissions: `Alle Missionen freischalten`,
|
||||
cheats_unlockAllMissions_ok: `Erfolgreich. Bitte beachte, dass du ein Dojo/Relais besuchen oder dich neu einloggen musst, damit die Sternenkarte aktualisiert wird.`,
|
||||
cheats_infiniteCredits: `Unendlich Credits`,
|
||||
@ -233,7 +234,7 @@ dict = {
|
||||
cheats_baroFullyStocked: `Baro hat volles Inventar`,
|
||||
cheats_syndicateMissionsRepeatable: `Syndikat-Missionen wiederholbar`,
|
||||
cheats_unlockAllProfitTakerStages: `Alle Profiteintreiber-Phasen freischalten`,
|
||||
cheats_unlockSuccInventory: `[UNTRANSLATED] Success. Please note that you'll need to resync your inventory, e.g. using the bootstrapper's /sync command in game chat, visiting a dojo/relay, or relogging.`,
|
||||
cheats_unlockSuccInventory: `Erfolgreich. Bitte beachte, dass du dein Inventar neu synchronisieren musst, z. B. mit dem /sync Befehl des Bootstrappers im Spielchat, durch Besuch eines Dojo/Relais oder durch erneutes Einloggen.`,
|
||||
cheats_instantFinishRivenChallenge: `Riven-Mod Herausforderung sofort abschließen`,
|
||||
cheats_instantResourceExtractorDrones: `Sofortige Ressourcen-Extraktor-Drohnen`,
|
||||
cheats_noResourceExtractorDronesDamage: `Kein Schaden für Ressourcen-Extraktor-Drohnen`,
|
||||
@ -262,49 +263,49 @@ dict = {
|
||||
cheats_changeSupportedSyndicate: `Unterstütztes Syndikat`,
|
||||
cheats_changeButton: `Ändern`,
|
||||
cheats_markAllAsRead: `Posteingang als gelesen markieren`,
|
||||
cheats_finishInvasionsInOneMission: `[UNTRANSLATED] Finish Invasions in One Mission`,
|
||||
cheats_nemesisHenchmenKillsMultiplierGrineer: `[UNTRANSLATED] Rage Progess Multiplier (Grineer)`,
|
||||
cheats_nemesisHenchmenKillsMultiplierCorpus: `[UNTRANSLATED] Rage Progess Multiplier (Corpus)`,
|
||||
cheats_nemesisAntivirusGainMultiplier: `[UNTRANSLATED] Antivirus Progress Multiplier`,
|
||||
cheats_nemesisHintProgressMultiplierGrineer: `[UNTRANSLATED] Hint Progress Multiplier (Grineer)`,
|
||||
cheats_nemesisHintProgressMultiplierCorpus: `[UNTRANSLATED] Hint Progress Multiplier (Corpus)`,
|
||||
cheats_nemesisExtraWeapon: `[UNTRANSLATED] Extra Nemesis Weapon / Token On Vanquish (0 to disable)`,
|
||||
cheats_finishInvasionsInOneMission: `Invasionen in einer Mission abschließen`,
|
||||
cheats_nemesisHenchmenKillsMultiplierGrineer: `Wut-Fortschrittsmultiplikator (Grineer)`,
|
||||
cheats_nemesisHenchmenKillsMultiplierCorpus: `Wut-Fortschrittsmultiplikator (Corpus)`,
|
||||
cheats_nemesisAntivirusGainMultiplier: `Antivirus-Fortschrittsmultiplikator`,
|
||||
cheats_nemesisHintProgressMultiplierGrineer: `Hinweis-Fortschrittsmultiplikator (Grineer)`,
|
||||
cheats_nemesisHintProgressMultiplierCorpus: `Hinweis-Fortschrittsmultiplikator (Corpus)`,
|
||||
cheats_nemesisExtraWeapon: `Zusätzliche Nemesis-Waffe/-Symbol bei Besiegung (0 zum deaktivieren)`,
|
||||
|
||||
worldState: `Weltstatus`,
|
||||
worldState_creditBoost: `Event Booster: Credit`,
|
||||
worldState_affinityBoost: `Event Booster: Erfahrung`,
|
||||
worldState_resourceBoost: `Event Booster: Ressourcen`,
|
||||
worldState_tennoLiveRelay: `TennoLive Relais`,
|
||||
worldState_baroTennoConRelay: `Baros TennoCon Relais`,
|
||||
worldState_baroTennoConRelay: `Baros TennoCon-Relais`,
|
||||
worldState_starDays: `Sternen-Tage`,
|
||||
worldState_galleonOfGhouls: `Galeone der Ghule`,
|
||||
worldState_anniversary: `[UNTRANSLATED] Warframe Anniversary`,
|
||||
worldState_useAnniversaryTagForOldGoals: `[UNTRANSLATED] Use <code>Tag</code> from Warframe Anniversary for old Events`,
|
||||
worldState_anniversary: `Warframe Jubiläum`,
|
||||
worldState_useAnniversaryTagForOldGoals: `Verwende <code>Tag</code> vom Warframe Jubiläum für alte Events`,
|
||||
worldState_ghoulEmergence: `Ghul Ausrottung`,
|
||||
worldState_plagueStar: `Plagenstern`,
|
||||
worldState_dogDays: `Hitzefrei`,
|
||||
worldState_dogDaysRewards: `[UNTRANSLATED] Dog Days Rewards`,
|
||||
worldState_wolfHunt: `Wolfsjagd (2025)`,
|
||||
worldState_dogDaysRewards: `Hitzefrei-Belohnungen`,
|
||||
worldState_wolfHunt: `Wolfsjagd`,
|
||||
worldState_voidCorruption: `Void-Korruption (|VAL|)`,
|
||||
worldState_orphixVenom: `Orphix Gift`,
|
||||
worldState_longShadow: `Lange Schatten`,
|
||||
worldState_hallowedFlame: `Geweihte Flamme`,
|
||||
worldState_hallowedNightmares: `Geweihte Albträume`,
|
||||
worldState_hallowedNightmaresRewards: `[UNTRANSLATED] Hallowed Nightmares Rewards`,
|
||||
worldState_naberusNights: `[UNTRANSLATED] Nights of Naberus`,
|
||||
worldState_hallowedNightmaresRewards: `Geweihte Albträume-Belohnungen`,
|
||||
worldState_naberusNights: `Naberus Nacht`,
|
||||
worldState_proxyRebellion: `Proxy-Rebellion`,
|
||||
worldState_proxyRebellionRewards: `[UNTRANSLATED] Proxy Rebellion Rewards`,
|
||||
worldState_proxyRebellionRewards: `Proxy-Rebellion-Belohnungen`,
|
||||
worldState_bellyOfTheBeast: `Das Innere der Bestie`,
|
||||
worldState_bellyOfTheBeastProgressOverride: `[UNTRANSLATED] Belly of the Beast Progress`,
|
||||
worldState_bellyOfTheBeastProgressOverride: `Das Innere der Bestie-Fortschritt`,
|
||||
worldState_eightClaw: `Acht Klauen`,
|
||||
worldState_eightClawProgressOverride: `[UNTRANSLATED] Eight Claw Progress`,
|
||||
worldState_eightClawProgressOverride: `Acht Klauen-Fortschritt`,
|
||||
worldState_thermiaFractures: `Thermische Risse`,
|
||||
worldState_thermiaFracturesProgressOverride: `[UNTRANSLATED] Thermia Fractures Progress`,
|
||||
worldState_qtccAlerts: `[UNTRANSLATED] Quest to Conquer Cancer Alerts`,
|
||||
worldState_from_year: `[UNTRANSLATED] from |VAL|`,
|
||||
worldState_pre_year: `[UNTRANSLATED] pre |VAL|`,
|
||||
worldState_week: `[UNTRANSLATED] Week |VAL|`,
|
||||
worldState_incompatibleWith: `[UNTRANSLATED] Incompatible with:`,
|
||||
worldState_thermiaFracturesProgressOverride: `Thermische Risse-Fortschritt`,
|
||||
worldState_qtccAlerts: `Quest zum Kampf gegen Krebs-Alarmierungen`,
|
||||
worldState_from_year: `Von |VAL|`,
|
||||
worldState_pre_year: `Vor |VAL|`,
|
||||
worldState_week: `Woche |VAL|`,
|
||||
worldState_incompatibleWith: `Inkompatibel mit:`,
|
||||
enabled: `Aktiviert`,
|
||||
disabled: `Deaktiviert`,
|
||||
worldState_we1: `Wochenende 1`,
|
||||
@ -348,7 +349,7 @@ dict = {
|
||||
worldState_varziaFullyStocked: `Varzia hat volles Inventar`,
|
||||
worldState_varziaOverride: `Varzia-Angebotsüberschreibung`,
|
||||
|
||||
import_importNote: `[UNTRANSLATED] You can provide a full or partial <code>inventory.php</code> or <code>getShip.php</code> response (client representation) here.`,
|
||||
import_importNote: `Du kannst hier eine vollständige oder teilweise <code>inventory.php</code> oder <code>getShip.php</code> Antwort (Client-Darstellung) einfügen.`,
|
||||
import_importNote2: `Alle Felder, die vom Importer unterstützt werden, <b>werden in deinem Account überschrieben</b>.`,
|
||||
import_submit: `Absenden`,
|
||||
import_samples: `Beispiele:`,
|
||||
@ -416,9 +417,11 @@ dict = {
|
||||
theme_dark: `Dunkles Design`,
|
||||
theme_light: `Helles Design`,
|
||||
|
||||
guildView_cheats: `[UNTRANSLATED] Clan Cheats`,
|
||||
guildView_cheats: `Clan-Cheats`,
|
||||
guildView_techProjects: `Forschung`,
|
||||
guildView_vaultDecoRecipes: `[UNTRANSLATED] Dojo Deco Recipes`,
|
||||
guildView_vaultDecoRecipes: `Dojo-Deko-Baupläne`,
|
||||
guildView_vaultMiscItems: `Ressourcen im Tresor`,
|
||||
guildView_vaultShipDecorations: `Dekorationen im Tresor`,
|
||||
guildView_alliance: `Allianz`,
|
||||
guildView_members: `Mitglieder`,
|
||||
guildView_pending: `Ausstehend`,
|
||||
@ -438,11 +441,12 @@ dict = {
|
||||
guildView_rank_soldier: `Soldat`,
|
||||
guildView_rank_utility: `Versorger`,
|
||||
guildView_rank_warlord: `Kriegsherr`,
|
||||
guildView_currency_owned: `[UNTRANSLATED] |COUNT| in Vault.`,
|
||||
guildView_bulkAddTechProjects: `[UNTRANSLATED] Add Missing Research`,
|
||||
guildView_bulkAddVaultDecoRecipes: `[UNTRANSLATED] Add Missing Dojo Deco Recipes`,
|
||||
guildView_bulkFundTechProjects: `[UNTRANSLATED] Fund All Research`,
|
||||
guildView_bulkCompleteTechProjects: `[UNTRANSLATED] Complete All Research`,
|
||||
guildView_currency_owned: `|COUNT| im Tresor.`,
|
||||
guildView_bulkAddTechProjects: `Fehlende Forschungen hinzufügen`,
|
||||
guildView_bulkAddVaultDecoRecipes: `Fehlende Dojo-Deko-Baupläne hinzufügen`,
|
||||
guildView_bulkAddVaultShipDecorations: `Fehlende Dekorationen im Tresor hinzufügen`,
|
||||
guildView_bulkFundTechProjects: `Alle Forschungen spenden`,
|
||||
guildView_bulkCompleteTechProjects: `Alle Forschungen abschließen`,
|
||||
guildView_promote: `Befördern`,
|
||||
guildView_demote: `Degradieren`,
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ dict = {
|
||||
code_remove: `Remove`,
|
||||
code_addItemsConfirm: `Are you sure you want to add |COUNT| items to your account?`,
|
||||
code_addTechProjectsConfirm: `Are you sure you want to add |COUNT| research to your clan?`,
|
||||
code_addDecoRecipesConfirm: `Are you sure you want to add |COUNT| deco recipes to your clan?`,
|
||||
code_addVaultItemsConfirm: `Are you sure you want to add |COUNT| items to your clan vault?`,
|
||||
code_succRankUp: `Successfully ranked up.`,
|
||||
code_noEquipmentToRankUp: `No equipment to rank up.`,
|
||||
code_succAdded: `Successfully added.`,
|
||||
@ -47,7 +47,7 @@ dict = {
|
||||
code_unlockLevelCap: `Unlock level cap`,
|
||||
code_count: `Count`,
|
||||
code_focusAllUnlocked: `All focus schools are already unlocked.`,
|
||||
code_focusUnlocked: `Unlocked |COUNT| new focus schools! An inventory update will be needed for the changes to be reflected in-game. Visiting the navigation should be the easiest way to trigger that.`,
|
||||
code_focusUnlocked: `Unlocked |COUNT| new focus schools! An inventory update will be needed for the changes to be reflected in-game.`,
|
||||
code_addModsConfirm: `Are you sure you want to add |COUNT| mods to your account?`,
|
||||
code_succImport: `Successfully imported.`,
|
||||
code_succRelog: `Done. Please note that you'll need to relog to see a difference in-game.`,
|
||||
@ -134,6 +134,7 @@ dict = {
|
||||
inventory_bulkRankUpSentinelWeapons: `Max Rank All Sentinel Weapons`,
|
||||
inventory_bulkRankUpEvolutionProgress: `Max Rank All Incarnon Evolution Progress`,
|
||||
inventory_maxPlexus: `Max Rank Plexus`,
|
||||
inventory_removeIsNew: `Remove New Equipment Exclamation Icon`,
|
||||
|
||||
quests_list: `Quests`,
|
||||
quests_completeAll: `Complete All Quests`,
|
||||
@ -283,7 +284,7 @@ dict = {
|
||||
worldState_plagueStar: `Plague Star`,
|
||||
worldState_dogDays: `Dog Days`,
|
||||
worldState_dogDaysRewards: `Dog Days Rewards`,
|
||||
worldState_wolfHunt: `Wolf Hunt (2025)`,
|
||||
worldState_wolfHunt: `Wolf Hunt`,
|
||||
worldState_voidCorruption: `Void Corruption (|VAL|)`,
|
||||
worldState_orphixVenom: `Orphix Venom`,
|
||||
worldState_longShadow: `Long Shadow`,
|
||||
@ -300,8 +301,8 @@ dict = {
|
||||
worldState_thermiaFractures: `Thermia Fractures`,
|
||||
worldState_thermiaFracturesProgressOverride: `Thermia Fractures Progress`,
|
||||
worldState_qtccAlerts: `Quest to Conquer Cancer Alerts`,
|
||||
worldState_from_year: `from |VAL|`,
|
||||
worldState_pre_year: `pre |VAL|`,
|
||||
worldState_from_year: `From |VAL|`,
|
||||
worldState_pre_year: `Pre-|VAL|`,
|
||||
worldState_week: `Week |VAL|`,
|
||||
worldState_incompatibleWith: `Incompatible with:`,
|
||||
enabled: `Enabled`,
|
||||
@ -418,6 +419,8 @@ dict = {
|
||||
guildView_cheats: `Clan Cheats`,
|
||||
guildView_techProjects: `Research`,
|
||||
guildView_vaultDecoRecipes: `Dojo Deco Recipes`,
|
||||
guildView_vaultMiscItems: `Resources in Vault`,
|
||||
guildView_vaultShipDecorations: `Decorations in Vault`,
|
||||
guildView_alliance: `Alliance`,
|
||||
guildView_members: `Members`,
|
||||
guildView_pending: `Pending`,
|
||||
@ -440,6 +443,7 @@ dict = {
|
||||
guildView_currency_owned: `|COUNT| in Vault.`,
|
||||
guildView_bulkAddTechProjects: `Add Missing Research`,
|
||||
guildView_bulkAddVaultDecoRecipes: `Add Missing Dojo Deco Recipes`,
|
||||
guildView_bulkAddVaultShipDecorations: `Add Missing Decorations in Vault`,
|
||||
guildView_bulkFundTechProjects: `Fund All Research`,
|
||||
guildView_bulkCompleteTechProjects: `Complete All Research`,
|
||||
guildView_promote: `Promote`,
|
||||
|
||||
@ -33,7 +33,7 @@ dict = {
|
||||
code_remove: `Quitar`,
|
||||
code_addItemsConfirm: `¿Estás seguro de que deseas agregar |COUNT| objetos a tu cuenta?`,
|
||||
code_addTechProjectsConfirm: `¿Estás seguro de que quieres añadir |COUNT| proyectos de investigación a tu clan?`,
|
||||
code_addDecoRecipesConfirm: `¿Estás seguro de que quieres añadir |COUNT| planos de decoración a tu clan?`,
|
||||
code_addVaultItemsConfirm: `[UNTRANSLATED] Are you sure you want to add |COUNT| items to your clan vault?`,
|
||||
code_succRankUp: `Ascenso exitoso.`,
|
||||
code_noEquipmentToRankUp: `No hay equipo para ascender.`,
|
||||
code_succAdded: `Agregado exitosamente.`,
|
||||
@ -48,7 +48,7 @@ dict = {
|
||||
code_unlockLevelCap: `Desbloquear level cap`,
|
||||
code_count: `Cantidad`,
|
||||
code_focusAllUnlocked: `Todas las escuelas de enfoque ya están desbloqueadas.`,
|
||||
code_focusUnlocked: `¡Desbloqueadas |COUNT| nuevas escuelas de enfoque! Se necesita una actualización del inventario para reflejar los cambios en el juego. Visitar la navegación debería ser la forma más sencilla de activarlo.`,
|
||||
code_focusUnlocked: `¡Desbloqueadas |COUNT| nuevas escuelas de enfoque! Se necesita una actualización del inventario para reflejar los cambios en el juego.`,
|
||||
code_addModsConfirm: `¿Estás seguro de que deseas agregar |COUNT| modificadores a tu cuenta?`,
|
||||
code_succImport: `Importación exitosa.`,
|
||||
code_succRelog: `Hecho. Ten en cuenta que deberás volver a iniciar sesión para ver los cambios en el juego.`,
|
||||
@ -135,6 +135,7 @@ dict = {
|
||||
inventory_bulkRankUpSentinelWeapons: `Maximizar rango de todas las armas de centinela`,
|
||||
inventory_bulkRankUpEvolutionProgress: `Maximizar todo el progreso de evolución Incarnon`,
|
||||
inventory_maxPlexus: `Rango máximo de Plexus`,
|
||||
inventory_removeIsNew: `[UNTRANSLATED] Remove New Equipment Exclamation Icon`,
|
||||
|
||||
quests_list: `Misiones`,
|
||||
quests_completeAll: `Completar todas las misiones`,
|
||||
@ -284,7 +285,7 @@ dict = {
|
||||
worldState_plagueStar: `Estrella Infestada`,
|
||||
worldState_dogDays: `Canícula`,
|
||||
worldState_dogDaysRewards: `Recompensas de Canícula`,
|
||||
worldState_wolfHunt: `Cacería del Lobo (2025)`,
|
||||
worldState_wolfHunt: `Cacería del Lobo`,
|
||||
worldState_voidCorruption: `Corrupción del Vacío (|VAL|)`,
|
||||
worldState_orphixVenom: `Veneno de Orphix`,
|
||||
worldState_longShadow: `Sombra Prolongada`,
|
||||
@ -301,8 +302,8 @@ dict = {
|
||||
worldState_thermiaFractures: `Fracturas Thermia`,
|
||||
worldState_thermiaFracturesProgressOverride: `Progreso de Fracturas Thermia`,
|
||||
worldState_qtccAlerts: `[UNTRANSLATED] Quest to Conquer Cancer Alerts`,
|
||||
worldState_from_year: `de |VAL|`,
|
||||
worldState_pre_year: `antes de |VAL|`,
|
||||
worldState_from_year: `De |VAL|`,
|
||||
worldState_pre_year: `Antes de |VAL|`,
|
||||
worldState_week: `Semana |VAL|`,
|
||||
worldState_incompatibleWith: `No compatible con:`,
|
||||
enabled: `Activado`,
|
||||
@ -419,6 +420,8 @@ dict = {
|
||||
guildView_cheats: `Trucos de Clan`,
|
||||
guildView_techProjects: `Investigación`,
|
||||
guildView_vaultDecoRecipes: `Planos de Decoración de Dojo`,
|
||||
guildView_vaultMiscItems: `[UNTRANSLATED] Resources in Vault`,
|
||||
guildView_vaultShipDecorations: `[UNTRANSLATED] Decorations in Vault`,
|
||||
guildView_alliance: `Alianza`,
|
||||
guildView_members: `Miembros`,
|
||||
guildView_pending: `Pendiente`,
|
||||
@ -441,6 +444,7 @@ dict = {
|
||||
guildView_currency_owned: `|COUNT| en la Bóveda.`,
|
||||
guildView_bulkAddTechProjects: `Añadir proyectos de Investigación Faltantes`,
|
||||
guildView_bulkAddVaultDecoRecipes: `Añadir planos de Decoración de Dojo Faltantes`,
|
||||
guildView_bulkAddVaultShipDecorations: `[UNTRANSLATED] Add Missing Decorations in Vault`,
|
||||
guildView_bulkFundTechProjects: `Financiar toda la Investigación`,
|
||||
guildView_bulkCompleteTechProjects: `Completar toda la Investigación`,
|
||||
guildView_promote: `Promover`,
|
||||
|
||||
@ -33,7 +33,7 @@ dict = {
|
||||
code_remove: `Retirer`,
|
||||
code_addItemsConfirm: `Ajouter |COUNT| items à l'inventaire ?`,
|
||||
code_addTechProjectsConfirm: `Ajouter |COUNT| recherches au clan ?`,
|
||||
code_addDecoRecipesConfirm: `Ajouter |COUNT| décorations au clan ?`,
|
||||
code_addVaultItemsConfirm: `Ajouter |COUNT| objets au coffre de clan ?`,
|
||||
code_succRankUp: `Montée de niveau effectuée.`,
|
||||
code_noEquipmentToRankUp: `Aucun équipement à monter de niveau.`,
|
||||
code_succAdded: `Ajouté.`,
|
||||
@ -45,7 +45,7 @@ dict = {
|
||||
code_rank: `Rang`,
|
||||
code_rankUp: `Monter de rang`,
|
||||
code_rankDown: `Baisser de rang`,
|
||||
code_unlockLevelCap: `[UNTRANSLATED] Unlock level cap`,
|
||||
code_unlockLevelCap: `Débloquer le level cap (9999)`,
|
||||
code_count: `Quantité`,
|
||||
code_focusAllUnlocked: `Les écoles de Focus sont déjà déverrouillées.`,
|
||||
code_focusUnlocked: `|COUNT| écoles de Focus déverrouillées ! Synchronisation de l'inventaire nécessaire.`,
|
||||
@ -65,22 +65,22 @@ dict = {
|
||||
code_completed: `Complétée`,
|
||||
code_active: `Active`,
|
||||
code_pigment: `Pigment`,
|
||||
code_controller: `[UNTRANSLATED] Controller cursor`,
|
||||
code_mouseLine: `[UNTRANSLATED] Line cursor`,
|
||||
code_mouse: `[UNTRANSLATED] Cursor`,
|
||||
code_controller: `Curseur manette`,
|
||||
code_mouseLine: `Curseur linéaire`,
|
||||
code_mouse: `Curseur`,
|
||||
code_itemColorPalette: `Palette de couleurs |ITEM|`,
|
||||
code_mature: `Maturer pour le combat`,
|
||||
code_unmature: `Régrésser l'âge génétique`,
|
||||
code_fund: `Financer`,
|
||||
code_funded: `Complété`,
|
||||
code_replays: `[UNTRANSLATED] Replays`,
|
||||
code_replays: `Rejouée`,
|
||||
code_stalker: `Stalker`,
|
||||
code_cutName: `[UNTRANSLATED] Cut |INDEX|`,
|
||||
code_cutName: `Coupe |INDEX|`,
|
||||
code_drifterBeardName: `Barbe du Voyageur |INDEX|`,
|
||||
code_drifterFaceName: `Visage du Voyageur |INDEX|`,
|
||||
code_operatorFaceName: `Visage de l'Opérateur |INDEX|`,
|
||||
code_succChange: `Changement effectué.`,
|
||||
code_requiredInvigorationUpgrade: `[UNTRANSLATED] You must select both an offensive & utility upgrade.`,
|
||||
code_requiredInvigorationUpgrade: `Invigoration offensive et défensive requises.`,
|
||||
login_description: `Connexion avec les informations de connexion OpenWF.`,
|
||||
login_emailLabel: `Email`,
|
||||
login_passwordLabel: `Mot de passe`,
|
||||
@ -114,7 +114,7 @@ dict = {
|
||||
inventory_kubrowPets: `Bêtes`,
|
||||
inventory_evolutionProgress: `Progrès de l'évolution Incarnon`,
|
||||
inventory_boosters: `Boosters`,
|
||||
inventory_flavourItems: `[UNTRANSLATED] <abbr title="Animation Sets, Glyphs, Palettes, etc.">Flavour Items</abbr>`,
|
||||
inventory_flavourItems: `<abbr title="Animation Sets, Glyphs, Palettes, etc.">Collectables</abbr>`,
|
||||
inventory_shipDecorations: `Décorations du vaisseau`,
|
||||
inventory_weaponSkins: `Aspects`,
|
||||
inventory_bulkAddSuits: `Ajouter les Warframes manquantes`,
|
||||
@ -123,10 +123,10 @@ dict = {
|
||||
inventory_bulkAddSpaceWeapons: `Ajouter les armes d'Archwing manquantes`,
|
||||
inventory_bulkAddSentinels: `Ajouter les Sentinelles manquantes`,
|
||||
inventory_bulkAddSentinelWeapons: `Ajouter les armes de Sentinelles manquantes`,
|
||||
inventory_bulkAddFlavourItems: `[UNTRANSLATED] Add Missing Flavour Items`,
|
||||
inventory_bulkAddShipDecorations: `[UNTRANSLATED] Add Missing Ship Decorations`,
|
||||
inventory_bulkAddFlavourItems: `Ajouter les collectables manquants ?`,
|
||||
inventory_bulkAddShipDecorations: `Ajouter les décorations de vaisseau manquantes`,
|
||||
inventory_bulkAddEvolutionProgress: `Ajouter les évolutions Incarnon manquantes`,
|
||||
inventory_bulkAddWeaponSkins: `[UNTRANSLATED] Add Missing Skins`,
|
||||
inventory_bulkAddWeaponSkins: `Ajouter les skins manquants`,
|
||||
inventory_bulkRankUpSuits: `Toutes les Warframes au rang max`,
|
||||
inventory_bulkRankUpWeapons: `Toutes les armes au rang max`,
|
||||
inventory_bulkRankUpSpaceSuits: `Tous les Archwings au rang max`,
|
||||
@ -135,6 +135,7 @@ dict = {
|
||||
inventory_bulkRankUpSentinelWeapons: `Toutes les armes de Sentinelles au rang max`,
|
||||
inventory_bulkRankUpEvolutionProgress: `Toutes les évolutions Incarnon au rang max`,
|
||||
inventory_maxPlexus: `Plexus au rang max`,
|
||||
inventory_removeIsNew: `[UNTRANSLATED] Remove New Equipment Exclamation Icon`,
|
||||
|
||||
quests_list: `Quêtes`,
|
||||
quests_completeAll: `Compléter toutes les quêtes`,
|
||||
@ -179,8 +180,8 @@ dict = {
|
||||
invigorations_utility_EnergyRegen: `+2 d'énergie régénérés/s`,
|
||||
|
||||
detailedView_invigorationOffensiveLabel: `Amélioration offensive`,
|
||||
detailedView_invigorationUtilityLabel: `[UNTRANSLATED] Utility Upgrade`,
|
||||
detailedView_invigorationExpiryLabel: `[UNTRANSLATED] Invigoration Expiry (optional)`,
|
||||
detailedView_invigorationUtilityLabel: `Amélioration défensive`,
|
||||
detailedView_invigorationExpiryLabel: `Expiration de l'invigoration (optionnel)`,
|
||||
|
||||
abilityOverride_label: `Remplacement de pouvoir`,
|
||||
abilityOverride_onSlot: `Sur l'emplacement`,
|
||||
@ -263,12 +264,12 @@ dict = {
|
||||
cheats_changeButton: `Changer`,
|
||||
cheats_markAllAsRead: `Marquer la boîte de réception comme lue`,
|
||||
cheats_finishInvasionsInOneMission: `Compléter les invasions en une mission.`,
|
||||
cheats_nemesisHenchmenKillsMultiplierGrineer: `[UNTRANSLATED] Rage Progess Multiplier (Grineer)`,
|
||||
cheats_nemesisHenchmenKillsMultiplierCorpus: `[UNTRANSLATED] Rage Progess Multiplier (Corpus)`,
|
||||
cheats_nemesisAntivirusGainMultiplier: `[UNTRANSLATED] Antivirus Progress Multiplier`,
|
||||
cheats_nemesisHintProgressMultiplierGrineer: `[UNTRANSLATED] Hint Progress Multiplier (Grineer)`,
|
||||
cheats_nemesisHintProgressMultiplierCorpus: `[UNTRANSLATED] Hint Progress Multiplier (Corpus)`,
|
||||
cheats_nemesisExtraWeapon: `[UNTRANSLATED] Extra Nemesis Weapon / Token On Vanquish (0 to disable)`,
|
||||
cheats_nemesisHenchmenKillsMultiplierGrineer: `Multiplicateur de rage (Grineer)`,
|
||||
cheats_nemesisHenchmenKillsMultiplierCorpus: `Multiplicateur de rage (Corpus)`,
|
||||
cheats_nemesisAntivirusGainMultiplier: `Multiplicateur de l'Antivirus`,
|
||||
cheats_nemesisHintProgressMultiplierGrineer: `Multiplicateur d'indices (Grineer)`,
|
||||
cheats_nemesisHintProgressMultiplierCorpus: `Multiplicateur d'indices (Corpus)`,
|
||||
cheats_nemesisExtraWeapon: `Arme de Nemesis/jeton supplémentaire sur exécution (0 pour désactiver)`,
|
||||
|
||||
worldState: `Carte Solaire`,
|
||||
worldState_creditBoost: `Booster de Crédit`,
|
||||
@ -284,14 +285,14 @@ dict = {
|
||||
worldState_plagueStar: `Fléau Céleste`,
|
||||
worldState_dogDays: `Bataille d'Eau`,
|
||||
worldState_dogDaysRewards: `Récompenses de la Bataille d'Eau`,
|
||||
worldState_wolfHunt: `Chasse au Loup (2025)`,
|
||||
worldState_wolfHunt: `Chasse au Loup`,
|
||||
worldState_voidCorruption: `Corruption du Néant (|VAL|)`,
|
||||
worldState_orphixVenom: `Venin Orphix`,
|
||||
worldState_longShadow: `La Propagation des Ombres`,
|
||||
worldState_hallowedFlame: `Flamme Hantée`,
|
||||
worldState_hallowedNightmares: `Cauchemars Hantés`,
|
||||
worldState_hallowedNightmaresRewards: `Récompenses Flamme Hantée Cauchemar`,
|
||||
worldState_naberusNights: `[UNTRANSLATED] Nights of Naberus`,
|
||||
worldState_naberusNights: `Les Nuits de Naberus`,
|
||||
worldState_proxyRebellion: `Rébellion Proxy`,
|
||||
worldState_proxyRebellionRewards: `Récompenses Rébellion Proxy`,
|
||||
worldState_bellyOfTheBeast: `Ventre de la Bête`,
|
||||
@ -300,9 +301,9 @@ dict = {
|
||||
worldState_eightClawProgressOverride: `Progrès de la Huitième Griffe`,
|
||||
worldState_thermiaFractures: `Crevasses Thermia`,
|
||||
worldState_thermiaFracturesProgressOverride: `Progrès des Fractures Thermia`,
|
||||
worldState_qtccAlerts: `[UNTRANSLATED] Quest to Conquer Cancer Alerts`,
|
||||
worldState_from_year: `de |VAL|`,
|
||||
worldState_pre_year: `pre-|VAL|`,
|
||||
worldState_qtccAlerts: `Alertes Quête pour Vaincre le Cancer`,
|
||||
worldState_from_year: `De |VAL|`,
|
||||
worldState_pre_year: `Pre-|VAL|`,
|
||||
worldState_week: `Semaine |VAL|`,
|
||||
worldState_incompatibleWith: `Incompatible avec :`,
|
||||
enabled: `Activé`,
|
||||
@ -416,9 +417,11 @@ dict = {
|
||||
theme_dark: `Thème sombre`,
|
||||
theme_light: `Thème clair`,
|
||||
|
||||
guildView_cheats: `[UNTRANSLATED] Clan Cheats`,
|
||||
guildView_cheats: `Clan`,
|
||||
guildView_techProjects: `Recherche`,
|
||||
guildView_vaultDecoRecipes: `Schémas de décorations de dojo`,
|
||||
guildView_vaultMiscItems: `Ressources dans le coffre`,
|
||||
guildView_vaultShipDecorations: `Décorations dans le coffre`,
|
||||
guildView_alliance: `Alliance`,
|
||||
guildView_members: `Members`,
|
||||
guildView_pending: `En Attente`,
|
||||
@ -441,6 +444,7 @@ dict = {
|
||||
guildView_currency_owned: `|COUNT| dans le coffre.`,
|
||||
guildView_bulkAddTechProjects: `Ajouter les recherches manquantes`,
|
||||
guildView_bulkAddVaultDecoRecipes: `Ajouter les schémas de décorations de dojo manquantes`,
|
||||
guildView_bulkAddVaultShipDecorations: `Ajouter dans le coffre les décorations manquantes`,
|
||||
guildView_bulkFundTechProjects: `Financer toutes les recherches`,
|
||||
guildView_bulkCompleteTechProjects: `Compléter toutes les recherches`,
|
||||
guildView_promote: `Promouvoir`,
|
||||
|
||||
@ -33,7 +33,7 @@ dict = {
|
||||
code_remove: `Удалить`,
|
||||
code_addItemsConfirm: `Вы уверены, что хотите добавить |COUNT| предметов на ваш аккаунт?`,
|
||||
code_addTechProjectsConfirm: `Вы уверены, что хотите добавить |COUNT| исследований в свой клан?`,
|
||||
code_addDecoRecipesConfirm: `Вы уверены, что хотите добавить |COUNT| рецептов декораций в свой клан?`,
|
||||
code_addVaultItemsConfirm: `Вы уверены, что хотите добавить |COUNT| предметов в хранилище своего клана?`,
|
||||
code_succRankUp: `Ранг успешно повышен.`,
|
||||
code_noEquipmentToRankUp: `Нет снаряжения для повышения ранга.`,
|
||||
code_succAdded: `Успешно добавлено.`,
|
||||
@ -48,7 +48,7 @@ dict = {
|
||||
code_unlockLevelCap: `Разблокировать ограничение уровня`,
|
||||
code_count: `Количество`,
|
||||
code_focusAllUnlocked: `Все школы Фокуса уже разблокированы.`,
|
||||
code_focusUnlocked: `Разблокировано |COUNT| новых школ Фокуса! Для отображения изменений в игре потребуется обновление инвентаря. Посещение навигации — самый простой способ этого добиться.`,
|
||||
code_focusUnlocked: `[UNTRANSLATED] Unlocked |COUNT| new focus schools! An inventory update will be needed for the changes to be reflected in-game.`,
|
||||
code_addModsConfirm: `Вы уверены, что хотите добавить |COUNT| модов на ваш аккаунт?`,
|
||||
code_succImport: `Успешно импортировано.`,
|
||||
code_succRelog: `Готово. Обратите внимание, что вам нужно будет перезайти, чтобы увидеть изменения в игре.`,
|
||||
@ -135,6 +135,7 @@ dict = {
|
||||
inventory_bulkRankUpSentinelWeapons: `Макс. ранг всего оружия Стражей`,
|
||||
inventory_bulkRankUpEvolutionProgress: `Макс. ранг всех эволюций Инкарнонов`,
|
||||
inventory_maxPlexus: `Макс. ранг Плексуса`,
|
||||
inventory_removeIsNew: `Удалить значок восклицательного знака нового снаряжения`,
|
||||
|
||||
quests_list: `Квесты`,
|
||||
quests_completeAll: `Завершить все квесты`,
|
||||
@ -284,7 +285,7 @@ dict = {
|
||||
worldState_plagueStar: `Чумная звезда`,
|
||||
worldState_dogDays: `Знойные дни`,
|
||||
worldState_dogDaysRewards: `Награды Знойных дней`,
|
||||
worldState_wolfHunt: `Волчья Охота (2025)`,
|
||||
worldState_wolfHunt: `Волчья Охота`,
|
||||
worldState_voidCorruption: `Искажение Бездны (|VAL|)`,
|
||||
worldState_orphixVenom: `Яд Орфикса`,
|
||||
worldState_longShadow: `Длинная Тень`,
|
||||
@ -301,8 +302,8 @@ dict = {
|
||||
worldState_thermiaFractures: `Разломы Термии`,
|
||||
worldState_thermiaFracturesProgressOverride: `Прогресс Разломов Термии`,
|
||||
worldState_qtccAlerts: `Тревоги Quest to Conquer Cancer`,
|
||||
worldState_from_year: `из |VAL|`,
|
||||
worldState_pre_year: `до |VAL|`,
|
||||
worldState_from_year: `Из |VAL|`,
|
||||
worldState_pre_year: `До |VAL|`,
|
||||
worldState_week: `Неделя |VAL|`,
|
||||
worldState_incompatibleWith: `Несовместимо с:`,
|
||||
enabled: `Включено`,
|
||||
@ -419,6 +420,8 @@ dict = {
|
||||
guildView_cheats: `Читы Клана`,
|
||||
guildView_techProjects: `Исследовения`,
|
||||
guildView_vaultDecoRecipes: `Рецепты декораций Додзё`,
|
||||
guildView_vaultMiscItems: `Ресурсы в Хранилище`,
|
||||
guildView_vaultShipDecorations: `Укращения в Хранилище`,
|
||||
guildView_alliance: `Альянс`,
|
||||
guildView_members: `Товарищи`,
|
||||
guildView_pending: `Ожидание`,
|
||||
@ -441,6 +444,7 @@ dict = {
|
||||
guildView_currency_owned: `В хранилище |COUNT|.`,
|
||||
guildView_bulkAddTechProjects: `Добавить отсутствующие исследования`,
|
||||
guildView_bulkAddVaultDecoRecipes: `Добавить отсутствующие рецепты декораций Дoдзё`,
|
||||
guildView_bulkAddVaultShipDecorations: `Добавить отсутствующие укращения в Хранилище`,
|
||||
guildView_bulkFundTechProjects: `Профинансировать все исследования`,
|
||||
guildView_bulkCompleteTechProjects: `Завершить все исследования`,
|
||||
guildView_promote: `Повысить`,
|
||||
|
||||
@ -33,7 +33,7 @@ dict = {
|
||||
code_remove: `Видалити`,
|
||||
code_addItemsConfirm: `Ви впевнені, що хочете додати |COUNT| предметів на ваш обліковий запис?`,
|
||||
code_addTechProjectsConfirm: `Ви впевнені, що хочете додати |COUNT| досліджень до свого клану?`,
|
||||
code_addDecoRecipesConfirm: `Ви впевнені, що хочете додати |COUNT| рецептів оздоблень до свого клану?`,
|
||||
code_addVaultItemsConfirm: `[UNTRANSLATED] Are you sure you want to add |COUNT| items to your clan vault?`,
|
||||
code_succRankUp: `Рівень успішно підвищено`,
|
||||
code_noEquipmentToRankUp: `Немає спорядження для підвищення рівня.`,
|
||||
code_succAdded: `Успішно додано.`,
|
||||
@ -48,7 +48,7 @@ dict = {
|
||||
code_unlockLevelCap: `Розблокувати обмеження рівня`,
|
||||
code_count: `Кількість`,
|
||||
code_focusAllUnlocked: `Всі школи Фокусу вже розблоковані.`,
|
||||
code_focusUnlocked: `Розблоковано |COUNT| нових шкіл Фокусу! Для відображення змін в грі знадобиться оновлення спорядження. Відвідування навігації — найпростіший спосіб цього досягти.`,
|
||||
code_focusUnlocked: `Розблоковано |COUNT| нових шкіл Фокусу! Для відображення змін в грі знадобиться оновлення спорядження.`,
|
||||
code_addModsConfirm: `Ви впевнені, що хочете додати |COUNT| модифікаторів на ваш обліковий запис?`,
|
||||
code_succImport: `Успішно імпортовано.`,
|
||||
code_succRelog: `Готово. Зверніть увагу, що вам потрібно буде перезайти, щоб побачити зміни в грі.`,
|
||||
@ -135,6 +135,7 @@ dict = {
|
||||
inventory_bulkRankUpSentinelWeapons: `Макс. рівень всієї зброї Вартових`,
|
||||
inventory_bulkRankUpEvolutionProgress: `Макс. рівень всіх еволюцій Інкарнонів`,
|
||||
inventory_maxPlexus: `Макс. рівень Плексу`,
|
||||
inventory_removeIsNew: `[UNTRANSLATED] Remove New Equipment Exclamation Icon`,
|
||||
|
||||
quests_list: `Пригоди`,
|
||||
quests_completeAll: `Закінчити всі пригоди`,
|
||||
@ -284,7 +285,7 @@ dict = {
|
||||
worldState_plagueStar: `Морова зірка`,
|
||||
worldState_dogDays: `Спекотні дні`,
|
||||
worldState_dogDaysRewards: `Нагороди Спекотних днів`,
|
||||
worldState_wolfHunt: `Полювання на Вовка (2025)`,
|
||||
worldState_wolfHunt: `Полювання на Вовка`,
|
||||
worldState_voidCorruption: `Викривлення Порожнечі (|VAL|)`,
|
||||
worldState_orphixVenom: `Орфіксова отрута`,
|
||||
worldState_longShadow: `Довга тінь`,
|
||||
@ -301,8 +302,8 @@ dict = {
|
||||
worldState_thermiaFractures: `Розломи термії`,
|
||||
worldState_thermiaFracturesProgressOverride: `Прогрес Розломів термії`,
|
||||
worldState_qtccAlerts: `[UNTRANSLATED] Quest to Conquer Cancer Alerts`,
|
||||
worldState_from_year: `з |VAL|`,
|
||||
worldState_pre_year: `до |VAL|`,
|
||||
worldState_from_year: `З |VAL|`,
|
||||
worldState_pre_year: `До |VAL|`,
|
||||
worldState_week: `Тиждень |VAL|`,
|
||||
worldState_incompatibleWith: `Несумісне з:`,
|
||||
enabled: `Увімкнено`,
|
||||
@ -419,6 +420,8 @@ dict = {
|
||||
guildView_cheats: `Кланові чити`,
|
||||
guildView_techProjects: `Дослідження`,
|
||||
guildView_vaultDecoRecipes: `Рецепти оздоблень Доджьо`,
|
||||
guildView_vaultMiscItems: `[UNTRANSLATED] Resources in Vault`,
|
||||
guildView_vaultShipDecorations: `[UNTRANSLATED] Decorations in Vault`,
|
||||
guildView_alliance: `Альянс`,
|
||||
guildView_members: `Учасники`,
|
||||
guildView_pending: `Очікування`,
|
||||
@ -441,6 +444,7 @@ dict = {
|
||||
guildView_currency_owned: `В сховищі |COUNT|.`,
|
||||
guildView_bulkAddTechProjects: `Додати відсутні дослідження`,
|
||||
guildView_bulkAddVaultDecoRecipes: `Додати відсутні рецепти оздоблень Доджьо`,
|
||||
guildView_bulkAddVaultShipDecorations: `[UNTRANSLATED] Add Missing Decorations in Vault`,
|
||||
guildView_bulkFundTechProjects: `Фінансувати всі дослідження`,
|
||||
guildView_bulkCompleteTechProjects: `Завершити всі дослідження`,
|
||||
guildView_promote: `Підвищити звання`,
|
||||
|
||||
@ -33,7 +33,7 @@ dict = {
|
||||
code_remove: `移除`,
|
||||
code_addItemsConfirm: `确定要向您的账户添加 |COUNT| 件物品吗?`,
|
||||
code_addTechProjectsConfirm: `[UNTRANSLATED] Are you sure you want to add |COUNT| research to your clan?`,
|
||||
code_addDecoRecipesConfirm: `[UNTRANSLATED] Are you sure you want to add |COUNT| deco recipes to your clan?`,
|
||||
code_addVaultItemsConfirm: `[UNTRANSLATED] Are you sure you want to add |COUNT| items to your clan vault?`,
|
||||
code_succRankUp: `等级已提升`,
|
||||
code_noEquipmentToRankUp: `没有可升级的装备`,
|
||||
code_succAdded: `添加成功`,
|
||||
@ -48,7 +48,7 @@ dict = {
|
||||
code_unlockLevelCap: `[UNTRANSLATED] Unlock level cap`,
|
||||
code_count: `数量`,
|
||||
code_focusAllUnlocked: `所有专精学派均已解锁`,
|
||||
code_focusUnlocked: `已解锁 |COUNT| 个新专精学派!需要游戏内仓库更新才能生效,您可以通过访问星图来触发仓库更新.`,
|
||||
code_focusUnlocked: `已解锁 |COUNT| 个新专精学派!需要游戏内仓库更新才能生效.`,
|
||||
code_addModsConfirm: `确定要向您的账户添加 |COUNT| 张MOD吗?`,
|
||||
code_succImport: `导入成功`,
|
||||
code_succRelog: `完成.需要重新登录游戏才能看到变化.`,
|
||||
@ -135,6 +135,7 @@ dict = {
|
||||
inventory_bulkRankUpSentinelWeapons: `所有守护武器升满级`,
|
||||
inventory_bulkRankUpEvolutionProgress: `所有灵化之源进度最大等级`,
|
||||
inventory_maxPlexus: `最大深控等级`,
|
||||
inventory_removeIsNew: `[UNTRANSLATED] Remove New Equipment Exclamation Icon`,
|
||||
|
||||
quests_list: `系列任务`,
|
||||
quests_completeAll: `完成所有任务`,
|
||||
@ -284,7 +285,7 @@ dict = {
|
||||
worldState_plagueStar: `瘟疫之星`,
|
||||
worldState_dogDays: `三伏天`,
|
||||
worldState_dogDaysRewards: `三伏天奖励设置`,
|
||||
worldState_wolfHunt: `恶狼狩猎 (2025)`,
|
||||
worldState_wolfHunt: `恶狼狩猎`,
|
||||
worldState_voidCorruption: `虚空堕落 (|VAL|)`,
|
||||
worldState_orphixVenom: `奥影之毒`,
|
||||
worldState_longShadow: `暗夜长影`,
|
||||
@ -419,6 +420,8 @@ dict = {
|
||||
guildView_cheats: `[UNTRANSLATED] Clan Cheats`,
|
||||
guildView_techProjects: `研究`,
|
||||
guildView_vaultDecoRecipes: `[UNTRANSLATED] Dojo Deco Recipes`,
|
||||
guildView_vaultMiscItems: `[UNTRANSLATED] Resources in Vault`,
|
||||
guildView_vaultShipDecorations: `[UNTRANSLATED] Decorations in Vault`,
|
||||
guildView_alliance: `联盟`,
|
||||
guildView_members: `成员`,
|
||||
guildView_pending: `待处理`,
|
||||
@ -441,6 +444,7 @@ dict = {
|
||||
guildView_currency_owned: `[UNTRANSLATED] |COUNT| in Vault.`,
|
||||
guildView_bulkAddTechProjects: `[UNTRANSLATED] Add Missing Research`,
|
||||
guildView_bulkAddVaultDecoRecipes: `[UNTRANSLATED] Add Missing Dojo Deco Recipes`,
|
||||
guildView_bulkAddVaultShipDecorations: `[UNTRANSLATED] Add Missing Decorations in Vault`,
|
||||
guildView_bulkFundTechProjects: `[UNTRANSLATED] Fund All Research`,
|
||||
guildView_bulkCompleteTechProjects: `[UNTRANSLATED] Complete All Research`,
|
||||
guildView_promote: `升级`,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user