merge upstream

This commit is contained in:
Animan8000 2025-06-20 07:39:01 -07:00
commit e72aca8476
33 changed files with 652 additions and 1333 deletions

View File

@ -4,9 +4,9 @@ on:
branches: branches:
- main - main
jobs: jobs:
docker: docker-amd64:
if: github.repository == 'OpenWF/SpaceNinjaServer' if: github.repository == 'OpenWF/SpaceNinjaServer'
runs-on: ubuntu-latest runs-on: amd64
steps: steps:
- name: Set up Docker buildx - name: Set up Docker buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
@ -18,8 +18,27 @@ jobs:
- name: Build and push - name: Build and push
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
with: with:
platforms: linux/amd64,linux/arm64 platforms: linux/amd64
push: true push: true
tags: | tags: |
openwf/spaceninjaserver:latest openwf/spaceninjaserver:latest
openwf/spaceninjaserver:${{ github.sha }} 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 }}-arm64

View File

@ -1,53 +1,11 @@
FROM node:24-alpine3.21 FROM node:24-alpine3.21
ENV APP_MONGODB_URL=mongodb://mongodb:27017/openWF RUN apk add --no-cache bash jq
ENV APP_MY_ADDRESS=localhost
ENV APP_HTTP_PORT=80
ENV APP_HTTPS_PORT=443
ENV APP_AUTO_CREATE_ACCOUNT=true
ENV APP_SKIP_TUTORIAL=false
ENV APP_SKIP_ALL_DIALOGUE=false
ENV APP_UNLOCK_ALL_SCANS=false
ENV APP_UNLOCK_ALL_MISSIONS=false
ENV APP_INFINITE_CREDITS=false
ENV APP_INFINITE_PLATINUM=false
ENV APP_INFINITE_ENDO=false
ENV APP_INFINITE_REGAL_AYA=false
ENV APP_INFINITE_HELMINTH_MATERIALS=false
ENV APP_CLAIMING_BLUEPRINT_REFUNDS_INGREDIENTS=false
ENV APP_DONT_SUBTRACT_VOIDTRACES=false
ENV APP_DONT_SUBTRACT_CONSUMABLES=false
ENV APP_UNLOCK_ALL_SHIP_FEATURES=false
ENV APP_UNLOCK_ALL_SHIP_DECORATIONS=false
ENV APP_UNLOCK_ALL_FLAVOUR_ITEMS=false
ENV APP_UNLOCK_ALL_SKINS=false
ENV APP_UNLOCK_ALL_CAPTURA_SCENES=false
ENV APP_UNIVERSAL_POLARITY_EVERYWHERE=false
ENV APP_UNLOCK_DOUBLE_CAPACITY_POTATOES_EVERYWHERE=false
ENV APP_UNLOCK_EXILUS_EVERYWHERE=false
ENV APP_UNLOCK_ARCANES_EVERYWHERE=false
ENV APP_NO_DAILY_FOCUS_LIMIT=false
ENV APP_NO_ARGON_CRYSTAL_DECAY=false
ENV APP_NO_MASTERY_RANK_UP_COOLDOWN=false
ENV APP_NO_VENDOR_PURCHASE_LIMITS=true
ENV APP_NO_DEATH_MARKS=false
ENV APP_NO_KIM_COOLDOWNS=false
ENV APP_SYNDICATE_MISSIONS_REPEATABLE=false
ENV APP_INSTANT_FINISH_RIVEN_CHALLENGE=false
ENV APP_INSTANT_RESOURCE_EXTRACTOR_DRONES=false
ENV APP_NO_RESOURCE_EXTRACTOR_DRONES_DAMAGE=false
ENV APP_SKIP_CLAN_KEY_CRAFTING=false
ENV APP_NO_DOJO_ROOM_BUILD_STAGE=false
ENV APP_NO_DECO_BUILD_STAGE=false
ENV APP_FAST_DOJO_ROOM_DESTRUCTION=false
ENV APP_NO_DOJO_RESEARCH_COSTS=false
ENV APP_NO_DOJO_RESEARCH_TIME=false
ENV APP_FAST_CLAN_ASCENSION=false
ENV APP_SPOOF_MASTERY_RANK=-1
RUN apk add --no-cache bash sed wget jq
COPY . /app COPY . /app
WORKDIR /app WORKDIR /app
RUN npm i --omit=dev
RUN npm run build
ENTRYPOINT ["/app/docker-entrypoint.sh"] ENTRYPOINT ["/app/docker-entrypoint.sh"]

View File

@ -16,6 +16,7 @@ SpaceNinjaServer requires a `config.json`. To set it up, you can copy the [confi
- `myIrcAddresses` can be used to point to an IRC server. If not provided, defaults to `[ myAddress ]`. - `myIrcAddresses` can be used to point to an IRC server. If not provided, defaults to `[ myAddress ]`.
- `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.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.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.
- `worldState.nightwaveOverride` will lock the nightwave season, assuming the client is new enough for it. Valid values: - `worldState.nightwaveOverride` will lock the nightwave season, assuming the client is new enough for it. Valid values:
- `RadioLegionIntermission13Syndicate` for Nora's Mix Vol. 9 - `RadioLegionIntermission13Syndicate` for Nora's Mix Vol. 9
- `RadioLegionIntermission12Syndicate` for Nora's Mix Vol. 8 - `RadioLegionIntermission12Syndicate` for Nora's Mix Vol. 8

View File

@ -20,6 +20,10 @@
"infiniteRegalAya": false, "infiniteRegalAya": false,
"infiniteHelminthMaterials": false, "infiniteHelminthMaterials": false,
"claimingBlueprintRefundsIngredients": false, "claimingBlueprintRefundsIngredients": false,
"dontSubtractPurchaseCreditCost": false,
"dontSubtractPurchasePlatinumCost": false,
"dontSubtractPurchaseItemCost": false,
"dontSubtractPurchaseStandingCost": false,
"dontSubtractVoidTraces": false, "dontSubtractVoidTraces": false,
"dontSubtractConsumables": false, "dontSubtractConsumables": false,
"unlockAllShipFeatures": false, "unlockAllShipFeatures": false,
@ -39,6 +43,7 @@
"noDeathMarks": false, "noDeathMarks": false,
"noKimCooldowns": false, "noKimCooldowns": false,
"syndicateMissionsRepeatable": false, "syndicateMissionsRepeatable": false,
"unlockAllProfitTakerStages": false,
"instantFinishRivenChallenge": false, "instantFinishRivenChallenge": false,
"instantResourceExtractorDrones": false, "instantResourceExtractorDrones": false,
"noResourceExtractorDronesDamage": false, "noResourceExtractorDronesDamage": false,
@ -49,6 +54,7 @@
"noDojoResearchCosts": false, "noDojoResearchCosts": false,
"noDojoResearchTime": false, "noDojoResearchTime": false,
"fastClanAscension": false, "fastClanAscension": false,
"missionsCanGiveAllRelics": false,
"spoofMasteryRank": -1, "spoofMasteryRank": -1,
"nightwaveStandingMultiplier": 1, "nightwaveStandingMultiplier": 1,
"worldState": { "worldState": {
@ -58,6 +64,7 @@
"starDays": true, "starDays": true,
"eidolonOverride": "", "eidolonOverride": "",
"vallisOverride": "", "vallisOverride": "",
"duviriOverride": "",
"nightwaveOverride": "", "nightwaveOverride": "",
"circuitGameModes": null "circuitGameModes": null
}, },

View File

@ -1,62 +1,20 @@
services: services:
spaceninjaserver: spaceninjaserver:
# build: . # The image to use. If you have an ARM CPU, replace 'latest' with 'latest-arm64'.
image: openwf/spaceninjaserver:latest image: openwf/spaceninjaserver:latest
environment:
APP_MONGODB_URL: mongodb://openwfagent:spaceninjaserver@mongodb:27017/
# Following environment variables are set to default image values.
# Uncomment to edit.
# APP_MY_ADDRESS: localhost
# APP_HTTP_PORT: 80
# APP_HTTPS_PORT: 443
# APP_AUTO_CREATE_ACCOUNT: true
# APP_SKIP_TUTORIAL: false
# APP_SKIP_ALL_DIALOGUE: false
# APP_UNLOCK_ALL_SCANS: false
# APP_UNLOCK_ALL_MISSIONS: false
# APP_INFINITE_CREDITS: false
# APP_INFINITE_PLATINUM: false
# APP_INFINITE_ENDO: false
# APP_INFINITE_REGAL_AYA: false
# APP_INFINITE_HELMINTH_MATERIALS: false
# APP_CLAIMING_BLUEPRINT_REFUNDS_INGREDIENTS: false
# APP_DONT_SUBTRACT_VOIDTRACES: false
# APP_DONT_SUBTRACT_CONSUMABLES: false
# APP_UNLOCK_ALL_SHIP_FEATURES: false
# APP_UNLOCK_ALL_SHIP_DECORATIONS: false
# APP_UNLOCK_ALL_FLAVOUR_ITEMS: false
# APP_UNLOCK_ALL_SKINS: false
# APP_UNLOCK_ALL_CAPTURA_SCENES: false
# APP_UNIVERSAL_POLARITY_EVERYWHERE: false
# APP_UNLOCK_DOUBLE_CAPACITY_POTATOES_EVERYWHERE: false
# APP_UNLOCK_EXILUS_EVERYWHERE: false
# APP_UNLOCK_ARCANES_EVERYWHERE: false
# APP_NO_DAILY_FOCUS_LIMIT: false
# APP_NO_ARGON_CRYSTAL_DECAY: false
# APP_NO_MASTERY_RANK_UP_COOLDOWN: false
# APP_NO_VENDOR_PURCHASE_LIMITS: true
# APP_NO_DEATH_MARKS: false
# APP_NO_KIM_COOLDOWNS: false
# APP_SYNDICATE_MISSIONS_REPEATABLE: false
# APP_INSTANT_FINISH_RIVEN_CHALLENGE: false
# APP_INSTANT_RESOURCE_EXTRACTOR_DRONES: false
# APP_NO_RESOURCE_EXTRACTOR_DRONES_DAMAGE: false
# APP_SKIP_CLAN_KEY_CRAFTING: false
# APP_NO_DOJO_ROOM_BUILD_STAGE: false
# APP_NO_DECO_BUILD_STAGE: false
# APP_FAST_DOJO_ROOM_DESTRUCTION: false
# APP_NO_DOJO_RESEARCH_COSTS: false
# APP_NO_DOJO_RESEARCH_TIME: false
# APP_FAST_CLAN_ASCENSION: false
# APP_SPOOF_MASTERY_RANK: -1
volumes: volumes:
- ./docker-data/static:/app/static/data - ./docker-data/conf:/app/conf
- ./docker-data/static-data:/app/static/data
- ./docker-data/logs:/app/logs - ./docker-data/logs:/app/logs
ports: ports:
- 80:80 - 80:80
- 443:443 - 443:443
# Normally, the image is fetched from Docker Hub, but you can use the local Dockerfile by removing "image" above and adding this:
#build: .
# Works best when using `docker-compose up --force-recreate --build`.
depends_on: depends_on:
- mongodb - mongodb
mongodb: mongodb:
@ -66,3 +24,4 @@ services:
MONGO_INITDB_ROOT_PASSWORD: spaceninjaserver MONGO_INITDB_ROOT_PASSWORD: spaceninjaserver
volumes: volumes:
- ./docker-data/database:/data/db - ./docker-data/database:/data/db
command: mongod --quiet --logpath /dev/null

View File

@ -1,24 +1,8 @@
#!/bin/bash #!/bin/bash
set -e set -e
# Set up the configuration file using environment variables. if [ ! -f conf/config.json ]; then
echo '{ jq --arg value "mongodb://openwfagent:spaceninjaserver@mongodb:27017/" '.mongodbUrl = $value' /app/config.json.example > /app/conf/config.json
"logger": { fi
"files": true,
"level": "trace",
"__valid_levels": "fatal, error, warn, info, http, debug, trace"
}
}
' > config.json
for config in $(env | grep "APP_") exec npm run start conf/config.json
do
var=$(echo "${config}" | tr '[:upper:]' '[:lower:]' | sed 's/app_//g' | sed -E 's/_([a-z])/\U\1/g' | sed 's/=.*//g')
val=$(echo "${config}" | sed 's/.*=//g')
jq --arg variable "$var" --arg value "$val" '.[$variable] += try [$value|fromjson][] catch $value' config.json > config.tmp
mv config.tmp config.json
done
npm i --omit=dev
npm run build
exec npm run start

View File

@ -339,9 +339,29 @@ export const getInventoryResponse = async (
} }
} }
if (config.unlockAllProfitTakerStages) {
inventoryResponse.CompletedJobChains ??= [];
const EudicoHeists = inventoryResponse.CompletedJobChains.find(x => x.LocationTag == "EudicoHeists");
if (EudicoHeists) {
EudicoHeists.Jobs = allEudicoHeistJobs;
} else {
inventoryResponse.CompletedJobChains.push({
LocationTag: "EudicoHeists",
Jobs: allEudicoHeistJobs
});
}
}
return inventoryResponse; return inventoryResponse;
}; };
const allEudicoHeistJobs = [
"/Lotus/Types/Gameplay/Venus/Jobs/Heists/HeistProfitTakerBountyOne",
"/Lotus/Types/Gameplay/Venus/Jobs/Heists/HeistProfitTakerBountyTwo",
"/Lotus/Types/Gameplay/Venus/Jobs/Heists/HeistProfitTakerBountyThree",
"/Lotus/Types/Gameplay/Venus/Jobs/Heists/HeistProfitTakerBountyFour"
];
const addString = (arr: string[], str: string): void => { const addString = (arr: string[], str: string): void => {
if (arr.indexOf(str) == -1) { if (arr.indexOf(str) == -1) {
arr.push(str); arr.push(str);

View File

@ -151,7 +151,8 @@ export const nemesisController: RequestHandler = async (req, res) => {
inventory.Nemesis!.HenchmenKilled += antivirusGain; inventory.Nemesis!.HenchmenKilled += antivirusGain;
if (inventory.Nemesis!.HenchmenKilled >= 100) { if (inventory.Nemesis!.HenchmenKilled >= 100) {
inventory.Nemesis!.HenchmenKilled = 100; inventory.Nemesis!.HenchmenKilled = 100;
// Client doesn't seem to request mode=w for infested liches, so weakening it here.
// Weaken nemesis now.
inventory.Nemesis!.InfNodes = [ inventory.Nemesis!.InfNodes = [
{ {
Node: getNemesisManifest(inventory.Nemesis!.manifest).showdownNode, Node: getNemesisManifest(inventory.Nemesis!.manifest).showdownNode,
@ -294,31 +295,15 @@ export const nemesisController: RequestHandler = async (req, res) => {
target: inventory.toJSON().Nemesis target: inventory.toJSON().Nemesis
}); });
} else if ((req.query.mode as string) == "w") { } else if ((req.query.mode as string) == "w") {
const inventory = await getInventory( const inventory = await getInventory(account._id.toString(), "Nemesis");
account._id.toString(),
"Nemesis LoadOutPresets CurrentLoadOutIds DataKnives Upgrades RawUpgrades"
);
//const body = getJSONfromString<INemesisWeakenRequest>(String(req.body)); //const body = getJSONfromString<INemesisWeakenRequest>(String(req.body));
if (inventory.Nemesis!.Weakened) { // As of 38.6.0, this request is no longer sent, instead mode=r already weakens the nemesis if appropriate.
logger.warn(`client is weakening an already-weakened nemesis?!`); // We always weaken the nemesis in mode=r so simply giving the client back the nemesis.
}
inventory.Nemesis!.InfNodes = [
{
Node: getNemesisManifest(inventory.Nemesis!.manifest).showdownNode,
Influence: 1
}
];
inventory.Nemesis!.Weakened = true;
const response: INemesisWeakenResponse = { const response: INemesisWeakenResponse = {
target: inventory.toJSON<IInventoryClient>().Nemesis! target: inventory.toJSON<IInventoryClient>().Nemesis!
}; };
await consumePasscodeModCharges(inventory, response);
await inventory.save();
res.json(response); res.json(response);
} else { } else {
logger.debug(`data provided to ${req.path}: ${String(req.body)}`); logger.debug(`data provided to ${req.path}: ${String(req.body)}`);

View File

@ -1,6 +1,7 @@
import { getJSONfromString } from "@/src/helpers/stringHelpers"; import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { getInventory, updateCurrency } from "@/src/services/inventoryService"; import { getInventory, updateCurrency } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { RequestHandler } from "express"; import { RequestHandler } from "express";
export const renamePetController: RequestHandler = async (req, res) => { export const renamePetController: RequestHandler = async (req, res) => {
@ -8,12 +9,18 @@ export const renamePetController: RequestHandler = async (req, res) => {
const inventory = await getInventory(accountId, "KubrowPets PremiumCredits PremiumCreditsFree"); const inventory = await getInventory(accountId, "KubrowPets PremiumCredits PremiumCreditsFree");
const data = getJSONfromString<IRenamePetRequest>(String(req.body)); const data = getJSONfromString<IRenamePetRequest>(String(req.body));
const details = inventory.KubrowPets.id(data.petId)!.Details!; const details = inventory.KubrowPets.id(data.petId)!.Details!;
details.Name = data.name; details.Name = data.name;
const currencyChanges = updateCurrency(inventory, 15, true);
const inventoryChanges: IInventoryChanges = {};
if (!("webui" in req.query)) {
updateCurrency(inventory, 15, true, inventoryChanges);
}
await inventory.save(); await inventory.save();
res.json({ res.json({
...data, ...data,
inventoryChanges: currencyChanges inventoryChanges: inventoryChanges
}); });
}; };

View File

@ -4,6 +4,8 @@ import { getAccountForRequest } from "@/src/services/loginService";
import { addChallenges, getInventory } from "@/src/services/inventoryService"; import { addChallenges, getInventory } from "@/src/services/inventoryService";
import { IChallengeProgress, ISeasonChallenge } from "@/src/types/inventoryTypes/inventoryTypes"; import { IChallengeProgress, ISeasonChallenge } from "@/src/types/inventoryTypes/inventoryTypes";
import { IAffiliationMods } from "@/src/types/purchaseTypes"; import { IAffiliationMods } from "@/src/types/purchaseTypes";
import { getEntriesUnsafe } from "@/src/utils/ts-utils";
import { logger } from "@/src/utils/logger";
export const updateChallengeProgressController: RequestHandler = async (req, res) => { export const updateChallengeProgressController: RequestHandler = async (req, res) => {
const challenges = getJSONfromString<IUpdateChallengeProgressRequest>(String(req.body)); const challenges = getJSONfromString<IUpdateChallengeProgressRequest>(String(req.body));
@ -13,9 +15,6 @@ export const updateChallengeProgressController: RequestHandler = async (req, res
account._id.toString(), account._id.toString(),
"ChallengesFixVersion ChallengeProgress SeasonChallengeHistory Affiliations" "ChallengesFixVersion ChallengeProgress SeasonChallengeHistory Affiliations"
); );
if (challenges.ChallengesFixVersion !== undefined) {
inventory.ChallengesFixVersion = challenges.ChallengesFixVersion;
}
let affiliationMods: IAffiliationMods[] = []; let affiliationMods: IAffiliationMods[] = [];
if (challenges.ChallengeProgress) { if (challenges.ChallengeProgress) {
affiliationMods = addChallenges( affiliationMods = addChallenges(
@ -25,8 +24,14 @@ export const updateChallengeProgressController: RequestHandler = async (req, res
challenges.SeasonChallengeCompletions challenges.SeasonChallengeCompletions
); );
} }
if (challenges.SeasonChallengeHistory) { for (const [key, value] of getEntriesUnsafe(challenges)) {
challenges.SeasonChallengeHistory.forEach(({ challenge, id }) => { switch (key) {
case "ChallengesFixVersion":
inventory.ChallengesFixVersion = value;
break;
case "SeasonChallengeHistory":
value!.forEach(({ challenge, id }) => {
const itemIndex = inventory.SeasonChallengeHistory.findIndex(i => i.challenge === challenge); const itemIndex = inventory.SeasonChallengeHistory.findIndex(i => i.challenge === challenge);
if (itemIndex !== -1) { if (itemIndex !== -1) {
inventory.SeasonChallengeHistory[itemIndex].id = id; inventory.SeasonChallengeHistory[itemIndex].id = id;
@ -34,6 +39,16 @@ export const updateChallengeProgressController: RequestHandler = async (req, res
inventory.SeasonChallengeHistory.push({ challenge, id }); inventory.SeasonChallengeHistory.push({ challenge, id });
} }
}); });
break;
case "ChallengeProgress":
case "SeasonChallengeCompletions":
case "ChallengePTS":
case "crossPlaySetting":
break;
default:
logger.warn(`unknown challenge progress entry`, { key, value });
}
} }
await inventory.save(); await inventory.save();
@ -43,8 +58,10 @@ export const updateChallengeProgressController: RequestHandler = async (req, res
}; };
interface IUpdateChallengeProgressRequest { interface IUpdateChallengeProgressRequest {
ChallengePTS?: number;
ChallengesFixVersion?: number; ChallengesFixVersion?: number;
ChallengeProgress?: IChallengeProgress[]; ChallengeProgress?: IChallengeProgress[];
SeasonChallengeHistory?: ISeasonChallenge[]; SeasonChallengeHistory?: ISeasonChallenge[];
SeasonChallengeCompletions?: ISeasonChallenge[]; SeasonChallengeCompletions?: ISeasonChallenge[];
crossPlaySetting?: string;
} }

View File

@ -1,6 +1,15 @@
import { RequestHandler } from "express"; import { RequestHandler } from "express";
import { getWorldState } from "@/src/services/worldStateService"; import { getWorldState, populateFissures } from "@/src/services/worldStateService";
import { version_compare } from "@/src/helpers/inventoryHelpers";
export const worldStateController: RequestHandler = (req, res) => { export const worldStateController: RequestHandler = async (req, res) => {
res.json(getWorldState(req.query.buildLabel as string | undefined)); const buildLabel = req.query.buildLabel as string | undefined;
const worldState = getWorldState(buildLabel);
// Omitting void fissures for versions prior to Dante Unbound to avoid script errors.
if (!buildLabel || version_compare(buildLabel, "2024.03.24.20.00") >= 0) {
await populateFissures(worldState);
}
res.json(worldState);
}; };

View File

@ -22,6 +22,7 @@ import { JSONStringify } from "json-with-bigint";
import { startWebServer } from "./services/webService"; import { startWebServer } from "./services/webService";
import { validateConfig } from "@/src/services/configWatcherService"; import { validateConfig } from "@/src/services/configWatcherService";
import { updateWorldStateCollections } from "./services/worldStateService";
// Patch JSON.stringify to work flawlessly with Bigints. // Patch JSON.stringify to work flawlessly with Bigints.
JSON.stringify = JSONStringify; JSON.stringify = JSONStringify;
@ -33,6 +34,11 @@ mongoose
.then(() => { .then(() => {
logger.info("Connected to MongoDB"); logger.info("Connected to MongoDB");
startWebServer(); startWebServer();
void updateWorldStateCollections();
setInterval(() => {
void updateWorldStateCollections();
}, 60_000);
}) })
.catch(error => { .catch(error => {
if (error instanceof Error) { if (error instanceof Error) {

View File

@ -0,0 +1,14 @@
import { IFissureDatabase } from "@/src/types/worldStateTypes";
import { model, Schema } from "mongoose";
const fissureSchema = new Schema<IFissureDatabase>({
Activation: Date,
Expiry: Date,
Node: String, // must be unique
Modifier: String,
Hard: Boolean
});
fissureSchema.index({ Expiry: 1 }, { expireAfterSeconds: 0 }); // With this, MongoDB will automatically delete expired entries.
export const Fissure = model<IFissureDatabase>("Fissure", fissureSchema);

View File

@ -25,6 +25,10 @@ export interface IConfig {
infiniteRegalAya?: boolean; infiniteRegalAya?: boolean;
infiniteHelminthMaterials?: boolean; infiniteHelminthMaterials?: boolean;
claimingBlueprintRefundsIngredients?: boolean; claimingBlueprintRefundsIngredients?: boolean;
dontSubtractPurchaseCreditCost?: boolean;
dontSubtractPurchasePlatinumCost?: boolean;
dontSubtractPurchaseItemCost?: boolean;
dontSubtractPurchaseStandingCost?: boolean;
dontSubtractVoidTraces?: boolean; dontSubtractVoidTraces?: boolean;
dontSubtractConsumables?: boolean; dontSubtractConsumables?: boolean;
unlockAllShipFeatures?: boolean; unlockAllShipFeatures?: boolean;
@ -45,6 +49,7 @@ export interface IConfig {
noDeathMarks?: boolean; noDeathMarks?: boolean;
noKimCooldowns?: boolean; noKimCooldowns?: boolean;
syndicateMissionsRepeatable?: boolean; syndicateMissionsRepeatable?: boolean;
unlockAllProfitTakerStages?: boolean;
instantFinishRivenChallenge?: boolean; instantFinishRivenChallenge?: boolean;
instantResourceExtractorDrones?: boolean; instantResourceExtractorDrones?: boolean;
noResourceExtractorDronesDamage?: boolean; noResourceExtractorDronesDamage?: boolean;
@ -55,6 +60,7 @@ export interface IConfig {
noDojoResearchCosts?: boolean; noDojoResearchCosts?: boolean;
noDojoResearchTime?: boolean; noDojoResearchTime?: boolean;
fastClanAscension?: boolean; fastClanAscension?: boolean;
missionsCanGiveAllRelics?: boolean;
spoofMasteryRank?: number; spoofMasteryRank?: number;
nightwaveStandingMultiplier?: number; nightwaveStandingMultiplier?: number;
worldState?: { worldState?: {
@ -64,6 +70,7 @@ export interface IConfig {
starDays?: boolean; starDays?: boolean;
eidolonOverride?: string; eidolonOverride?: string;
vallisOverride?: string; vallisOverride?: string;
duviriOverride?: string;
nightwaveOverride?: string; nightwaveOverride?: string;
circuitGameModes?: string[]; circuitGameModes?: string[];
}; };

View File

@ -2,6 +2,7 @@ import {
ExportEnemies, ExportEnemies,
ExportFusionBundles, ExportFusionBundles,
ExportRegions, ExportRegions,
ExportRelics,
ExportRewards, ExportRewards,
IMissionReward as IMissionRewardExternal, IMissionReward as IMissionRewardExternal,
IRegion, IRegion,
@ -1204,8 +1205,10 @@ export const addMissionRewards = async (
if (syndicateEntry && syndicateEntry.Jobs) { if (syndicateEntry && syndicateEntry.Jobs) {
let currentJob = syndicateEntry.Jobs[rewardInfo.JobTier!]; let currentJob = syndicateEntry.Jobs[rewardInfo.JobTier!];
if (syndicateEntry.Tag === "EntratiSyndicate") { if (syndicateEntry.Tag === "EntratiSyndicate") {
if (jobType.endsWith("VaultBounty")) {
const vault = syndicateEntry.Jobs.find(j => j.locationTag === locationTag); const vault = syndicateEntry.Jobs.find(j => j.locationTag === locationTag);
if (vault) currentJob = vault; if (vault) currentJob = vault;
}
let medallionAmount = Math.floor(currentJob.xpAmounts[rewardInfo.JobStage] / (rewardInfo.Q ? 0.8 : 1)); let medallionAmount = Math.floor(currentJob.xpAmounts[rewardInfo.JobStage] / (rewardInfo.Q ? 0.8 : 1));
if ( if (
@ -1552,8 +1555,10 @@ function getRandomMissionDrops(
let job = syndicateEntry.Jobs[RewardInfo.JobTier!]; let job = syndicateEntry.Jobs[RewardInfo.JobTier!];
if (syndicateEntry.Tag === "EntratiSyndicate") { if (syndicateEntry.Tag === "EntratiSyndicate") {
if (jobType.endsWith("VaultBounty")) {
const vault = syndicateEntry.Jobs.find(j => j.locationTag === locationTag); const vault = syndicateEntry.Jobs.find(j => j.locationTag === locationTag);
if (vault && locationTag) job = vault; if (vault) job = vault;
}
// if ( // if (
// [ // [
// "DeimosRuinsExterminateBounty", // "DeimosRuinsExterminateBounty",
@ -1801,6 +1806,23 @@ function getRandomMissionDrops(
drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount }); drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount });
} }
} }
if (config.missionsCanGiveAllRelics) {
for (const drop of drops) {
const itemType = fromStoreItem(drop.StoreItem);
if (itemType in ExportRelics) {
const relic = ExportRelics[itemType];
const replacement = getRandomElement(
Object.entries(ExportRelics).filter(
arr => arr[1].era == relic.era && arr[1].quality == relic.quality
)
)!;
logger.debug(`replacing ${relic.era} ${relic.category} with ${replacement[1].category}`);
drop.StoreItem = toStoreItem(replacement[0]);
}
}
}
return drops; return drops;
} }

View File

@ -67,18 +67,23 @@ export const handlePurchase = async (
if (!offer) { if (!offer) {
throw new Error(`unknown vendor offer: ${ItemId ? ItemId : purchaseRequest.PurchaseParams.StoreItem}`); throw new Error(`unknown vendor offer: ${ItemId ? ItemId : purchaseRequest.PurchaseParams.StoreItem}`);
} }
if (!config.dontSubtractPurchaseCreditCost) {
if (offer.RegularPrice) { if (offer.RegularPrice) {
combineInventoryChanges( combineInventoryChanges(
prePurchaseInventoryChanges, prePurchaseInventoryChanges,
updateCurrency(inventory, offer.RegularPrice[0], false) updateCurrency(inventory, offer.RegularPrice[0], false)
); );
} }
}
if (!config.dontSubtractPurchasePlatinumCost) {
if (offer.PremiumPrice) { if (offer.PremiumPrice) {
combineInventoryChanges( combineInventoryChanges(
prePurchaseInventoryChanges, prePurchaseInventoryChanges,
updateCurrency(inventory, offer.PremiumPrice[0], true) updateCurrency(inventory, offer.PremiumPrice[0], true)
); );
} }
}
if (!config.dontSubtractPurchaseItemCost) {
if (offer.ItemPrices) { if (offer.ItemPrices) {
handleItemPrices( handleItemPrices(
inventory, inventory,
@ -87,6 +92,7 @@ export const handlePurchase = async (
prePurchaseInventoryChanges prePurchaseInventoryChanges
); );
} }
}
if (offer.LocTagRandSeed !== undefined) { if (offer.LocTagRandSeed !== undefined) {
seed = BigInt(offer.LocTagRandSeed); seed = BigInt(offer.LocTagRandSeed);
} }
@ -179,14 +185,17 @@ export const handlePurchase = async (
x => x.ItemType == purchaseRequest.PurchaseParams.StoreItem x => x.ItemType == purchaseRequest.PurchaseParams.StoreItem
); );
if (offer) { if (offer) {
if (!config.dontSubtractPurchaseCreditCost) {
combineInventoryChanges( combineInventoryChanges(
purchaseResponse.InventoryChanges, purchaseResponse.InventoryChanges,
updateCurrency(inventory, offer.RegularPrice, false) updateCurrency(inventory, offer.RegularPrice, false)
); );
}
if (purchaseRequest.PurchaseParams.ExpectedPrice) { if (purchaseRequest.PurchaseParams.ExpectedPrice) {
throw new Error(`vendor purchase should not have an expected price`); throw new Error(`vendor purchase should not have an expected price`);
} }
if (!config.dontSubtractPurchaseItemCost) {
const invItem: IMiscItem = { const invItem: IMiscItem = {
ItemType: "/Lotus/Types/Items/MiscItems/PrimeBucks", ItemType: "/Lotus/Types/Items/MiscItems/PrimeBucks",
ItemCount: offer.PrimePrice * purchaseRequest.PurchaseParams.Quantity * -1 ItemCount: offer.PrimePrice * purchaseRequest.PurchaseParams.Quantity * -1
@ -195,6 +204,7 @@ export const handlePurchase = async (
purchaseResponse.InventoryChanges.MiscItems ??= []; purchaseResponse.InventoryChanges.MiscItems ??= [];
purchaseResponse.InventoryChanges.MiscItems.push(invItem); purchaseResponse.InventoryChanges.MiscItems.push(invItem);
} }
}
break; break;
} }
case 2: case 2:
@ -211,7 +221,7 @@ export const handlePurchase = async (
Title: lastTitle Title: lastTitle
} }
]; ];
} else { } else if (!config.dontSubtractPurchaseStandingCost) {
const syndicate = ExportSyndicates[syndicateTag]; const syndicate = ExportSyndicates[syndicateTag];
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (syndicate) { if (syndicate) {
@ -239,19 +249,19 @@ export const handlePurchase = async (
const vendor = ExportVendors[purchaseRequest.PurchaseParams.SourceId!]; const vendor = ExportVendors[purchaseRequest.PurchaseParams.SourceId!];
const offer = vendor.items.find(x => x.storeItem == purchaseRequest.PurchaseParams.StoreItem); const offer = vendor.items.find(x => x.storeItem == purchaseRequest.PurchaseParams.StoreItem);
if (offer) { if (offer) {
if (typeof offer.credits == "number") { if (typeof offer.credits == "number" && !config.dontSubtractPurchaseCreditCost) {
combineInventoryChanges( combineInventoryChanges(
purchaseResponse.InventoryChanges, purchaseResponse.InventoryChanges,
updateCurrency(inventory, offer.credits, false) updateCurrency(inventory, offer.credits, false)
); );
} }
if (typeof offer.platinum == "number") { if (typeof offer.platinum == "number" && !config.dontSubtractPurchasePlatinumCost) {
combineInventoryChanges( combineInventoryChanges(
purchaseResponse.InventoryChanges, purchaseResponse.InventoryChanges,
updateCurrency(inventory, offer.platinum, true) updateCurrency(inventory, offer.platinum, true)
); );
} }
if (offer.itemPrices) { if (offer.itemPrices && !config.dontSubtractPurchaseItemCost) {
handleItemPrices( handleItemPrices(
inventory, inventory,
offer.itemPrices, offer.itemPrices,
@ -278,6 +288,7 @@ export const handlePurchase = async (
); );
if (offer) { if (offer) {
if (offer.RegularPrice) { if (offer.RegularPrice) {
if (!config.dontSubtractPurchaseItemCost) {
const invItem: IMiscItem = { const invItem: IMiscItem = {
ItemType: "/Lotus/Types/Items/MiscItems/SchismKey", ItemType: "/Lotus/Types/Items/MiscItems/SchismKey",
ItemCount: offer.RegularPrice * purchaseRequest.PurchaseParams.Quantity * -1 ItemCount: offer.RegularPrice * purchaseRequest.PurchaseParams.Quantity * -1
@ -287,6 +298,7 @@ export const handlePurchase = async (
purchaseResponse.InventoryChanges.MiscItems ??= []; purchaseResponse.InventoryChanges.MiscItems ??= [];
purchaseResponse.InventoryChanges.MiscItems.push(invItem); purchaseResponse.InventoryChanges.MiscItems.push(invItem);
}
} else if (!config.infiniteRegalAya) { } else if (!config.infiniteRegalAya) {
inventory.PrimeTokens -= offer.PrimePrice! * purchaseRequest.PurchaseParams.Quantity; inventory.PrimeTokens -= offer.PrimePrice! * purchaseRequest.PurchaseParams.Quantity;

View File

@ -7,7 +7,6 @@ import { IItemManifest, IVendorInfo, IVendorManifest } from "@/src/types/vendorT
import { logger } from "@/src/utils/logger"; import { logger } from "@/src/utils/logger";
import { ExportVendors, IRange, IVendor, IVendorOffer } from "warframe-public-export-plus"; import { ExportVendors, IRange, IVendor, IVendorOffer } from "warframe-public-export-plus";
import ArchimedeanVendorManifest from "@/static/fixed_responses/getVendorInfo/ArchimedeanVendorManifest.json";
import DeimosEntratiFragmentVendorProductsManifest from "@/static/fixed_responses/getVendorInfo/DeimosEntratiFragmentVendorProductsManifest.json"; import DeimosEntratiFragmentVendorProductsManifest from "@/static/fixed_responses/getVendorInfo/DeimosEntratiFragmentVendorProductsManifest.json";
import DeimosHivemindCommisionsManifestFishmonger from "@/static/fixed_responses/getVendorInfo/DeimosHivemindCommisionsManifestFishmonger.json"; import DeimosHivemindCommisionsManifestFishmonger from "@/static/fixed_responses/getVendorInfo/DeimosHivemindCommisionsManifestFishmonger.json";
import DeimosHivemindCommisionsManifestPetVendor from "@/static/fixed_responses/getVendorInfo/DeimosHivemindCommisionsManifestPetVendor.json"; import DeimosHivemindCommisionsManifestPetVendor from "@/static/fixed_responses/getVendorInfo/DeimosHivemindCommisionsManifestPetVendor.json";
@ -19,15 +18,11 @@ import DeimosPetVendorManifest from "@/static/fixed_responses/getVendorInfo/Deim
import DuviriAcrithisVendorManifest from "@/static/fixed_responses/getVendorInfo/DuviriAcrithisVendorManifest.json"; import DuviriAcrithisVendorManifest from "@/static/fixed_responses/getVendorInfo/DuviriAcrithisVendorManifest.json";
import EntratiLabsEntratiLabsCommisionsManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabsCommisionsManifest.json"; import EntratiLabsEntratiLabsCommisionsManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabsCommisionsManifest.json";
import EntratiLabsEntratiLabVendorManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabVendorManifest.json"; import EntratiLabsEntratiLabVendorManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabVendorManifest.json";
import MaskSalesmanManifest from "@/static/fixed_responses/getVendorInfo/MaskSalesmanManifest.json";
import Nova1999ConquestShopManifest from "@/static/fixed_responses/getVendorInfo/Nova1999ConquestShopManifest.json"; import Nova1999ConquestShopManifest from "@/static/fixed_responses/getVendorInfo/Nova1999ConquestShopManifest.json";
import OstronPetVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronPetVendorManifest.json"; import OstronPetVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronPetVendorManifest.json";
import SolarisDebtTokenVendorRepossessionsManifest from "@/static/fixed_responses/getVendorInfo/SolarisDebtTokenVendorRepossessionsManifest.json"; import SolarisDebtTokenVendorRepossessionsManifest from "@/static/fixed_responses/getVendorInfo/SolarisDebtTokenVendorRepossessionsManifest.json";
import Temple1999VendorManifest from "@/static/fixed_responses/getVendorInfo/Temple1999VendorManifest.json";
import ZarimanCommisionsManifestArchimedean from "@/static/fixed_responses/getVendorInfo/ZarimanCommisionsManifestArchimedean.json";
const rawVendorManifests: IVendorManifest[] = [ const rawVendorManifests: IVendorManifest[] = [
ArchimedeanVendorManifest,
DeimosEntratiFragmentVendorProductsManifest, DeimosEntratiFragmentVendorProductsManifest,
DeimosHivemindCommisionsManifestFishmonger, DeimosHivemindCommisionsManifestFishmonger,
DeimosHivemindCommisionsManifestPetVendor, DeimosHivemindCommisionsManifestPetVendor,
@ -39,12 +34,9 @@ const rawVendorManifests: IVendorManifest[] = [
DuviriAcrithisVendorManifest, DuviriAcrithisVendorManifest,
EntratiLabsEntratiLabsCommisionsManifest, EntratiLabsEntratiLabsCommisionsManifest,
EntratiLabsEntratiLabVendorManifest, EntratiLabsEntratiLabVendorManifest,
MaskSalesmanManifest,
Nova1999ConquestShopManifest, Nova1999ConquestShopManifest,
OstronPetVendorManifest, OstronPetVendorManifest,
SolarisDebtTokenVendorRepossessionsManifest, SolarisDebtTokenVendorRepossessionsManifest
Temple1999VendorManifest,
ZarimanCommisionsManifestArchimedean
]; ];
interface IGeneratableVendorInfo extends Omit<IVendorInfo, "ItemManifest" | "Expiry"> { interface IGeneratableVendorInfo extends Omit<IVendorInfo, "ItemManifest" | "Expiry"> {
@ -283,6 +275,7 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
// Add permanent offers // Add permanent offers
let numUncountedOffers = 0; let numUncountedOffers = 0;
let numCountedOffers = 0;
let offset = 0; let offset = 0;
for (const item of manifest.items) { for (const item of manifest.items) {
if (item.alwaysOffered || item.rotatedWeekly) { if (item.alwaysOffered || item.rotatedWeekly) {
@ -293,22 +286,30 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
offersToAdd.push(item); offersToAdd.push(item);
++offset; ++offset;
} }
} else {
numCountedOffers += 1 + item.duplicates;
} }
} }
// Add counted offers // Add counted offers
if (manifest.numItems) { const useRng =
const useRng = manifest.numItems.minValue != manifest.numItems.maxValue; manifest.numItems &&
const numItemsTarget = (manifest.numItems.minValue != manifest.numItems.maxValue ||
numUncountedOffers + manifest.numItems.minValue != numCountedOffers);
const numItemsTarget = manifest.numItems
? numUncountedOffers +
(useRng (useRng
? rng.randomInt(manifest.numItems.minValue, manifest.numItems.maxValue) ? rng.randomInt(manifest.numItems.minValue, manifest.numItems.maxValue)
: manifest.numItems.minValue); : manifest.numItems.minValue)
: manifest.items.length;
let i = 0; let i = 0;
const rollableOffers = manifest.items.filter(x => x.probability !== undefined) as (Omit<
IVendorOffer,
"probability"
> & { probability: number })[];
while (info.ItemManifest.length + offersToAdd.length < numItemsTarget) { while (info.ItemManifest.length + offersToAdd.length < numItemsTarget) {
const item = useRng ? rng.randomElement(manifest.items)! : manifest.items[i++]; const item = useRng ? rng.randomReward(rollableOffers)! : rollableOffers[i++];
if ( if (
!item.alwaysOffered &&
remainingItemCapacity[getOfferId(item)] != 0 && remainingItemCapacity[getOfferId(item)] != 0 &&
(numOffersThatNeedToMatchABin == 0 || missingItemsPerBin[item.bin]) (numOffersThatNeedToMatchABin == 0 || missingItemsPerBin[item.bin])
) { ) {
@ -319,11 +320,10 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
} }
offersToAdd.splice(offset, 0, item); offersToAdd.splice(offset, 0, item);
} }
if (i == manifest.items.length) { if (i == rollableOffers.length) {
i = 0; i = 0;
} }
} }
}
} else { } else {
const binThisCycle = cycleIndex % 2; // Note: May want to auto-compute the bin size, but this is only used for coda weapons right now. const binThisCycle = cycleIndex % 2; // Note: May want to auto-compute the bin size, but this is only used for coda weapons right now.
for (const rawItem of manifest.items) { for (const rawItem of manifest.items) {
@ -358,7 +358,7 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
} }
}; };
if (rawItem.numRandomItemPrices) { if (rawItem.numRandomItemPrices) {
item.ItemPrices = []; item.ItemPrices ??= [];
for (let i = 0; i != rawItem.numRandomItemPrices; ++i) { for (let i = 0; i != rawItem.numRandomItemPrices; ++i) {
let itemPrice: { type: string; count: IRange }; let itemPrice: { type: string; count: IRange };
do { do {
@ -398,11 +398,13 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
info.ItemManifest.push(item); info.ItemManifest.push(item);
} }
if (manifest.numItemsPerBin) {
info.ItemManifest.sort((a, b) => { info.ItemManifest.sort((a, b) => {
const aBin = parseInt(a.Bin.substring(4)); const aBin = parseInt(a.Bin.substring(4));
const bBin = parseInt(b.Bin.substring(4)); const bBin = parseInt(b.Bin.substring(4));
return aBin == bBin ? 0 : aBin < bBin ? +1 : -1; return aBin == bBin ? 0 : aBin < bBin ? +1 : -1;
}); });
}
// Update vendor expiry // Update vendor expiry
let soonestOfferExpiry: number = Number.MAX_SAFE_INTEGER; let soonestOfferExpiry: number = Number.MAX_SAFE_INTEGER;
@ -465,4 +467,26 @@ if (isDev) {
) { ) {
logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Hubs/RailjackCrewMemberVendorManifest`); logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Hubs/RailjackCrewMemberVendorManifest`);
} }
const temple = getVendorManifestByTypeName("/Lotus/Types/Game/VendorManifests/TheHex/Temple1999VendorManifest")!
.VendorInfo.ItemManifest;
if (!temple.find(x => x.StoreItem == "/Lotus/StoreItems/Types/Items/MiscItems/Kuva")) {
logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/TheHex/Temple1999VendorManifest`);
}
const nakak = getVendorManifestByTypeName("/Lotus/Types/Game/VendorManifests/Ostron/MaskSalesmanManifest")!
.VendorInfo.ItemManifest;
if (
nakak.length != 10 ||
nakak[0].StoreItem != "/Lotus/StoreItems/Upgrades/Skins/Ostron/RevenantMask" ||
nakak[1].StoreItem != "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumper" ||
nakak[1].ItemPrices?.length != 4 ||
nakak[2].StoreItem != "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumperMedium" ||
nakak[2].ItemPrices?.length != 4 ||
nakak[3].StoreItem != "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumperLarge" ||
nakak[3].ItemPrices?.length != 4
// The remaining offers should be computed by weighted RNG.
) {
logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Ostron/MaskSalesmanManifest`);
}
} }

View File

@ -1,12 +1,13 @@
import staticWorldState from "@/static/fixed_responses/worldState/worldState.json"; import staticWorldState from "@/static/fixed_responses/worldState/worldState.json";
import fissureMissions from "@/static/fixed_responses/worldState/fissureMissions.json";
import sortieTilesets from "@/static/fixed_responses/worldState/sortieTilesets.json"; import sortieTilesets from "@/static/fixed_responses/worldState/sortieTilesets.json";
import sortieTilesetMissions from "@/static/fixed_responses/worldState/sortieTilesetMissions.json"; import sortieTilesetMissions from "@/static/fixed_responses/worldState/sortieTilesetMissions.json";
import syndicateMissions from "@/static/fixed_responses/worldState/syndicateMissions.json"; import syndicateMissions from "@/static/fixed_responses/worldState/syndicateMissions.json";
import { buildConfig } from "@/src/services/buildConfigService"; import { buildConfig } from "@/src/services/buildConfigService";
import { unixTimesInMs } from "@/src/constants/timeConstants"; import { unixTimesInMs } from "@/src/constants/timeConstants";
import { config } from "@/src/services/configService"; import { config } from "@/src/services/configService";
import { SRng } from "@/src/services/rngService"; import { getRandomElement, getRandomInt, SRng } from "@/src/services/rngService";
import { ExportRegions, ExportSyndicates, IRegion } from "warframe-public-export-plus"; import { eMissionType, ExportRegions, ExportSyndicates, IRegion } from "warframe-public-export-plus";
import { import {
ICalendarDay, ICalendarDay,
ICalendarEvent, ICalendarEvent,
@ -21,8 +22,9 @@ import {
IWorldState, IWorldState,
TCircuitGameMode TCircuitGameMode
} from "../types/worldStateTypes"; } from "../types/worldStateTypes";
import { version_compare } from "../helpers/inventoryHelpers"; import { toMongoDate, toOid, version_compare } from "../helpers/inventoryHelpers";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { Fissure } from "../models/worldStateModel";
const sortieBosses = [ const sortieBosses = [
"SORTIE_BOSS_HYENA", "SORTIE_BOSS_HYENA",
@ -1068,6 +1070,27 @@ const doesTimeSatsifyConstraints = (timeSecs: number): boolean => {
} }
} }
if (config.worldState?.duviriOverride) {
const duviriMoods = ["sorrow", "fear", "joy", "anger", "envy"];
const desiredMood = duviriMoods.indexOf(config.worldState.duviriOverride);
if (desiredMood == -1) {
logger.warn(`ignoring invalid config value for worldState.duviriOverride`, {
value: config.worldState.duviriOverride,
valid_values: duviriMoods
});
} else {
const moodIndex = Math.trunc(timeSecs / 7200);
const moodStart = moodIndex * 7200;
const moodEnd = moodStart + 7200;
if (
moodIndex % 5 != desiredMood ||
isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, moodEnd * 1000)
) {
return false;
}
}
}
return true; return true;
}; };
@ -1089,6 +1112,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
Alerts: [], Alerts: [],
Sorties: [], Sorties: [],
LiteSorties: [], LiteSorties: [],
ActiveMissions: [],
GlobalUpgrades: [], GlobalUpgrades: [],
VoidStorms: [], VoidStorms: [],
EndlessXpChoices: [], EndlessXpChoices: [],
@ -1097,14 +1121,10 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
SyndicateMissions: [...staticWorldState.SyndicateMissions] SyndicateMissions: [...staticWorldState.SyndicateMissions]
}; };
// Omit void fissures for versions prior to Dante Unbound to avoid script errors.
if (buildLabel && version_compare(buildLabel, "2024.03.24.20.00") < 0) {
worldState.ActiveMissions = [];
if (version_compare(buildLabel, "2017.10.12.17.04") < 0) {
// Old versions seem to really get hung up on not being able to load these. // Old versions seem to really get hung up on not being able to load these.
if (buildLabel && version_compare(buildLabel, "2017.10.12.17.04") < 0) {
worldState.PVPChallengeInstances = []; worldState.PVPChallengeInstances = [];
} }
}
if (config.worldState?.starDays) { if (config.worldState?.starDays) {
worldState.Goals.push({ worldState.Goals.push({
@ -1343,6 +1363,24 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
return worldState; return worldState;
}; };
export const populateFissures = async (worldState: IWorldState): Promise<void> => {
const fissures = await Fissure.find({});
for (const fissure of fissures) {
const meta = ExportRegions[fissure.Node];
worldState.ActiveMissions.push({
_id: toOid(fissure._id),
Region: meta.systemIndex + 1,
Seed: 1337,
Activation: toMongoDate(fissure.Activation),
Expiry: toMongoDate(fissure.Expiry),
Node: fissure.Node,
MissionType: eMissionType[meta.missionIndex].tag,
Modifier: fissure.Modifier,
Hard: fissure.Hard
});
}
};
export const idToBountyCycle = (id: string): number => { export const idToBountyCycle = (id: string): number => {
return Math.trunc((parseInt(id.substring(0, 8), 16) * 1000) / 9000_000); return Math.trunc((parseInt(id.substring(0, 8), 16) * 1000) / 9000_000);
}; };
@ -1470,3 +1508,57 @@ const nightwaveTagToSeason: Record<string, number> = {
RadioLegionIntermissionSyndicate: 1, // Intermission I RadioLegionIntermissionSyndicate: 1, // Intermission I
RadioLegionSyndicate: 0 // The Wolf of Saturn Six RadioLegionSyndicate: 0 // The Wolf of Saturn Six
}; };
export const updateWorldStateCollections = async (): Promise<void> => {
const fissures = await Fissure.find();
const activeNodes = new Set<string>();
const tierToFurthestExpiry: Record<string, number> = {
VoidT1: 0,
VoidT2: 0,
VoidT3: 0,
VoidT4: 0,
VoidT5: 0,
VoidT6: 0,
VoidT1Hard: 0,
VoidT2Hard: 0,
VoidT3Hard: 0,
VoidT4Hard: 0,
VoidT5Hard: 0,
VoidT6Hard: 0
};
for (const fissure of fissures) {
activeNodes.add(fissure.Node);
const key = fissure.Modifier + (fissure.Hard ? "Hard" : "");
tierToFurthestExpiry[key] = Math.max(tierToFurthestExpiry[key], fissure.Expiry.getTime());
}
const deadline = Date.now() - 6 * unixTimesInMs.minute;
for (const [tier, expiry] of Object.entries(tierToFurthestExpiry)) {
if (expiry < deadline) {
const numFissures = getRandomInt(1, 3);
for (let i = 0; i != numFissures; ++i) {
const modifier = tier.replace("Hard", "") as
| "VoidT1"
| "VoidT2"
| "VoidT3"
| "VoidT4"
| "VoidT5"
| "VoidT6";
let node: string;
do {
node = getRandomElement(fissureMissions[modifier])!;
} while (activeNodes.has(node));
activeNodes.add(node);
await Fissure.insertOne({
Activation: new Date(),
Expiry: new Date(Date.now() + getRandomInt(60, 120) * unixTimesInMs.minute),
Node: node,
Modifier: modifier,
Hard: tier.indexOf("Hard") != -1 ? true : undefined
});
}
}
}
};

View File

@ -9,8 +9,8 @@ export interface IWorldState {
Sorties: ISortie[]; Sorties: ISortie[];
LiteSorties: ILiteSortie[]; LiteSorties: ILiteSortie[];
SyndicateMissions: ISyndicateMissionInfo[]; SyndicateMissions: ISyndicateMissionInfo[];
GlobalUpgrades: IGlobalUpgrade[];
ActiveMissions: IFissure[]; ActiveMissions: IFissure[];
GlobalUpgrades: IGlobalUpgrade[];
NodeOverrides: INodeOverride[]; NodeOverrides: INodeOverride[];
VoidStorms: IVoidStorm[]; VoidStorms: IVoidStorm[];
PVPChallengeInstances: IPVPChallengeInstance[]; PVPChallengeInstances: IPVPChallengeInstance[];
@ -86,6 +86,14 @@ export interface IFissure {
Hard?: boolean; Hard?: boolean;
} }
export interface IFissureDatabase {
Activation: Date;
Expiry: Date;
Node: string;
Modifier: "VoidT1" | "VoidT2" | "VoidT3" | "VoidT4" | "VoidT5" | "VoidT6";
Hard?: boolean;
}
export interface INodeOverride { export interface INodeOverride {
_id: IOid; _id: IOid;
Activation?: IMongoDate; Activation?: IMongoDate;

View File

@ -1,38 +0,0 @@
{
"VendorInfo": {
"_id": { "$oid": "62695b0467e5d379750f9f75" },
"TypeName": "/Lotus/Types/Game/VendorManifests/Zariman/ArchimedeanVendorManifest",
"ItemManifest": [
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/VoidPlumeAOrnament",
"ItemPrices": [{ "ItemCount": 1, "ItemType": "/Lotus/Types/Gameplay/Zariman/Resources/VoidAngelItem", "ProductCategory": "MiscItems" }],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": { "$date": { "$numberLong": "9999999000000" } },
"AllowMultipurchase": true,
"Id": { "$oid": "63ed01ef4c37f93d0b797826" }
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/VoidPlumeBOrnament",
"ItemPrices": [{ "ItemCount": 1, "ItemType": "/Lotus/Types/Gameplay/Zariman/Resources/VoidAngelItem", "ProductCategory": "MiscItems" }],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": { "$date": { "$numberLong": "9999999000000" } },
"AllowMultipurchase": true,
"Id": { "$oid": "63ed01ef4c37f93d0b797827" }
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/MiscItems/Kuva",
"ItemPrices": [{ "ItemCount": 5, "ItemType": "/Lotus/Types/Gameplay/Zariman/Resources/VoidAngelItem", "ProductCategory": "MiscItems" }],
"Bin": "BIN_0",
"QuantityMultiplier": 35000,
"Expiry": { "$date": { "$numberLong": "9999999000000" } },
"PurchaseQuantityLimit": 1,
"AllowMultipurchase": false,
"Id": { "$oid": "66664112af1177b5070ab882" }
}
],
"PropertyTextHash": "DB7BF03C3FE6D0036A4DC30066A9A17E",
"Expiry": { "$date": { "$numberLong": "9999999000000" } }
}
}

View File

@ -1,301 +0,0 @@
{
"VendorInfo": {
"_id": {
"$oid": "598a090d9a4a313746fd1f24"
},
"TypeName": "/Lotus/Types/Game/VendorManifests/Ostron/MaskSalesmanManifest",
"ItemManifest": [
{
"StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/RevenantMask",
"ItemPrices": [
{
"ItemCount": 1,
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/CetusWispItem",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "63ed01ef4c37f93d0b797674"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumper",
"ItemPrices": [
{
"ItemCount": 2,
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/CetusWispItem",
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishBPartItem",
"ItemCount": 10,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/NistlebrushItem",
"ItemCount": 10,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonOreAAlloyAItem",
"ItemCount": 32,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "63ed01ef4c37f93d0b797675"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumperMedium",
"ItemPrices": [
{
"ItemCount": 4,
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/CetusWispItem",
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonGemBCutAItem",
"ItemCount": 24,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishAPartItem",
"ItemCount": 18,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishBPartItem",
"ItemCount": 27,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_1",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "63ed01ef4c37f93d0b797676"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumperLarge",
"ItemPrices": [
{
"ItemCount": 6,
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/CetusWispItem",
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonGemACutAItem",
"ItemCount": 35,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothCommonFishAPartItem",
"ItemCount": 95,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/NistlebrushItem",
"ItemCount": 60,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "63ed01ef4c37f93d0b797677"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Recipes/SynthicatorRecipes/FlareBlueBlueprint",
"ItemPrices": [
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishBPartItem",
"ItemCount": 10,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/DayCommonFishCPartItem",
"ItemCount": 10,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "6651291214e90115b91b50a1"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Recipes/SynthicatorRecipes/FlareRedBlueprint",
"ItemPrices": [
{
"ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonOreAAlloyAItem",
"ItemCount": 37,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishAPartItem",
"ItemCount": 7,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "6651291214e90115b91b50a2"
}
},
{
"StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/VoltMask",
"ItemPrices": [
{
"ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonOreBAlloyBItem",
"ItemCount": 34,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/GrokdrulItem",
"ItemCount": 17,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "6651291214e90115b91b50a3"
}
},
{
"StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/MagMask",
"ItemPrices": [
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/DayCommonFishBPartItem",
"ItemCount": 16,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/ForestRodentPartItem",
"ItemCount": 5,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "6651291214e90115b91b50a4"
}
},
{
"StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/ExcaliburMask",
"ItemPrices": [
{
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/BirdOfPreyPartItem",
"ItemCount": 5,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/GrokdrulItem",
"ItemCount": 20,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "6651291214e90115b91b50a5"
}
},
{
"StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/GrineerMask",
"ItemPrices": [
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/DayCommonFishBPartItem",
"ItemCount": 20,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonOreAAlloyAItem",
"ItemCount": 31,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_1",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "6651291214e90115b91b50a6"
}
}
],
"PropertyTextHash": "6AACA376DA34B35B5C16F1B40DBC017D",
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
}
}
}

View File

@ -1,459 +0,0 @@
{
"VendorInfo": {
"_id": {
"$oid": "67dadc30e4b6e0e5979c8d56"
},
"TypeName": "/Lotus/Types/Game/VendorManifests/TheHex/Temple1999VendorManifest",
"ItemManifest": [
{
"StoreItem": "/Lotus/StoreItems/Types/Recipes/WarframeRecipes/TempleBlueprint",
"ItemPrices": [
{
"ItemCount": 195,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c18c"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Recipes/WarframeRecipes/TempleSystemsBlueprint",
"ItemPrices": [
{
"ItemCount": 65,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c18d"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Recipes/WarframeRecipes/TempleChassisBlueprint",
"ItemPrices": [
{
"ItemCount": 65,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c18e"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Recipes/WarframeRecipes/TempleHelmetBlueprint",
"ItemPrices": [
{
"ItemCount": 65,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c18f"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Recipes/Weapons/1999EntHybridPistolBlueprint",
"ItemPrices": [
{
"ItemCount": 120,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c190"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Recipes/Weapons/WeaponParts/1999EntHybridPistolBarrelBlueprint",
"ItemPrices": [
{
"ItemCount": 60,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c191"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Recipes/Weapons/WeaponParts/1999EntHybridPistolReceiverBlueprint",
"ItemPrices": [
{
"ItemCount": 60,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c192"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Recipes/Weapons/WeaponParts/1999EntHybridPistolStockBlueprint",
"ItemPrices": [
{
"ItemCount": 60,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c193"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumDrumCoreKitA",
"ItemPrices": [
{
"ItemCount": 30,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c194"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumDrumCymbalA",
"ItemPrices": [
{
"ItemCount": 30,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c195"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumDrumFloorTomA",
"ItemPrices": [
{
"ItemCount": 30,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c196"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumDrumSnareA",
"ItemPrices": [
{
"ItemCount": 30,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c197"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumEquipmentCaseA",
"ItemPrices": [
{
"ItemCount": 30,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c198"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumEquipmentCaseB",
"ItemPrices": [
{
"ItemCount": 30,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c199"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumEquipmentCaseC",
"ItemPrices": [
{
"ItemCount": 30,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c19a"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumEquipmentCaseD",
"ItemPrices": [
{
"ItemCount": 30,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c19b"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumEquipmentCaseE",
"ItemPrices": [
{
"ItemCount": 30,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c19c"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumEquipmentCaseF",
"ItemPrices": [
{
"ItemCount": 30,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c19d"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Hollvania/LASxStadiumSynthKeyboardA",
"ItemPrices": [
{
"ItemCount": 30,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c19e"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/PhotoBooth/Vania/PhotoboothTileVaniaObjTempleDefense",
"ItemPrices": [
{
"ItemCount": 100,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": false,
"Id": {
"$oid": "67dadc30641da66dc5c1c19f"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/MiscItems/Kuva",
"ItemPrices": [
{
"ItemCount": 110,
"ItemType": "/Lotus/Types/Gameplay/1999Wf/Resources/1999ResourceDefense",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 6000,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"PurchaseQuantityLimit": 7,
"AllowMultipurchase": true,
"Id": {
"$oid": "67dadc30641da66dc5c1c1a5"
}
}
],
"PropertyTextHash": "20B13D9EB78FEC80EA32D0687F5BA1AE",
"RequiredGoalTag": "",
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
}
}
}

View File

@ -1,75 +0,0 @@
{
"VendorInfo": {
"_id": { "$oid": "62a20ba667e5d3797540d831" },
"TypeName": "/Lotus/Types/Game/VendorManifests/Zariman/ZarimanCommisionsManifestArchimedean",
"ItemManifest": [
{
"StoreItem": "/Lotus/Types/StoreItems/Packages/Tasks/Zariman/AchimedeanTaskE",
"ItemPrices": [
{ "ItemType": "/Lotus/Types/Gameplay/Zariman/Resources/ZarimanMiscItemB", "ItemCount": 4, "ProductCategory": "MiscItems" },
{ "ItemType": "/Lotus/Types/Gameplay/Zariman/Resources/ZarimanMiscItemA", "ItemCount": 6, "ProductCategory": "MiscItems" }
],
"Bin": "BIN_4",
"QuantityMultiplier": 1,
"Expiry": { "$date": { "$numberLong": "9999999000000" } },
"PurchaseQuantityLimit": 1,
"AllowMultipurchase": false,
"Id": { "$oid": "6678b612aa3d8ee5c2597299" }
},
{
"StoreItem": "/Lotus/Types/StoreItems/Packages/Tasks/Zariman/AchimedeanTaskD",
"ItemPrices": [
{ "ItemType": "/Lotus/Types/Gameplay/Zariman/Resources/ZarimanMiscItemA", "ItemCount": 5, "ProductCategory": "MiscItems" },
{ "ItemType": "/Lotus/Types/Gameplay/Zariman/Resources/ZarimanMiscItemB", "ItemCount": 3, "ProductCategory": "MiscItems" }
],
"Bin": "BIN_3",
"QuantityMultiplier": 1,
"Expiry": { "$date": { "$numberLong": "9999999000000" } },
"PurchaseQuantityLimit": 1,
"AllowMultipurchase": false,
"Id": { "$oid": "6678b612aa3d8ee5c259729a" }
},
{
"StoreItem": "/Lotus/Types/StoreItems/Packages/Tasks/Zariman/AchimedeanTaskC",
"ItemPrices": [
{ "ItemType": "/Lotus/Types/Gameplay/Zariman/Resources/VoidWraithItem", "ItemCount": 15, "ProductCategory": "MiscItems" },
{ "ItemType": "/Lotus/Types/Gameplay/Zariman/Resources/ZarimanDogTagUncommon", "ItemCount": 1, "ProductCategory": "MiscItems" }
],
"Bin": "BIN_2",
"QuantityMultiplier": 1,
"Expiry": { "$date": { "$numberLong": "9999999000000" } },
"PurchaseQuantityLimit": 1,
"AllowMultipurchase": false,
"Id": { "$oid": "6678b612aa3d8ee5c259729b" }
},
{
"StoreItem": "/Lotus/Types/StoreItems/Packages/Tasks/Zariman/AchimedeanTaskB",
"ItemPrices": [
{ "ItemType": "/Lotus/Types/Gameplay/Zariman/Resources/VoidWraithItem", "ItemCount": 4, "ProductCategory": "MiscItems" },
{ "ItemType": "/Lotus/Types/Gameplay/Zariman/Resources/ZarimanMiscItemB", "ItemCount": 1, "ProductCategory": "MiscItems" }
],
"Bin": "BIN_1",
"QuantityMultiplier": 1,
"Expiry": { "$date": { "$numberLong": "9999999000000" } },
"PurchaseQuantityLimit": 1,
"AllowMultipurchase": false,
"Id": { "$oid": "6678b612aa3d8ee5c259729c" }
},
{
"StoreItem": "/Lotus/Types/StoreItems/Packages/Tasks/Zariman/AchimedeanTaskA",
"ItemPrices": [
{ "ItemType": "/Lotus/Types/Gameplay/Zariman/Resources/ZarimanMiscItemB", "ItemCount": 1, "ProductCategory": "MiscItems" },
{ "ItemType": "/Lotus/Types/Gameplay/Zariman/Resources/ZarimanMiscItemA", "ItemCount": 2, "ProductCategory": "MiscItems" }
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": { "$date": { "$numberLong": "9999999000000" } },
"PurchaseQuantityLimit": 1,
"AllowMultipurchase": false,
"Id": { "$oid": "6678b612aa3d8ee5c259729d" }
}
],
"PropertyTextHash": "F43F0ED811985EEF856970A8342EF322",
"Expiry": { "$date": { "$numberLong": "9999999000000" } }
}
}

View File

@ -0,0 +1,154 @@
{
"VoidT1": [
"SolNode23",
"SolNode66",
"SolNode45",
"SolNode41",
"SolNode59",
"SolNode39",
"SolNode75",
"SolNode113",
"SolNode85",
"SolNode58",
"SolNode101",
"SolNode109",
"SolNode26",
"SolNode15",
"SolNode61",
"SolNode123",
"SolNode16",
"SolNode79",
"SolNode2",
"SolNode22",
"SolNode68",
"SolNode89",
"SolNode11",
"SolNode46",
"SolNode36",
"SolNode27",
"SolNode14",
"SolNode106",
"SolNode30",
"SolNode107",
"SolNode63",
"SolNode128"
],
"VoidT2": [
"SolNode141",
"SolNode149",
"SolNode10",
"SolNode93",
"SettlementNode11",
"SolNode137",
"SolNode132",
"SolNode73",
"SolNode82",
"SolNode25",
"SolNode88",
"SolNode126",
"SolNode135",
"SolNode74",
"SettlementNode15",
"SolNode147",
"SolNode67",
"SolNode20",
"SolNode42",
"SolNode18",
"SolNode31",
"SolNode139",
"SettlementNode12",
"SolNode100",
"SolNode140",
"SolNode70",
"SettlementNode1",
"SettlementNode14",
"SolNode50",
"SettlementNode2",
"SolNode146",
"SettlementNode3",
"SolNode97",
"SolNode125",
"SolNode19",
"SolNode121",
"SolNode96",
"SolNode131"
],
"VoidT3": [
"SolNode62",
"SolNode17",
"SolNode403",
"SolNode6",
"SolNode118",
"SolNode211",
"SolNode217",
"SolNode401",
"SolNode64",
"SolNode405",
"SolNode84",
"SolNode402",
"SolNode408",
"SolNode122",
"SolNode57",
"SolNode216",
"SolNode205",
"SolNode215",
"SolNode404",
"SolNode209",
"SolNode406",
"SolNode204",
"SolNode203",
"SolNode409",
"SolNode400",
"SolNode212",
"SolNode1",
"SolNode412",
"SolNode49",
"SolNode78",
"SolNode410",
"SolNode407",
"SolNode220"
],
"VoidT4": [
"SolNode188",
"SolNode403",
"SolNode189",
"SolNode21",
"SolNode102",
"SolNode171",
"SolNode196",
"SolNode184",
"SolNode185",
"SolNode76",
"SolNode195",
"SolNode164",
"SolNode401",
"SolNode405",
"SolNode56",
"SolNode402",
"SolNode408",
"SolNode4",
"SolNode181",
"SolNode406",
"SolNode162",
"SolNode72",
"SolNode407",
"SolNode177",
"SolNode404",
"SolNode400",
"SolNode409",
"SolNode43",
"SolNode166",
"SolNode172",
"SolNode412",
"SolNode187",
"SolNode38",
"SolNode175",
"SolNode81",
"SolNode48",
"SolNode410",
"SolNode153",
"SolNode173"
],
"VoidT5": ["SolNode747", "SolNode743", "SolNode742", "SolNode744", "SolNode745", "SolNode748", "SolNode746", "SolNode741"],
"VoidT6": ["SolNode717", "SolNode309", "SolNode718", "SolNode232", "SolNode230", "SolNode310"]
}

View File

@ -327,195 +327,6 @@
"Nodes": [] "Nodes": []
} }
], ],
"ActiveMissions": [
{
"_id": { "$oid": "663a7509d93367863785932d" },
"Region": 15,
"Seed": 80795,
"Activation": { "$date": { "$numberLong": "1715107081517" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode400",
"MissionType": "MT_EXTERMINATION",
"Modifier": "VoidT3",
"Hard": true
},
{
"_id": { "$oid": "663a75f959a5964cadb39879" },
"Region": 19,
"Seed": 32067,
"Activation": { "$date": { "$numberLong": "1715107321237" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode747",
"MissionType": "MT_INTEL",
"Modifier": "VoidT5",
"Hard": true
},
{
"_id": { "$oid": "663a779d3e347839ff301814" },
"Region": 7,
"Seed": 51739,
"Activation": { "$date": { "$numberLong": "1715107741454" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode64",
"MissionType": "MT_TERRITORY",
"Modifier": "VoidT3"
},
{
"_id": { "$oid": "663a77d916c199f4644ee67d" },
"Region": 17,
"Seed": 61179,
"Activation": { "$date": { "$numberLong": "1715107801647" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode718",
"MissionType": "MT_ALCHEMY",
"Modifier": "VoidT6"
},
{
"_id": { "$oid": "663a78c98a609b49b8410726" },
"Region": 3,
"Seed": 9520,
"Activation": { "$date": { "$numberLong": "1715108041501" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode79",
"MissionType": "MT_INTEL",
"Modifier": "VoidT1",
"Hard": true
},
{
"_id": { "$oid": "663a7df15eeabaac79b0a061" },
"Region": 6,
"Seed": 48861,
"Activation": { "$date": { "$numberLong": "1715109361974" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode67",
"MissionType": "MT_INTEL",
"Modifier": "VoidT2",
"Hard": true
},
{
"_id": { "$oid": "663a7df25eeabaac79b0a062" },
"Region": 5,
"Seed": 13550,
"Activation": { "$date": { "$numberLong": "1715109361974" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode10",
"MissionType": "MT_SABOTAGE",
"Modifier": "VoidT2",
"Hard": true
},
{
"_id": { "$oid": "663a83cdec0d5181435f1324" },
"Region": 19,
"Seed": 39392,
"Activation": { "$date": { "$numberLong": "1715110861506" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode742",
"MissionType": "MT_DEFENSE",
"Modifier": "VoidT5"
},
{
"_id": { "$oid": "663a83cdec0d5181435f1325" },
"Region": 19,
"Seed": 88668,
"Activation": { "$date": { "$numberLong": "1715110861506" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode743",
"MissionType": "MT_MOBILE_DEFENSE",
"Modifier": "VoidT5"
},
{
"_id": { "$oid": "663a83cdec0d5181435f1326" },
"Region": 19,
"Seed": 73823,
"Activation": { "$date": { "$numberLong": "1715110861506" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode741",
"MissionType": "MT_ASSAULT",
"Modifier": "VoidT5"
},
{
"_id": { "$oid": "663a878d23d1514873170466" },
"Region": 9,
"Seed": 88696,
"Activation": { "$date": { "$numberLong": "1715111821951" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode4",
"MissionType": "MT_EXTERMINATION",
"Modifier": "VoidT4",
"Hard": true
},
{
"_id": { "$oid": "663a887d4903098c10992fe6" },
"Region": 6,
"Seed": 66337,
"Activation": { "$date": { "$numberLong": "1715112061729" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode18",
"MissionType": "MT_TERRITORY",
"Modifier": "VoidT2"
},
{
"_id": { "$oid": "663a887d4903098c10992fe7" },
"Region": 10,
"Seed": 5135,
"Activation": { "$date": { "$numberLong": "1715112061729" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode149",
"MissionType": "MT_DEFENSE",
"Modifier": "VoidT2"
},
{
"_id": { "$oid": "663a8931586c301b1fbe63d3" },
"Region": 15,
"Seed": 32180,
"Activation": { "$date": { "$numberLong": "1715112241196" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode408",
"MissionType": "MT_DEFENSE",
"Modifier": "VoidT4"
},
{
"_id": { "$oid": "663a8931586c301b1fbe63d4" },
"Region": 12,
"Seed": 22521,
"Activation": { "$date": { "$numberLong": "1715112241196" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode181",
"MissionType": "MT_EXTERMINATION",
"Modifier": "VoidT4"
},
{
"_id": { "$oid": "663a8931586c301b1fbe63d5" },
"Region": 2,
"Seed": 28500,
"Activation": { "$date": { "$numberLong": "1715112241196" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode128",
"MissionType": "MT_EXTERMINATION",
"Modifier": "VoidT1"
},
{
"_id": { "$oid": "663a8931586c301b1fbe63d6" },
"Region": 3,
"Seed": 24747,
"Activation": { "$date": { "$numberLong": "1715112241196" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode26",
"MissionType": "MT_DEFENSE",
"Modifier": "VoidT1"
},
{
"_id": { "$oid": "663a8931586c301b1fbe63d7" },
"Region": 17,
"Seed": 63914,
"Activation": { "$date": { "$numberLong": "1715112241196" } },
"Expiry": { "$date": { "$numberLong": "2000000000000" } },
"Node": "SolNode717",
"MissionType": "MT_SURVIVAL",
"Modifier": "VoidT6",
"Hard": true
}
],
"NodeOverrides": [ "NodeOverrides": [
{ "_id": { "$oid": "549b18e9b029cef5991d6aec" }, "Node": "EuropaHUB", "Hide": true }, { "_id": { "$oid": "549b18e9b029cef5991d6aec" }, "Node": "EuropaHUB", "Hide": true },
{ "_id": { "$oid": "54a1737aeb658f6cbccf70ff" }, "Node": "ErisHUB", "Hide": true }, { "_id": { "$oid": "54a1737aeb658f6cbccf70ff" }, "Node": "ErisHUB", "Hide": true },

View File

@ -604,13 +604,29 @@
<input class="form-check-input" type="checkbox" id="infiniteRegalAya" /> <input class="form-check-input" type="checkbox" id="infiniteRegalAya" />
<label class="form-check-label" for="infiniteRegalAya" data-loc="cheats_infiniteRegalAya"></label> <label class="form-check-label" for="infiniteRegalAya" data-loc="cheats_infiniteRegalAya"></label>
</div> </div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="infiniteHelminthMaterials" />
<label class="form-check-label" for="infiniteHelminthMaterials" data-loc="cheats_infiniteHelminthMaterials"></label>
</div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" id="claimingBlueprintRefundsIngredients" /> <input class="form-check-input" type="checkbox" id="claimingBlueprintRefundsIngredients" />
<label class="form-check-label" for="claimingBlueprintRefundsIngredients" data-loc="cheats_claimingBlueprintRefundsIngredients"></label> <label class="form-check-label" for="claimingBlueprintRefundsIngredients" data-loc="cheats_claimingBlueprintRefundsIngredients"></label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" id="infiniteHelminthMaterials" /> <input class="form-check-input" type="checkbox" id="dontSubtractPurchaseCreditCost" />
<label class="form-check-label" for="infiniteHelminthMaterials" data-loc="cheats_infiniteHelminthMaterials"></label> <label class="form-check-label" for="dontSubtractPurchaseCreditCost" data-loc="cheats_dontSubtractPurchaseCreditCost"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="dontSubtractPurchasePlatinumCost" />
<label class="form-check-label" for="dontSubtractPurchasePlatinumCost" data-loc="cheats_dontSubtractPurchasePlatinumCost"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="dontSubtractPurchaseItemCost" />
<label class="form-check-label" for="dontSubtractPurchaseItemCost" data-loc="cheats_dontSubtractPurchaseItemCost"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="dontSubtractPurchaseStandingCost" />
<label class="form-check-label" for="dontSubtractPurchaseStandingCost" data-loc="cheats_dontSubtractPurchaseStandingCost"></label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" id="dontSubtractVoidTraces" /> <input class="form-check-input" type="checkbox" id="dontSubtractVoidTraces" />
@ -692,6 +708,10 @@
<input class="form-check-input" type="checkbox" id="syndicateMissionsRepeatable" /> <input class="form-check-input" type="checkbox" id="syndicateMissionsRepeatable" />
<label class="form-check-label" for="syndicateMissionsRepeatable" data-loc="cheats_syndicateMissionsRepeatable"></label> <label class="form-check-label" for="syndicateMissionsRepeatable" data-loc="cheats_syndicateMissionsRepeatable"></label>
</div> </div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="unlockAllProfitTakerStages" />
<label class="form-check-label" for="unlockAllProfitTakerStages" data-loc="cheats_unlockAllProfitTakerStages"></label>
</div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" id="instantFinishRivenChallenge" /> <input class="form-check-input" type="checkbox" id="instantFinishRivenChallenge" />
<label class="form-check-label" for="instantFinishRivenChallenge" data-loc="cheats_instantFinishRivenChallenge"></label> <label class="form-check-label" for="instantFinishRivenChallenge" data-loc="cheats_instantFinishRivenChallenge"></label>
@ -732,6 +752,10 @@
<input class="form-check-input" type="checkbox" id="fastClanAscension" /> <input class="form-check-input" type="checkbox" id="fastClanAscension" />
<label class="form-check-label" for="fastClanAscension" data-loc="cheats_fastClanAscension"></label> <label class="form-check-label" for="fastClanAscension" data-loc="cheats_fastClanAscension"></label>
</div> </div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="missionsCanGiveAllRelics" />
<label class="form-check-label" for="missionsCanGiveAllRelics" data-loc="cheats_missionsCanGiveAllRelics"></label>
</div>
<form class="form-group mt-2" onsubmit="doSaveConfig('spoofMasteryRank'); return false;"> <form class="form-group mt-2" onsubmit="doSaveConfig('spoofMasteryRank'); return false;">
<label class="form-label" for="spoofMasteryRank" data-loc="cheats_spoofMasteryRank"></label> <label class="form-label" for="spoofMasteryRank" data-loc="cheats_spoofMasteryRank"></label>
<div class="input-group"> <div class="input-group">

View File

@ -546,6 +546,9 @@ function updateInventory() {
td.textContent = item.ItemName + " (" + td.textContent + ")"; td.textContent = item.ItemName + " (" + td.textContent + ")";
} }
} }
if (item.Details?.Name) {
td.textContent = item.Details.Name + " (" + td.textContent + ")";
}
if (item.ModularParts && item.ModularParts.length) { if (item.ModularParts && item.ModularParts.length) {
td.textContent += " ["; td.textContent += " [";
item.ModularParts.forEach(part => { item.ModularParts.forEach(part => {
@ -1506,6 +1509,18 @@ function sendBatchGearExp(data) {
function renameGear(category, oid, name) { function renameGear(category, oid, name) {
revalidateAuthz(() => { revalidateAuthz(() => {
if (category == "KubrowPets") {
$.post({
url: "/api/renamePet.php?" + window.authz + "&webui=1",
contentType: "text/plain",
data: JSON.stringify({
petId: oid,
name: name
})
}).done(function () {
updateInventory();
});
} else {
$.post({ $.post({
url: "/api/nameWeapon.php?" + window.authz + "&Category=" + category + "&ItemId=" + oid + "&webui=1", url: "/api/nameWeapon.php?" + window.authz + "&Category=" + category + "&ItemId=" + oid + "&webui=1",
contentType: "text/plain", contentType: "text/plain",
@ -1515,6 +1530,7 @@ function renameGear(category, oid, name) {
}).done(function () { }).done(function () {
updateInventory(); updateInventory();
}); });
}
}); });
} }

View File

@ -135,11 +135,15 @@ dict = {
cheats_infiniteRegalAya: `Unendlich Reines Aya`, cheats_infiniteRegalAya: `Unendlich Reines Aya`,
cheats_infiniteHelminthMaterials: `Unendlich Helminth-Materialien`, cheats_infiniteHelminthMaterials: `Unendlich Helminth-Materialien`,
cheats_claimingBlueprintRefundsIngredients: `Fertige Blaupausen erstatten Ressourcen zurück`, cheats_claimingBlueprintRefundsIngredients: `Fertige Blaupausen erstatten Ressourcen zurück`,
cheats_dontSubtractPurchaseCreditCost: `[UNTRANSLATED] Don't Subtract Purchase Credit Cost`,
cheats_dontSubtractPurchasePlatinumCost: `[UNTRANSLATED] Don't Subtract Purchase Platinum Cost`,
cheats_dontSubtractPurchaseItemCost: `[UNTRANSLATED] Don't Subtract Purchase Item Cost`,
cheats_dontSubtractPurchaseStandingCost: `[UNTRANSLATED] Don't Subtract Purchase Standing Cost`,
cheats_dontSubtractVoidTraces: `Void-Spuren nicht verbrauchen`, cheats_dontSubtractVoidTraces: `Void-Spuren nicht verbrauchen`,
cheats_dontSubtractConsumables: `Verbrauchsgegenstände (Ausrüstung) nicht verbrauchen`, cheats_dontSubtractConsumables: `Verbrauchsgegenstände (Ausrüstung) nicht verbrauchen`,
cheats_unlockAllShipFeatures: `Alle Schiffs-Funktionen freischalten`, cheats_unlockAllShipFeatures: `Alle Schiffs-Funktionen freischalten`,
cheats_unlockAllShipDecorations: `Alle Schiffsdekorationen freischalten`, cheats_unlockAllShipDecorations: `Alle Schiffsdekorationen freischalten`,
cheats_unlockAllFlavourItems: `Alle <abbr title=\"Animationssets, Glyphen, Farbpaletten usw.\">Sammlerstücke</abbr> freischalten`, cheats_unlockAllFlavourItems: `Alle <abbr title="Animationssets, Glyphen, Farbpaletten usw.">Sammlerstücke</abbr> freischalten`,
cheats_unlockAllSkins: `Alle Skins freischalten`, cheats_unlockAllSkins: `Alle Skins freischalten`,
cheats_unlockAllCapturaScenes: `Alle Photora-Szenen freischalten`, cheats_unlockAllCapturaScenes: `Alle Photora-Szenen freischalten`,
cheats_unlockAllDecoRecipes: `Alle Dojo-Deko-Baupläne freischalten`, cheats_unlockAllDecoRecipes: `Alle Dojo-Deko-Baupläne freischalten`,
@ -155,6 +159,7 @@ dict = {
cheats_noDeathMarks: `Keine Todesmarkierungen`, cheats_noDeathMarks: `Keine Todesmarkierungen`,
cheats_noKimCooldowns: `Keine Wartezeit bei KIM`, cheats_noKimCooldowns: `Keine Wartezeit bei KIM`,
cheats_syndicateMissionsRepeatable: `Syndikat-Missionen wiederholbar`, cheats_syndicateMissionsRepeatable: `Syndikat-Missionen wiederholbar`,
cheats_unlockAllProfitTakerStages: `[UNTRANSLATED] Unlock All Profit Taker Stages`,
cheats_instantFinishRivenChallenge: `Riven-Mod Herausforderung sofort abschließen`, cheats_instantFinishRivenChallenge: `Riven-Mod Herausforderung sofort abschließen`,
cheats_instantResourceExtractorDrones: `Sofortige Ressourcen-Extraktor-Drohnen`, cheats_instantResourceExtractorDrones: `Sofortige Ressourcen-Extraktor-Drohnen`,
cheats_noResourceExtractorDronesDamage: `Kein Schaden für Ressourcen-Extraktor-Drohnen`, cheats_noResourceExtractorDronesDamage: `Kein Schaden für Ressourcen-Extraktor-Drohnen`,
@ -165,6 +170,7 @@ dict = {
cheats_noDojoResearchCosts: `Keine Dojo-Forschungskosten`, cheats_noDojoResearchCosts: `Keine Dojo-Forschungskosten`,
cheats_noDojoResearchTime: `Keine Dojo-Forschungszeit`, cheats_noDojoResearchTime: `Keine Dojo-Forschungszeit`,
cheats_fastClanAscension: `Schneller Clan-Aufstieg`, cheats_fastClanAscension: `Schneller Clan-Aufstieg`,
cheats_missionsCanGiveAllRelics: `[UNTRANSLATED] Missions Can Give All Relics`,
cheats_spoofMasteryRank: `Gefälschter Meisterschaftsrang (-1 zum deaktivieren)`, cheats_spoofMasteryRank: `Gefälschter Meisterschaftsrang (-1 zum deaktivieren)`,
cheats_nightwaveStandingMultiplier: `[UNTRANSLATED] Nightwave Standing Multiplier`, cheats_nightwaveStandingMultiplier: `[UNTRANSLATED] Nightwave Standing Multiplier`,
cheats_save: `[UNTRANSLATED] Save`, cheats_save: `[UNTRANSLATED] Save`,
@ -185,7 +191,7 @@ dict = {
upgrade_WarframeAbilityDuration: `[UNTRANSLATED] +|VAL|% Ability Duration`, upgrade_WarframeAbilityDuration: `[UNTRANSLATED] +|VAL|% Ability Duration`,
upgrade_WarframeAbilityStrength: `[UNTRANSLATED] +|VAL|% Ability Strength`, upgrade_WarframeAbilityStrength: `[UNTRANSLATED] +|VAL|% Ability Strength`,
upgrade_WarframeArmourMax: `[UNTRANSLATED] +|VAL| Armor`, upgrade_WarframeArmourMax: `[UNTRANSLATED] +|VAL| Armor`,
upgrade_WarframeBlastProc: `[UNTRANSLATED] +|VAL| Shields on inflicting Blast Status`, upgrade_WarframeBlastProc: `[UNTRANSLATED] +|VAL| Shields on kill with Blast Damage`,
upgrade_WarframeCastingSpeed: `[UNTRANSLATED] +|VAL|% Casting Speed`, upgrade_WarframeCastingSpeed: `[UNTRANSLATED] +|VAL|% Casting Speed`,
upgrade_WarframeCorrosiveDamageBoost: `[UNTRANSLATED] +|VAL|% Ability Damage on enemies affected by Corrosion Status`, upgrade_WarframeCorrosiveDamageBoost: `[UNTRANSLATED] +|VAL|% Ability Damage on enemies affected by Corrosion Status`,
upgrade_WarframeCorrosiveStack: `[UNTRANSLATED] Increase max stacks of Corrosion Status by +|VAL|`, upgrade_WarframeCorrosiveStack: `[UNTRANSLATED] Increase max stacks of Corrosion Status by +|VAL|`,

View File

@ -134,11 +134,15 @@ dict = {
cheats_infiniteRegalAya: `Infinite Regal Aya`, cheats_infiniteRegalAya: `Infinite Regal Aya`,
cheats_infiniteHelminthMaterials: `Infinite Helminth Materials`, cheats_infiniteHelminthMaterials: `Infinite Helminth Materials`,
cheats_claimingBlueprintRefundsIngredients: `Claiming Blueprint Refunds Ingredients`, cheats_claimingBlueprintRefundsIngredients: `Claiming Blueprint Refunds Ingredients`,
cheats_dontSubtractPurchaseCreditCost: `Don't Subtract Purchase Credit Cost`,
cheats_dontSubtractPurchasePlatinumCost: `Don't Subtract Purchase Platinum Cost`,
cheats_dontSubtractPurchaseItemCost: `Don't Subtract Purchase Item Cost`,
cheats_dontSubtractPurchaseStandingCost: `Don't Subtract Purchase Standing Cost`,
cheats_dontSubtractVoidTraces: `Don't Subtract Void Traces`, cheats_dontSubtractVoidTraces: `Don't Subtract Void Traces`,
cheats_dontSubtractConsumables: `Don't Subtract Consumables`, cheats_dontSubtractConsumables: `Don't Subtract Consumables`,
cheats_unlockAllShipFeatures: `Unlock All Ship Features`, cheats_unlockAllShipFeatures: `Unlock All Ship Features`,
cheats_unlockAllShipDecorations: `Unlock All Ship Decorations`, cheats_unlockAllShipDecorations: `Unlock All Ship Decorations`,
cheats_unlockAllFlavourItems: `Unlock All <abbr title=\"Animation Sets, Glyphs, Palettes, etc.\">Flavor Items</abbr>`, cheats_unlockAllFlavourItems: `Unlock All <abbr title="Animation Sets, Glyphs, Palettes, etc.">Flavor Items</abbr>`,
cheats_unlockAllSkins: `Unlock All Skins`, cheats_unlockAllSkins: `Unlock All Skins`,
cheats_unlockAllCapturaScenes: `Unlock All Captura Scenes`, cheats_unlockAllCapturaScenes: `Unlock All Captura Scenes`,
cheats_unlockAllDecoRecipes: `Unlock All Dojo Deco Recipes`, cheats_unlockAllDecoRecipes: `Unlock All Dojo Deco Recipes`,
@ -154,6 +158,7 @@ dict = {
cheats_noDeathMarks: `No Death Marks`, cheats_noDeathMarks: `No Death Marks`,
cheats_noKimCooldowns: `No KIM Cooldowns`, cheats_noKimCooldowns: `No KIM Cooldowns`,
cheats_syndicateMissionsRepeatable: `Syndicate Missions Repeatable`, cheats_syndicateMissionsRepeatable: `Syndicate Missions Repeatable`,
cheats_unlockAllProfitTakerStages: `Unlock All Profit Taker Stages`,
cheats_instantFinishRivenChallenge: `Instant Finish Riven Challenge`, cheats_instantFinishRivenChallenge: `Instant Finish Riven Challenge`,
cheats_instantResourceExtractorDrones: `Instant Resource Extractor Drones`, cheats_instantResourceExtractorDrones: `Instant Resource Extractor Drones`,
cheats_noResourceExtractorDronesDamage: `No Resource Extractor Drones Damage`, cheats_noResourceExtractorDronesDamage: `No Resource Extractor Drones Damage`,
@ -164,6 +169,7 @@ dict = {
cheats_noDojoResearchCosts: `No Dojo Research Costs`, cheats_noDojoResearchCosts: `No Dojo Research Costs`,
cheats_noDojoResearchTime: `No Dojo Research Time`, cheats_noDojoResearchTime: `No Dojo Research Time`,
cheats_fastClanAscension: `Fast Clan Ascension`, cheats_fastClanAscension: `Fast Clan Ascension`,
cheats_missionsCanGiveAllRelics: `Missions Can Give All Relics`,
cheats_spoofMasteryRank: `Spoofed Mastery Rank (-1 to disable)`, cheats_spoofMasteryRank: `Spoofed Mastery Rank (-1 to disable)`,
cheats_nightwaveStandingMultiplier: `Nightwave Standing Multiplier`, cheats_nightwaveStandingMultiplier: `Nightwave Standing Multiplier`,
cheats_save: `Save`, cheats_save: `Save`,
@ -184,7 +190,7 @@ dict = {
upgrade_WarframeAbilityDuration: `+|VAL|% Ability Duration`, upgrade_WarframeAbilityDuration: `+|VAL|% Ability Duration`,
upgrade_WarframeAbilityStrength: `+|VAL|% Ability Strength`, upgrade_WarframeAbilityStrength: `+|VAL|% Ability Strength`,
upgrade_WarframeArmourMax: `+|VAL| Armor`, upgrade_WarframeArmourMax: `+|VAL| Armor`,
upgrade_WarframeBlastProc: `+|VAL| Shields on inflicting Blast Status`, upgrade_WarframeBlastProc: `+|VAL| Shields on kill with Blast Damage`,
upgrade_WarframeCastingSpeed: `+|VAL|% Casting Speed`, upgrade_WarframeCastingSpeed: `+|VAL|% Casting Speed`,
upgrade_WarframeCorrosiveDamageBoost: `+|VAL|% Ability Damage on enemies affected by Corrosion Status`, upgrade_WarframeCorrosiveDamageBoost: `+|VAL|% Ability Damage on enemies affected by Corrosion Status`,
upgrade_WarframeCorrosiveStack: `Increase max stacks of Corrosion Status by +|VAL|`, upgrade_WarframeCorrosiveStack: `Increase max stacks of Corrosion Status by +|VAL|`,

View File

@ -135,6 +135,10 @@ dict = {
cheats_infiniteRegalAya: `Aya Real infinita`, cheats_infiniteRegalAya: `Aya Real infinita`,
cheats_infiniteHelminthMaterials: `Materiales Helminto infinitos`, cheats_infiniteHelminthMaterials: `Materiales Helminto infinitos`,
cheats_claimingBlueprintRefundsIngredients: `Reclamar ingredientes devueltos por planos`, cheats_claimingBlueprintRefundsIngredients: `Reclamar ingredientes devueltos por planos`,
cheats_dontSubtractPurchaseCreditCost: `[UNTRANSLATED] Don't Subtract Purchase Credit Cost`,
cheats_dontSubtractPurchasePlatinumCost: `[UNTRANSLATED] Don't Subtract Purchase Platinum Cost`,
cheats_dontSubtractPurchaseItemCost: `[UNTRANSLATED] Don't Subtract Purchase Item Cost`,
cheats_dontSubtractPurchaseStandingCost: `[UNTRANSLATED] Don't Subtract Purchase Standing Cost`,
cheats_dontSubtractVoidTraces: `No descontar vestigios del Vacío`, cheats_dontSubtractVoidTraces: `No descontar vestigios del Vacío`,
cheats_dontSubtractConsumables: `No restar consumibles`, cheats_dontSubtractConsumables: `No restar consumibles`,
cheats_unlockAllShipFeatures: `Desbloquear todas las funciones de nave`, cheats_unlockAllShipFeatures: `Desbloquear todas las funciones de nave`,
@ -155,6 +159,7 @@ dict = {
cheats_noDeathMarks: `Sin marcas de muerte`, cheats_noDeathMarks: `Sin marcas de muerte`,
cheats_noKimCooldowns: `Sin tiempo de espera para conversaciones KIM`, cheats_noKimCooldowns: `Sin tiempo de espera para conversaciones KIM`,
cheats_syndicateMissionsRepeatable: `Misiones de sindicato rejugables`, cheats_syndicateMissionsRepeatable: `Misiones de sindicato rejugables`,
cheats_unlockAllProfitTakerStages: `[UNTRANSLATED] Unlock All Profit Taker Stages`,
cheats_instantFinishRivenChallenge: `Terminar desafío de agrietado inmediatamente`, cheats_instantFinishRivenChallenge: `Terminar desafío de agrietado inmediatamente`,
cheats_instantResourceExtractorDrones: `Drones de extracción de recursos instantáneos`, cheats_instantResourceExtractorDrones: `Drones de extracción de recursos instantáneos`,
cheats_noResourceExtractorDronesDamage: `Sin daño a los drones extractores de recursos`, cheats_noResourceExtractorDronesDamage: `Sin daño a los drones extractores de recursos`,
@ -165,6 +170,7 @@ dict = {
cheats_noDojoResearchCosts: `Sin costo de investigación del dojo`, cheats_noDojoResearchCosts: `Sin costo de investigación del dojo`,
cheats_noDojoResearchTime: `Sin tiempo de investigación del dojo`, cheats_noDojoResearchTime: `Sin tiempo de investigación del dojo`,
cheats_fastClanAscension: `Ascenso rápido del clan`, cheats_fastClanAscension: `Ascenso rápido del clan`,
cheats_missionsCanGiveAllRelics: `[UNTRANSLATED] Missions Can Give All Relics`,
cheats_spoofMasteryRank: `Rango de maestría simulado (-1 para desactivar)`, cheats_spoofMasteryRank: `Rango de maestría simulado (-1 para desactivar)`,
cheats_nightwaveStandingMultiplier: `Multiplicador de Reputación de Onda Nocturna`, cheats_nightwaveStandingMultiplier: `Multiplicador de Reputación de Onda Nocturna`,
cheats_save: `Guardar`, cheats_save: `Guardar`,
@ -185,7 +191,7 @@ dict = {
upgrade_WarframeAbilityDuration: `+|VAL|% de duración de habilidades`, upgrade_WarframeAbilityDuration: `+|VAL|% de duración de habilidades`,
upgrade_WarframeAbilityStrength: `+|VAL|% de fuerza de habilidades`, upgrade_WarframeAbilityStrength: `+|VAL|% de fuerza de habilidades`,
upgrade_WarframeArmourMax: `+|VAL| de armadura`, upgrade_WarframeArmourMax: `+|VAL| de armadura`,
upgrade_WarframeBlastProc: `+|VAL| de escudos al infligir estado de explosión`, upgrade_WarframeBlastProc: `+|VAL| de escudos al matar con daño de explosión`,
upgrade_WarframeCastingSpeed: `+|VAL|% de velocidad de lanzamiento de habilidades`, upgrade_WarframeCastingSpeed: `+|VAL|% de velocidad de lanzamiento de habilidades`,
upgrade_WarframeCorrosiveDamageBoost: `+|VAL|% de daño de habilidades a enemigos con estado corrosivo`, upgrade_WarframeCorrosiveDamageBoost: `+|VAL|% de daño de habilidades a enemigos con estado corrosivo`,
upgrade_WarframeCorrosiveStack: `Aumenta los acumuladores máximos de estado corrosivo en +|VAL|`, upgrade_WarframeCorrosiveStack: `Aumenta los acumuladores máximos de estado corrosivo en +|VAL|`,

View File

@ -135,11 +135,15 @@ dict = {
cheats_infiniteRegalAya: `Aya Raffiné infini`, cheats_infiniteRegalAya: `Aya Raffiné infini`,
cheats_infiniteHelminthMaterials: `Ressources d'Helminth infinies`, cheats_infiniteHelminthMaterials: `Ressources d'Helminth infinies`,
cheats_claimingBlueprintRefundsIngredients: `Récupérer les items rend les ressources`, cheats_claimingBlueprintRefundsIngredients: `Récupérer les items rend les ressources`,
cheats_dontSubtractPurchaseCreditCost: `[UNTRANSLATED] Don't Subtract Purchase Credit Cost`,
cheats_dontSubtractPurchasePlatinumCost: `[UNTRANSLATED] Don't Subtract Purchase Platinum Cost`,
cheats_dontSubtractPurchaseItemCost: `[UNTRANSLATED] Don't Subtract Purchase Item Cost`,
cheats_dontSubtractPurchaseStandingCost: `[UNTRANSLATED] Don't Subtract Purchase Standing Cost`,
cheats_dontSubtractVoidTraces: `Ne pas consommer de Void Traces`, cheats_dontSubtractVoidTraces: `Ne pas consommer de Void Traces`,
cheats_dontSubtractConsumables: `Ne pas retirer de consommables`, cheats_dontSubtractConsumables: `Ne pas retirer de consommables`,
cheats_unlockAllShipFeatures: `Débloquer tous les segments du vaisseau`, cheats_unlockAllShipFeatures: `Débloquer tous les segments du vaisseau`,
cheats_unlockAllShipDecorations: `Débloquer toutes les décorations du vaisseau`, cheats_unlockAllShipDecorations: `Débloquer toutes les décorations du vaisseau`,
cheats_unlockAllFlavourItems: `Débloquer tous les <abbr title=\"Animations, Glyphes, Palettes, etc.\">Flavor Items</abbr>`, cheats_unlockAllFlavourItems: `Débloquer tous les <abbr title="Animations, Glyphes, Palettes, etc.">Flavor Items</abbr>`,
cheats_unlockAllSkins: `Débloquer tous les skins`, cheats_unlockAllSkins: `Débloquer tous les skins`,
cheats_unlockAllCapturaScenes: `Débloquer toutes les scènes captura`, cheats_unlockAllCapturaScenes: `Débloquer toutes les scènes captura`,
cheats_unlockAllDecoRecipes: `Débloquer toutes les recherches dojo`, cheats_unlockAllDecoRecipes: `Débloquer toutes les recherches dojo`,
@ -155,6 +159,7 @@ dict = {
cheats_noDeathMarks: `Aucune marque d'assassin`, cheats_noDeathMarks: `Aucune marque d'assassin`,
cheats_noKimCooldowns: `Aucun cooldown sur le KIM`, cheats_noKimCooldowns: `Aucun cooldown sur le KIM`,
cheats_syndicateMissionsRepeatable: `Mission syndicat répétables`, cheats_syndicateMissionsRepeatable: `Mission syndicat répétables`,
cheats_unlockAllProfitTakerStages: `[UNTRANSLATED] Unlock All Profit Taker Stages`,
cheats_instantFinishRivenChallenge: `Débloquer le challenge Riven instantanément`, cheats_instantFinishRivenChallenge: `Débloquer le challenge Riven instantanément`,
cheats_instantResourceExtractorDrones: `Ressources de drones d'extraction instantannées`, cheats_instantResourceExtractorDrones: `Ressources de drones d'extraction instantannées`,
cheats_noResourceExtractorDronesDamage: `Aucun dégâts aux drones d'extraction de resources`, cheats_noResourceExtractorDronesDamage: `Aucun dégâts aux drones d'extraction de resources`,
@ -165,6 +170,7 @@ dict = {
cheats_noDojoResearchCosts: `Aucun coût de recherche (Dojo)`, cheats_noDojoResearchCosts: `Aucun coût de recherche (Dojo)`,
cheats_noDojoResearchTime: `Aucun temps de recherche (Dojo)`, cheats_noDojoResearchTime: `Aucun temps de recherche (Dojo)`,
cheats_fastClanAscension: `Ascension de clan rapide`, cheats_fastClanAscension: `Ascension de clan rapide`,
cheats_missionsCanGiveAllRelics: `[UNTRANSLATED] Missions Can Give All Relics`,
cheats_spoofMasteryRank: `Rang de maîtrise personnalisé (-1 pour désactiver)`, cheats_spoofMasteryRank: `Rang de maîtrise personnalisé (-1 pour désactiver)`,
cheats_nightwaveStandingMultiplier: `[UNTRANSLATED] Nightwave Standing Multiplier`, cheats_nightwaveStandingMultiplier: `[UNTRANSLATED] Nightwave Standing Multiplier`,
cheats_save: `[UNTRANSLATED] Save`, cheats_save: `[UNTRANSLATED] Save`,
@ -185,7 +191,7 @@ dict = {
upgrade_WarframeAbilityDuration: `[UNTRANSLATED] +|VAL|% Ability Duration`, upgrade_WarframeAbilityDuration: `[UNTRANSLATED] +|VAL|% Ability Duration`,
upgrade_WarframeAbilityStrength: `[UNTRANSLATED] +|VAL|% Ability Strength`, upgrade_WarframeAbilityStrength: `[UNTRANSLATED] +|VAL|% Ability Strength`,
upgrade_WarframeArmourMax: `[UNTRANSLATED] +|VAL| Armor`, upgrade_WarframeArmourMax: `[UNTRANSLATED] +|VAL| Armor`,
upgrade_WarframeBlastProc: `[UNTRANSLATED] +|VAL| Shields on inflicting Blast Status`, upgrade_WarframeBlastProc: `[UNTRANSLATED] +|VAL| Shields on kill with Blast Damage`,
upgrade_WarframeCastingSpeed: `[UNTRANSLATED] +|VAL|% Casting Speed`, upgrade_WarframeCastingSpeed: `[UNTRANSLATED] +|VAL|% Casting Speed`,
upgrade_WarframeCorrosiveDamageBoost: `[UNTRANSLATED] +|VAL|% Ability Damage on enemies affected by Corrosion Status`, upgrade_WarframeCorrosiveDamageBoost: `[UNTRANSLATED] +|VAL|% Ability Damage on enemies affected by Corrosion Status`,
upgrade_WarframeCorrosiveStack: `[UNTRANSLATED] Increase max stacks of Corrosion Status by +|VAL|`, upgrade_WarframeCorrosiveStack: `[UNTRANSLATED] Increase max stacks of Corrosion Status by +|VAL|`,

View File

@ -135,11 +135,15 @@ dict = {
cheats_infiniteRegalAya: `Бесконечная Королевская Айя`, cheats_infiniteRegalAya: `Бесконечная Королевская Айя`,
cheats_infiniteHelminthMaterials: `Бесконечные Выделения Гельминта`, cheats_infiniteHelminthMaterials: `Бесконечные Выделения Гельминта`,
cheats_claimingBlueprintRefundsIngredients: `[UNTRANSLATED] Claiming Blueprint Refunds Ingredients`, cheats_claimingBlueprintRefundsIngredients: `[UNTRANSLATED] Claiming Blueprint Refunds Ingredients`,
cheats_dontSubtractPurchaseCreditCost: `[UNTRANSLATED] Don't Subtract Purchase Credit Cost`,
cheats_dontSubtractPurchasePlatinumCost: `[UNTRANSLATED] Don't Subtract Purchase Platinum Cost`,
cheats_dontSubtractPurchaseItemCost: `[UNTRANSLATED] Don't Subtract Purchase Item Cost`,
cheats_dontSubtractPurchaseStandingCost: `[UNTRANSLATED] Don't Subtract Purchase Standing Cost`,
cheats_dontSubtractVoidTraces: `[UNTRANSLATED] Don't Subtract Void Traces`, cheats_dontSubtractVoidTraces: `[UNTRANSLATED] Don't Subtract Void Traces`,
cheats_dontSubtractConsumables: `Не уменьшать количество расходников`, cheats_dontSubtractConsumables: `Не уменьшать количество расходников`,
cheats_unlockAllShipFeatures: `Разблокировать все функции корабля`, cheats_unlockAllShipFeatures: `Разблокировать все функции корабля`,
cheats_unlockAllShipDecorations: `Разблокировать все украшения корабля`, cheats_unlockAllShipDecorations: `Разблокировать все украшения корабля`,
cheats_unlockAllFlavourItems: `Разблокировать все <abbr title=\"Наборы анимаций, глифы, палитры и т. д.\">уникальные предметы</abbr>`, cheats_unlockAllFlavourItems: `Разблокировать все <abbr title="Наборы анимаций, глифы, палитры и т. д.">уникальные предметы</abbr>`,
cheats_unlockAllSkins: `Разблокировать все скины`, cheats_unlockAllSkins: `Разблокировать все скины`,
cheats_unlockAllCapturaScenes: `Разблокировать все сцены Каптуры`, cheats_unlockAllCapturaScenes: `Разблокировать все сцены Каптуры`,
cheats_unlockAllDecoRecipes: `Разблокировать все рецепты декораций Дoдзё`, cheats_unlockAllDecoRecipes: `Разблокировать все рецепты декораций Дoдзё`,
@ -155,6 +159,7 @@ dict = {
cheats_noDeathMarks: `Без меток сметри`, cheats_noDeathMarks: `Без меток сметри`,
cheats_noKimCooldowns: `Чаты KIM без кулдауна`, cheats_noKimCooldowns: `Чаты KIM без кулдауна`,
cheats_syndicateMissionsRepeatable: `[UNTRANSLATED] Syndicate Missions Repeatable`, cheats_syndicateMissionsRepeatable: `[UNTRANSLATED] Syndicate Missions Repeatable`,
cheats_unlockAllProfitTakerStages: `[UNTRANSLATED] Unlock All Profit Taker Stages`,
cheats_instantFinishRivenChallenge: `[UNTRANSLATED] Instant Finish Riven Challenge`, cheats_instantFinishRivenChallenge: `[UNTRANSLATED] Instant Finish Riven Challenge`,
cheats_instantResourceExtractorDrones: `Мгновенные Экстракторы Ресурсов`, cheats_instantResourceExtractorDrones: `Мгновенные Экстракторы Ресурсов`,
cheats_noResourceExtractorDronesDamage: `Без урона по дронам-сборщикам`, cheats_noResourceExtractorDronesDamage: `Без урона по дронам-сборщикам`,
@ -165,6 +170,7 @@ dict = {
cheats_noDojoResearchCosts: `Бесплатные Исследование Додзё`, cheats_noDojoResearchCosts: `Бесплатные Исследование Додзё`,
cheats_noDojoResearchTime: `Мгновенные Исследование Додзё`, cheats_noDojoResearchTime: `Мгновенные Исследование Додзё`,
cheats_fastClanAscension: `Мгновенное Вознесение Клана`, cheats_fastClanAscension: `Мгновенное Вознесение Клана`,
cheats_missionsCanGiveAllRelics: `[UNTRANSLATED] Missions Can Give All Relics`,
cheats_spoofMasteryRank: `Подделанный ранг мастерства (-1 для отключения)`, cheats_spoofMasteryRank: `Подделанный ранг мастерства (-1 для отключения)`,
cheats_nightwaveStandingMultiplier: `[UNTRANSLATED] Nightwave Standing Multiplier`, cheats_nightwaveStandingMultiplier: `[UNTRANSLATED] Nightwave Standing Multiplier`,
cheats_save: `[UNTRANSLATED] Save`, cheats_save: `[UNTRANSLATED] Save`,
@ -185,7 +191,7 @@ dict = {
upgrade_WarframeAbilityDuration: `[UNTRANSLATED] +|VAL|% Ability Duration`, upgrade_WarframeAbilityDuration: `[UNTRANSLATED] +|VAL|% Ability Duration`,
upgrade_WarframeAbilityStrength: `[UNTRANSLATED] +|VAL|% Ability Strength`, upgrade_WarframeAbilityStrength: `[UNTRANSLATED] +|VAL|% Ability Strength`,
upgrade_WarframeArmourMax: `[UNTRANSLATED] +|VAL| Armor`, upgrade_WarframeArmourMax: `[UNTRANSLATED] +|VAL| Armor`,
upgrade_WarframeBlastProc: `[UNTRANSLATED] +|VAL| Shields on inflicting Blast Status`, upgrade_WarframeBlastProc: `[UNTRANSLATED] +|VAL| Shields on kill with Blast Damage`,
upgrade_WarframeCastingSpeed: `[UNTRANSLATED] +|VAL|% Casting Speed`, upgrade_WarframeCastingSpeed: `[UNTRANSLATED] +|VAL|% Casting Speed`,
upgrade_WarframeCorrosiveDamageBoost: `[UNTRANSLATED] +|VAL|% Ability Damage on enemies affected by Corrosion Status`, upgrade_WarframeCorrosiveDamageBoost: `[UNTRANSLATED] +|VAL|% Ability Damage on enemies affected by Corrosion Status`,
upgrade_WarframeCorrosiveStack: `[UNTRANSLATED] Increase max stacks of Corrosion Status by +|VAL|`, upgrade_WarframeCorrosiveStack: `[UNTRANSLATED] Increase max stacks of Corrosion Status by +|VAL|`,

View File

@ -135,11 +135,15 @@ dict = {
cheats_infiniteRegalAya: `无限御品阿耶`, cheats_infiniteRegalAya: `无限御品阿耶`,
cheats_infiniteHelminthMaterials: `无限Helminth材料`, cheats_infiniteHelminthMaterials: `无限Helminth材料`,
cheats_claimingBlueprintRefundsIngredients: `取消蓝图制造时返还材料`, cheats_claimingBlueprintRefundsIngredients: `取消蓝图制造时返还材料`,
cheats_dontSubtractPurchaseCreditCost: `[UNTRANSLATED] Don't Subtract Purchase Credit Cost`,
cheats_dontSubtractPurchasePlatinumCost: `[UNTRANSLATED] Don't Subtract Purchase Platinum Cost`,
cheats_dontSubtractPurchaseItemCost: `[UNTRANSLATED] Don't Subtract Purchase Item Cost`,
cheats_dontSubtractPurchaseStandingCost: `[UNTRANSLATED] Don't Subtract Purchase Standing Cost`,
cheats_dontSubtractVoidTraces: `虚空光体无消耗`, cheats_dontSubtractVoidTraces: `虚空光体无消耗`,
cheats_dontSubtractConsumables: `消耗物品使用时无损耗`, cheats_dontSubtractConsumables: `消耗物品使用时无损耗`,
cheats_unlockAllShipFeatures: `解锁所有飞船功能`, cheats_unlockAllShipFeatures: `解锁所有飞船功能`,
cheats_unlockAllShipDecorations: `解锁所有飞船装饰`, cheats_unlockAllShipDecorations: `解锁所有飞船装饰`,
cheats_unlockAllFlavourItems: `解锁所有<abbr title=\"动画组合、图标、调色板等\">装饰物品</abbr>`, cheats_unlockAllFlavourItems: `解锁所有<abbr title="动画组合、图标、调色板等">装饰物品</abbr>`,
cheats_unlockAllSkins: `解锁所有外观`, cheats_unlockAllSkins: `解锁所有外观`,
cheats_unlockAllCapturaScenes: `解锁所有Captura场景`, cheats_unlockAllCapturaScenes: `解锁所有Captura场景`,
cheats_unlockAllDecoRecipes: `解锁所有道场配方`, cheats_unlockAllDecoRecipes: `解锁所有道场配方`,
@ -155,6 +159,7 @@ dict = {
cheats_noDeathMarks: `无死亡标记(不会被 Stalker/Grustrag 三霸/Zanuka 猎人等标记)`, cheats_noDeathMarks: `无死亡标记(不会被 Stalker/Grustrag 三霸/Zanuka 猎人等标记)`,
cheats_noKimCooldowns: `无 KIM 冷却时间`, cheats_noKimCooldowns: `无 KIM 冷却时间`,
cheats_syndicateMissionsRepeatable: `集团任务可重复`, cheats_syndicateMissionsRepeatable: `集团任务可重复`,
cheats_unlockAllProfitTakerStages: `[UNTRANSLATED] Unlock All Profit Taker Stages`,
cheats_instantFinishRivenChallenge: `立即完成裂罅挑战`, cheats_instantFinishRivenChallenge: `立即完成裂罅挑战`,
cheats_instantResourceExtractorDrones: `即时资源采集无人机`, cheats_instantResourceExtractorDrones: `即时资源采集无人机`,
cheats_noResourceExtractorDronesDamage: `资源提取器不会损毁`, cheats_noResourceExtractorDronesDamage: `资源提取器不会损毁`,
@ -165,6 +170,7 @@ dict = {
cheats_noDojoResearchCosts: `无视道场研究消耗`, cheats_noDojoResearchCosts: `无视道场研究消耗`,
cheats_noDojoResearchTime: `无视道场研究时间`, cheats_noDojoResearchTime: `无视道场研究时间`,
cheats_fastClanAscension: `快速升级氏族`, cheats_fastClanAscension: `快速升级氏族`,
cheats_missionsCanGiveAllRelics: `[UNTRANSLATED] Missions Can Give All Relics`,
cheats_spoofMasteryRank: `伪造精通段位(-1为禁用)`, cheats_spoofMasteryRank: `伪造精通段位(-1为禁用)`,
cheats_nightwaveStandingMultiplier: `午夜电波声望倍率`, cheats_nightwaveStandingMultiplier: `午夜电波声望倍率`,
cheats_save: `[UNTRANSLATED] Save`, cheats_save: `[UNTRANSLATED] Save`,
@ -185,7 +191,7 @@ dict = {
upgrade_WarframeAbilityDuration: `+|VAL|% 技能持续时间`, upgrade_WarframeAbilityDuration: `+|VAL|% 技能持续时间`,
upgrade_WarframeAbilityStrength: `+|VAL|% 技能强度`, upgrade_WarframeAbilityStrength: `+|VAL|% 技能强度`,
upgrade_WarframeArmourMax: `+|VAL| 护甲`, upgrade_WarframeArmourMax: `+|VAL| 护甲`,
upgrade_WarframeBlastProc: `施加爆炸状态时,护盾 +|VAL|`, upgrade_WarframeBlastProc: `[UNTRANSLATED] +|VAL| Shields on kill with Blast Damage`,
upgrade_WarframeCastingSpeed: `+|VAL|% 施放速度`, upgrade_WarframeCastingSpeed: `+|VAL|% 施放速度`,
upgrade_WarframeCorrosiveDamageBoost: `对受腐蚀状态影响的敌人 +|VAL|% 技能伤害`, upgrade_WarframeCorrosiveDamageBoost: `对受腐蚀状态影响的敌人 +|VAL|% 技能伤害`,
upgrade_WarframeCorrosiveStack: `腐蚀状态最大堆叠数 +|VAL|`, upgrade_WarframeCorrosiveStack: `腐蚀状态最大堆叠数 +|VAL|`,