Compare commits

..

No commits in common. "main" and "main" have entirely different histories.
main ... main

48 changed files with 576 additions and 2925 deletions

View File

@ -13,6 +13,11 @@
"skipTutorial": false,
"skipAllDialogue": false,
"unlockAllScans": false,
"infiniteCredits": false,
"infinitePlatinum": false,
"infiniteEndo": false,
"infiniteRegalAya": false,
"infiniteHelminthMaterials": false,
"claimingBlueprintRefundsIngredients": false,
"dontSubtractPurchaseCreditCost": false,
"dontSubtractPurchasePlatinumCost": false,
@ -66,23 +71,8 @@
"affinityBoost": false,
"resourceBoost": false,
"tennoLiveRelay": false,
"wolfHunt": false,
"longShadow": false,
"hallowedFlame": false,
"hallowedNightmares": false,
"hallowedNightmaresRewardsOverride": 0,
"proxyRebellion": false,
"proxyRebellionRewardsOverride": 0,
"galleonOfGhouls": 0,
"ghoulEmergenceOverride": null,
"plagueStarOverride": null,
"starDaysOverride": null,
"dogDaysOverride": null,
"dogDaysRewardsOverride": null,
"bellyOfTheBeast": false,
"bellyOfTheBeastProgressOverride": 0,
"eightClaw": false,
"eightClawProgressOverride": 0,
"eidolonOverride": "",
"vallisOverride": "",
"duviriOverride": "",

8
package-lock.json generated
View File

@ -23,7 +23,7 @@
"ncp": "^2.0.0",
"typescript": "^5.5",
"undici": "^7.10.0",
"warframe-public-export-plus": "^0.5.80",
"warframe-public-export-plus": "^0.5.78",
"warframe-riven-info": "^0.1.2",
"winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0",
@ -5507,9 +5507,9 @@
}
},
"node_modules/warframe-public-export-plus": {
"version": "0.5.80",
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.80.tgz",
"integrity": "sha512-K5f1Ws3szVdnO0tBcxlNdhXoGHIw09cjHel7spKPGL7aF/vmEkbBGRmYQFvs8n5cGo+v+3qIDMre54Ghb3t0Iw=="
"version": "0.5.78",
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.78.tgz",
"integrity": "sha512-Zvg7N+EdXS8cOAZIxqCbqiqyvQZBgh2xTxEwpHnoyJjNBpm3sP/7dtXmzHaxAZjyaCL4pvi9e7kTvxmpH8Pcag=="
},
"node_modules/warframe-riven-info": {
"version": "0.1.2",

View File

@ -40,7 +40,7 @@
"ncp": "^2.0.0",
"typescript": "^5.5",
"undici": "^7.10.0",
"warframe-public-export-plus": "^0.5.80",
"warframe-public-export-plus": "^0.5.78",
"warframe-riven-info": "^0.1.2",
"winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0",

View File

@ -3,6 +3,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
import { RequestHandler } from "express";
import { IInventoryClient, IUpgradeClient } from "@/src/types/inventoryTypes/inventoryTypes";
import { addMods, getInventory } from "@/src/services/inventoryService";
import { config } from "@/src/services/configService";
export const artifactsController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
@ -33,10 +34,10 @@ export const artifactsController: RequestHandler = async (req, res) => {
addMods(inventory, [{ ItemType, ItemCount: -1 }]);
}
if (!inventory.infiniteCredits) {
if (!config.infiniteCredits) {
inventory.RegularCredits -= Cost;
}
if (!inventory.infiniteEndo) {
if (!config.infiniteEndo) {
inventory.FusionPoints -= FusionPointCost;
}

View File

@ -1,4 +1,5 @@
import { RequestHandler } from "express";
import { config } from "@/src/services/configService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { getInventory } from "@/src/services/inventoryService";
@ -8,7 +9,7 @@ export const creditsController: RequestHandler = async (req, res) => {
getAccountIdForRequest(req),
getInventory(
req.query.accountId as string,
"RegularCredits TradesRemaining PremiumCreditsFree PremiumCredits infiniteCredits infinitePlatinum"
"RegularCredits TradesRemaining PremiumCreditsFree PremiumCredits"
)
])
)[1];
@ -20,10 +21,10 @@ export const creditsController: RequestHandler = async (req, res) => {
PremiumCredits: inventory.PremiumCredits
};
if (inventory.infiniteCredits) {
if (config.infiniteCredits) {
response.RegularCredits = 999999999;
}
if (inventory.infinitePlatinum) {
if (config.infinitePlatinum) {
response.PremiumCreditsFree = 0;
response.PremiumCredits = 999999999;
}

View File

@ -72,7 +72,7 @@ export const dronesController: RequestHandler = async (req, res) => {
);
}
} else {
drone.ResourceCount = droneMeta.binCapacity * droneMeta.capacityMultipliers[resource.Rarity];
drone.ResourceCount = 1;
}
await inventory.save();
res.json({});

View File

@ -1,25 +0,0 @@
import { RequestHandler } from "express";
import { getAccountForRequest } from "@/src/services/loginService";
import { getInventory } from "@/src/services/inventoryService";
import { Guild } from "@/src/models/guildModel";
export const getGuildEventScoreController: RequestHandler = async (req, res) => {
const account = await getAccountForRequest(req);
const inventory = await getInventory(account._id.toString(), "GuildId");
const guild = await Guild.findById(inventory.GuildId);
const goalId = req.query.goalId as string;
if (guild && guild.GoalProgress && goalId) {
const goal = guild.GoalProgress.find(x => x.goalId.toString() == goalId);
if (goal) {
return res.json({
Tier: guild.Tier,
GoalProgress: {
Count: goal.Count,
Tag: goal.Tag,
_id: { $oid: goal.goalId }
}
});
}
}
return res.json({});
};

View File

@ -1,62 +0,0 @@
import { RequestHandler } from "express";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { getInventory } from "@/src/services/inventoryService";
import { EPOCH, getSeasonChallengePools, getWorldState, pushWeeklyActs } from "@/src/services/worldStateService";
import { unixTimesInMs } from "@/src/constants/timeConstants";
import { ISeasonChallenge } from "@/src/types/worldStateTypes";
import { ExportChallenges } from "warframe-public-export-plus";
export const getPastWeeklyChallengesController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const inventory = await getInventory(accountId, "SeasonChallengeHistory ChallengeProgress");
const worldState = getWorldState(undefined);
if (worldState.SeasonInfo) {
const pools = getSeasonChallengePools(worldState.SeasonInfo.AffiliationTag);
const nightwaveStartTimestamp = Number(worldState.SeasonInfo.Activation.$date.$numberLong);
const nightwaveSeason = worldState.SeasonInfo.Season;
const timeMs = worldState.Time * 1000;
const completedChallengesIds = new Set<string>();
inventory.SeasonChallengeHistory.forEach(challengeHistory => {
const entryNightwaveSeason = parseInt(challengeHistory.id.slice(0, 4), 10) - 1;
if (nightwaveSeason == entryNightwaveSeason) {
const meta = Object.entries(ExportChallenges).find(
([key]) => key.split("/").pop() === challengeHistory.challenge
);
if (meta) {
const [, challengeMeta] = meta;
const challengeProgress = inventory.ChallengeProgress.find(
c => c.Name === challengeHistory.challenge
);
if (challengeProgress && challengeProgress.Progress >= (challengeMeta.requiredCount ?? 1)) {
completedChallengesIds.add(challengeHistory.id);
}
}
}
});
const PastWeeklyChallenges: ISeasonChallenge[] = [];
let week = Math.trunc((timeMs - EPOCH) / unixTimesInMs.week) - 1;
while (EPOCH + week * unixTimesInMs.week >= nightwaveStartTimestamp && PastWeeklyChallenges.length < 3) {
const tempActs: ISeasonChallenge[] = [];
pushWeeklyActs(tempActs, pools, week, nightwaveStartTimestamp, nightwaveSeason);
for (const act of tempActs) {
if (!completedChallengesIds.has(act._id.$oid) && PastWeeklyChallenges.length < 3) {
if (act.Challenge.startsWith("/Lotus/Types/Challenges/Seasons/Weekly/SeasonWeeklyPermanent")) {
act.Permanent = true;
}
PastWeeklyChallenges.push(act);
}
}
week--;
}
res.json({ PastWeeklyChallenges: PastWeeklyChallenges });
}
};

View File

@ -12,7 +12,7 @@ export const hubBlessingController: RequestHandler = async (req, res) => {
if (req.query.mode == "send") {
const inventory = await getInventory(accountId, "BlessingCooldown Boosters");
inventory.BlessingCooldown = new Date(Date.now() + 86400000);
addBooster(boosterType, 3 * 3600, inventory); // unfaithful, but current HUB server does not handle broadcasting, so this way users can bless themselves.
addBooster(boosterType, 3 * 3600, inventory);
await inventory.save();
let token = "";

View File

@ -13,8 +13,7 @@ import {
addItems,
combineInventoryChanges,
getEffectiveAvatarImageType,
getInventory,
updateCurrency
getInventory
} from "@/src/services/inventoryService";
import { logger } from "@/src/utils/logger";
import { ExportFlavour } from "warframe-public-export-plus";
@ -101,9 +100,6 @@ export const inboxController: RequestHandler = async (req, res) => {
}
}
}
if (message.RegularCredits) {
updateCurrency(inventory, -message.RegularCredits, false, inventoryChanges);
}
await inventory.save();
res.json({ InventoryChanges: inventoryChanges });
} else if (latestClientMessageId) {

View File

@ -15,6 +15,7 @@ import { getRecipe } from "@/src/services/itemDataService";
import { toMongoDate, version_compare } from "@/src/helpers/inventoryHelpers";
import { logger } from "@/src/utils/logger";
import { colorToShard } from "@/src/helpers/shardHelper";
import { config } from "@/src/services/configService";
import {
addInfestedFoundryXP,
applyCheatsToInfestedFoundry,
@ -72,7 +73,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
addMiscItems(inventory, miscItemChanges);
// consume resources
if (!inventory.infiniteHelminthMaterials) {
if (!config.infiniteHelminthMaterials) {
let type: string;
let count: number;
if (account.BuildLabel && version_compare(account.BuildLabel, "2025.05.20.10.18") < 0) {
@ -98,7 +99,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
await inventory.save();
const infestedFoundry = inventory.toJSON<IInventoryClient>().InfestedFoundry!;
applyCheatsToInfestedFoundry(inventory, infestedFoundry);
applyCheatsToInfestedFoundry(infestedFoundry);
res.json({
InventoryChanges: {
MiscItems: miscItemChanges,
@ -128,14 +129,13 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
case "c": {
// consume items
const inventory = await getInventory(account._id.toString());
if (inventory.infiniteHelminthMaterials) {
if (config.infiniteHelminthMaterials) {
res.status(400).end();
return;
}
const request = getJSONfromString<IHelminthFeedRequest>(String(req.body));
const inventory = await getInventory(account._id.toString());
inventory.InfestedFoundry ??= {};
inventory.InfestedFoundry.Resources ??= [];
@ -240,7 +240,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
}
await inventory.save();
const infestedFoundry = inventory.toJSON<IInventoryClient>().InfestedFoundry!;
applyCheatsToInfestedFoundry(inventory, infestedFoundry);
applyCheatsToInfestedFoundry(infestedFoundry);
res.json({
InventoryChanges: {
InfestedFoundry: infestedFoundry
@ -254,7 +254,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
const request = getJSONfromString<IHelminthSubsumeRequest>(String(req.body));
const inventory = await getInventory(account._id.toString());
const recipe = getRecipe(request.Recipe)!;
if (!inventory.infiniteHelminthMaterials) {
if (!config.infiniteHelminthMaterials) {
for (const ingredient of recipe.secretIngredients!) {
const resource = inventory.InfestedFoundry!.Resources!.find(x => x.ItemType == ingredient.ItemType);
if (resource) {
@ -280,7 +280,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
freeUpSlot(inventory, InventorySlot.SUITS);
await inventory.save();
const infestedFoundry = inventory.toJSON<IInventoryClient>().InfestedFoundry!;
applyCheatsToInfestedFoundry(inventory, infestedFoundry);
applyCheatsToInfestedFoundry(infestedFoundry);
res.json({
InventoryChanges: {
Recipes: recipeChanges,
@ -307,7 +307,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
const recipeChanges = handleSubsumeCompletion(inventory);
await inventory.save();
const infestedFoundry = inventory.toJSON<IInventoryClient>().InfestedFoundry!;
applyCheatsToInfestedFoundry(inventory, infestedFoundry);
applyCheatsToInfestedFoundry(infestedFoundry);
res.json({
InventoryChanges: {
...currencyChanges,
@ -328,7 +328,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
suit.UpgradesExpiry = upgradesExpiry;
const recipeChanges = addInfestedFoundryXP(inventory.InfestedFoundry!, 4800_00);
addRecipes(inventory, recipeChanges);
if (!inventory.infiniteHelminthMaterials) {
if (!config.infiniteHelminthMaterials) {
for (let i = 0; i != request.ResourceTypes.length; ++i) {
inventory.InfestedFoundry!.Resources!.find(x => x.ItemType == request.ResourceTypes[i])!.Count -=
request.ResourceCosts[i];
@ -338,7 +338,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
inventory.InfestedFoundry!.InvigorationsApplied += 1;
await inventory.save();
const infestedFoundry = inventory.toJSON<IInventoryClient>().InfestedFoundry!;
applyCheatsToInfestedFoundry(inventory, infestedFoundry);
applyCheatsToInfestedFoundry(infestedFoundry);
res.json({
SuitId: request.SuitId,
OffensiveUpgrade: request.OffensiveUpgradeType,

View File

@ -295,17 +295,17 @@ export const getInventoryResponse = async (
};
}
if (inventory.infiniteCredits) {
if (config.infiniteCredits) {
inventoryResponse.RegularCredits = 999999999;
}
if (inventory.infinitePlatinum) {
if (config.infinitePlatinum) {
inventoryResponse.PremiumCreditsFree = 0;
inventoryResponse.PremiumCredits = 999999999;
}
if (inventory.infiniteEndo) {
if (config.infiniteEndo) {
inventoryResponse.FusionPoints = 999999999;
}
if (inventory.infiniteRegalAya) {
if (config.infiniteRegalAya) {
inventoryResponse.PrimeTokens = 999999999;
}
@ -450,7 +450,7 @@ export const getInventoryResponse = async (
}
if (inventoryResponse.InfestedFoundry) {
applyCheatsToInfestedFoundry(inventory, inventoryResponse.InfestedFoundry);
applyCheatsToInfestedFoundry(inventoryResponse.InfestedFoundry);
}
// Set 2FA enabled so trading post can be used

View File

@ -6,11 +6,7 @@ import { addMissionInventoryUpdates, addMissionRewards } from "@/src/services/mi
import { getInventory } from "@/src/services/inventoryService";
import { getInventoryResponse } from "@/src/controllers/api/inventoryController";
import { logger } from "@/src/utils/logger";
import {
IMissionInventoryUpdateResponse,
IMissionInventoryUpdateResponseBackToDryDock,
IMissionInventoryUpdateResponseRailjackInterstitial
} from "@/src/types/missionTypes";
import { IMissionInventoryUpdateResponse } from "@/src/types/missionTypes";
import { sendWsBroadcastTo } from "@/src/services/wsService";
import { generateRewardSeed } from "@/src/services/rngService";
@ -99,9 +95,11 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
inventory.RewardSeed = generateRewardSeed();
}
await inventory.save();
const inventoryResponse = await getInventoryResponse(inventory, true, account.BuildLabel);
//TODO: figure out when to send inventory. it is needed for many cases.
const deltas: IMissionInventoryUpdateResponseRailjackInterstitial = {
res.json({
InventoryJson: JSON.stringify(inventoryResponse),
InventoryChanges: inventoryChanges,
MissionRewards,
...credits,
@ -110,25 +108,7 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
SyndicateXPItemReward,
AffiliationMods,
ConquestCompletedMissionsCount
};
if (missionReport.RJ) {
logger.debug(`railjack interstitial request, sending only deltas`, deltas);
res.json(deltas);
} else if (missionReport.RewardInfo) {
logger.debug(`classic mission completion, sending everything`);
const inventoryResponse = await getInventoryResponse(inventory, true, account.BuildLabel);
res.json({
InventoryJson: JSON.stringify(inventoryResponse),
...deltas
} satisfies IMissionInventoryUpdateResponse);
} else {
logger.debug(`no reward info, assuming this wasn't a mission completion and we should just sync inventory`);
const inventoryResponse = await getInventoryResponse(inventory, true, account.BuildLabel);
res.json({
InventoryJson: JSON.stringify(inventoryResponse)
} satisfies IMissionInventoryUpdateResponseBackToDryDock);
}
} satisfies IMissionInventoryUpdateResponse);
sendWsBroadcastTo(account._id.toString(), { update_inventory: true });
};

View File

@ -7,6 +7,7 @@ import { addMiscItems, addRecipes, getInventory, updateCurrency } from "@/src/se
import { getRecipeByResult } from "@/src/services/itemDataService";
import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { addInfestedFoundryXP, applyCheatsToInfestedFoundry } from "@/src/services/infestedFoundryService";
import { config } from "@/src/services/configService";
import { sendWsBroadcastTo } from "@/src/services/wsService";
import { EquipmentFeatures, IEquipmentDatabase } from "@/src/types/equipmentTypes";
@ -51,7 +52,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
const recipe = getRecipeByResult(operation.UpgradeRequirement)!;
for (const ingredient of recipe.ingredients) {
totalPercentagePointsConsumed += ingredient.ItemCount / 10;
if (!inventory.infiniteHelminthMaterials) {
if (!config.infiniteHelminthMaterials) {
inventory.InfestedFoundry!.Resources!.find(x => x.ItemType == ingredient.ItemType)!.Count -=
ingredient.ItemCount;
}
@ -68,7 +69,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
inventoryChanges.Recipes = recipeChanges;
inventoryChanges.InfestedFoundry = inventory.toJSON<IInventoryClient>().InfestedFoundry;
applyCheatsToInfestedFoundry(inventory, inventoryChanges.InfestedFoundry!);
applyCheatsToInfestedFoundry(inventoryChanges.InfestedFoundry!);
} else
switch (operation.UpgradeRequirement) {
case "/Lotus/Types/Items/MiscItems/OrokinReactor":

View File

@ -153,21 +153,18 @@ const getItemListsController: RequestHandler = (req, response) => {
}
for (const [uniqueName, item] of Object.entries(ExportWeapons)) {
if (item.partType) {
if (!uniqueName.split("/")[7]?.startsWith("PvPVariant")) {
// not a pvp variant
if (!uniqueName.startsWith("/Lotus/Types/Items/Deimos/")) {
res.ModularParts.push({
uniqueName,
name: getString(item.name, lang),
partType: item.partType
});
}
if (uniqueName.split("/")[5] != "SentTrainingAmplifier") {
res.miscitems.push({
uniqueName: uniqueName,
name: getString(item.name, lang)
});
}
if (!uniqueName.startsWith("/Lotus/Types/Items/Deimos/")) {
res.ModularParts.push({
uniqueName,
name: getString(item.name, lang),
partType: item.partType
});
}
if (uniqueName.split("/")[5] != "SentTrainingAmplifier") {
res.miscitems.push({
uniqueName: uniqueName,
name: getString(item.name, lang)
});
}
} else if (item.totalDamage !== 0) {
if (

View File

@ -1,10 +1,8 @@
import { importInventory, importLoadOutPresets, importPersonalRooms } from "@/src/services/importService";
import { importInventory, importLoadOutPresets } from "@/src/services/importService";
import { getInventory } from "@/src/services/inventoryService";
import { getLoadout } from "@/src/services/loadoutService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { getPersonalRooms } from "@/src/services/personalRoomsService";
import { IInventoryClient } from "@/src/types/inventoryTypes/inventoryTypes";
import { IGetShipResponse } from "@/src/types/personalRoomsTypes";
import { RequestHandler } from "express";
export const importController: RequestHandler = async (req, res) => {
@ -15,21 +13,15 @@ export const importController: RequestHandler = async (req, res) => {
importInventory(inventory, request.inventory);
await inventory.save();
if ("LoadOutPresets" in request.inventory && request.inventory.LoadOutPresets) {
if (request.inventory.LoadOutPresets) {
const loadout = await getLoadout(accountId);
importLoadOutPresets(loadout, request.inventory.LoadOutPresets);
await loadout.save();
}
if ("Ship" in request.inventory || "Apartment" in request.inventory || "TailorShop" in request.inventory) {
const personalRooms = await getPersonalRooms(accountId);
importPersonalRooms(personalRooms, request.inventory);
await personalRooms.save();
}
res.end();
};
interface IImportRequest {
inventory: Partial<IInventoryClient> | Partial<IGetShipResponse>;
inventory: Partial<IInventoryClient>;
}

View File

@ -1,18 +0,0 @@
import { getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { IAccountCheats } from "@/src/types/inventoryTypes/inventoryTypes";
import { RequestHandler } from "express";
export const setAccountCheatController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const payload = req.body as ISetAccountCheatRequest;
const inventory = await getInventory(accountId, payload.key);
inventory[payload.key] = payload.value;
await inventory.save();
res.end();
};
interface ISetAccountCheatRequest {
key: keyof IAccountCheats;
value: boolean;
}

View File

@ -22,11 +22,8 @@ export interface INemesisManifest {
ephemeraTypes?: Record<TInnateDamageTag, string>;
firstKillReward: string;
firstConvertReward: string;
killMessageSubject: string;
killMessageBody: string;
convertMessageSubject: string;
convertMessageBody: string;
convertMessageIcon: string;
messageTitle: string;
messageBody: string;
minBuild: string;
}
@ -60,11 +57,8 @@ class KuvaLichManifest implements INemesisManifest {
};
firstKillReward = "/Lotus/StoreItems/Upgrades/Skins/Clan/LichKillerBadgeItem";
firstConvertReward = "/Lotus/StoreItems/Upgrades/Skins/Sigils/KuvaLichSigil";
killMessageSubject = "/Lotus/Language/Inbox/VanquishKuvaMsgTitle";
killMessageBody = "/Lotus/Language/Inbox/VanquishLichMsgBody";
convertMessageSubject = "/Lotus/Language/Kingpins/InboxKuvaConvertedSubject";
convertMessageBody = "/Lotus/Language/Kingpins/InboxKuvaConvertedBody";
convertMessageIcon = "/Lotus/Interface/Graphics/WorldStatePanel/Grineer.png";
messageTitle = "/Lotus/Language/Inbox/VanquishKuvaMsgTitle";
messageBody = "/Lotus/Language/Inbox/VanquishLichMsgBody";
minBuild = "2019.10.31.22.42"; // 26.0.0
}
@ -137,11 +131,8 @@ class LawyerManifest implements INemesisManifest {
};
firstKillReward = "/Lotus/StoreItems/Upgrades/Skins/Clan/CorpusLichBadgeItem";
firstConvertReward = "/Lotus/StoreItems/Upgrades/Skins/Sigils/CorpusLichSigil";
killMessageSubject = "/Lotus/Language/Inbox/VanquishLawyerMsgTitle";
killMessageBody = "/Lotus/Language/Inbox/VanquishLichMsgBody";
convertMessageSubject = "/Lotus/Language/Kingpins/InboxSisterConvertedSubject";
convertMessageBody = "/Lotus/Language/Kingpins/InboxSisterConvertedBody";
convertMessageIcon = "/Lotus/Interface/Graphics/WorldStatePanel/Corpus.png";
messageTitle = "/Lotus/Language/Inbox/VanquishLawyerMsgTitle";
messageBody = "/Lotus/Language/Inbox/VanquishLichMsgBody";
minBuild = "2021.07.05.17.03"; // 30.5.0
}
@ -175,11 +166,8 @@ class InfestedLichManfest implements INemesisManifest {
ephemeraChance = 0;
firstKillReward = "/Lotus/StoreItems/Upgrades/Skins/Sigils/InfLichVanquishedSigil";
firstConvertReward = "/Lotus/StoreItems/Upgrades/Skins/Sigils/InfLichConvertedSigil";
killMessageSubject = "/Lotus/Language/Inbox/VanquishBandMsgTitle";
killMessageBody = "/Lotus/Language/Inbox/VanquishBandMsgBody";
convertMessageSubject = "/Lotus/Language/Kingpins/InboxBandConvertedSubject";
convertMessageBody = "/Lotus/Language/Kingpins/InboxBandConvertedBody";
convertMessageIcon = "/Lotus/Interface/Graphics/WorldStatePanel/Infested.png";
messageTitle = "/Lotus/Language/Inbox/VanquishBandMsgTitle";
messageBody = "/Lotus/Language/Inbox/VanquishBandMsgBody";
minBuild = "2025.03.18.09.51"; // 38.5.0
}

View File

@ -1,17 +1,5 @@
import { SlotPurchase, SlotPurchaseName } from "@/src/types/purchaseTypes";
export const slotPurchaseNameToSlotName: SlotPurchase = {
SuitSlotItem: { name: "SuitBin", purchaseQuantity: 1 },
TwoSentinelSlotItem: { name: "SentinelBin", purchaseQuantity: 2 },
TwoWeaponSlotItem: { name: "WeaponBin", purchaseQuantity: 2 },
SpaceSuitSlotItem: { name: "SpaceSuitBin", purchaseQuantity: 1 },
TwoSpaceWeaponSlotItem: { name: "SpaceWeaponBin", purchaseQuantity: 2 },
MechSlotItem: { name: "MechBin", purchaseQuantity: 1 },
TwoOperatorWeaponSlotItem: { name: "OperatorAmpBin", purchaseQuantity: 2 },
RandomModSlotItem: { name: "RandomModBin", purchaseQuantity: 3 },
TwoCrewShipSalvageSlotItem: { name: "CrewShipSalvageBin", purchaseQuantity: 2 },
CrewMemberSlotItem: { name: "CrewMemberBin", purchaseQuantity: 1 }
};
import { slotPurchaseNameToSlotName } from "@/src/services/purchaseService";
import { SlotPurchaseName } from "@/src/types/purchaseTypes";
export const isSlotPurchaseName = (slotPurchaseName: string): slotPurchaseName is SlotPurchaseName => {
return slotPurchaseName in slotPurchaseNameToSlotName;

View File

@ -19,8 +19,6 @@ import {
import { Document, Model, model, Schema, Types } from "mongoose";
import { fusionTreasuresSchema, typeCountSchema } from "@/src/models/inventoryModels/inventoryModel";
import { pictureFrameInfoSchema } from "@/src/models/personalRoomsModel";
import { IGoalProgressClient, IGoalProgressDatabase } from "@/src/types/inventoryTypes/inventoryTypes";
import { toOid } from "@/src/helpers/inventoryHelpers";
const dojoDecoSchema = new Schema<IDojoDecoDatabase>({
Type: String,
@ -176,28 +174,6 @@ const guildLogEntryNumberSchema = new Schema<IGuildLogEntryNumber>(
{ _id: false }
);
const goalProgressSchema = new Schema<IGoalProgressDatabase>(
{
Count: Number,
Tag: String,
goalId: Types.ObjectId
},
{ _id: false }
);
goalProgressSchema.set("toJSON", {
virtuals: true,
transform(_doc, obj: Record<string, any>) {
const db = obj as IGoalProgressDatabase;
const client = obj as IGoalProgressClient;
client._id = toOid(db.goalId);
delete obj.goalId;
delete obj.__v;
}
});
const guildSchema = new Schema<IGuildDatabase>(
{
Name: { type: String, required: true, unique: true },
@ -230,8 +206,7 @@ const guildSchema = new Schema<IGuildDatabase>(
RoomChanges: { type: [guildLogRoomChangeSchema], default: undefined },
TechChanges: { type: [guildLogEntryContributableSchema], default: undefined },
RosterActivity: { type: [guildLogEntryRosterSchema], default: undefined },
ClassChanges: { type: [guildLogEntryNumberSchema], default: undefined },
GoalProgress: { type: [goalProgressSchema], default: undefined }
ClassChanges: { type: [guildLogEntryNumberSchema], default: undefined }
},
{ id: false }
);

View File

@ -47,7 +47,6 @@ export interface IMessage {
acceptAction?: string;
declineAction?: string;
hasAccountAction?: boolean;
RegularCredits?: number;
}
export interface Arg {
@ -140,8 +139,7 @@ const messageSchema = new Schema<IMessageDatabase>(
contextInfo: String,
acceptAction: String,
declineAction: String,
hasAccountAction: Boolean,
RegularCredits: Number
hasAccountAction: Boolean
},
{ id: false }
);

View File

@ -85,8 +85,8 @@ import {
IAccolades,
IHubNpcCustomization,
IEndlessXpReward,
IGoalProgressDatabase,
IGoalProgressClient,
IPersonalGoalProgressDatabase,
IPersonalGoalProgressClient,
IKubrowPetPrintClient,
IKubrowPetPrintDatabase
} from "@/src/types/inventoryTypes/inventoryTypes";
@ -445,7 +445,7 @@ const discoveredMarkerSchema = new Schema<IDiscoveredMarker>(
{ _id: false }
);
const personalGoalProgressSchema = new Schema<IGoalProgressDatabase>(
const personalGoalProgressSchema = new Schema<IPersonalGoalProgressDatabase>(
{
Best: Number,
Count: Number,
@ -458,8 +458,8 @@ const personalGoalProgressSchema = new Schema<IGoalProgressDatabase>(
personalGoalProgressSchema.set("toJSON", {
virtuals: true,
transform(_doc, obj: Record<string, any>) {
const db = obj as IGoalProgressDatabase;
const client = obj as IGoalProgressClient;
const db = obj as IPersonalGoalProgressDatabase;
const client = obj as IPersonalGoalProgressClient;
client._id = toOid(db.goalId);
@ -1425,14 +1425,6 @@ const hubNpcCustomizationSchema = new Schema<IHubNpcCustomization>(
const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
{
accountOwnerId: Schema.Types.ObjectId,
// SNS account cheats
infiniteCredits: Boolean,
infinitePlatinum: Boolean,
infiniteEndo: Boolean,
infiniteRegalAya: Boolean,
infiniteHelminthMaterials: Boolean,
SubscribedToEmails: { type: Number, default: 0 },
SubscribedToEmailsPersonalized: { type: Number, default: 0 },
RewardSeed: BigInt,

View File

@ -62,12 +62,10 @@ import { getFriendsController } from "@/src/controllers/api/getFriendsController
import { getGuildContributionsController } from "@/src/controllers/api/getGuildContributionsController";
import { getGuildController } from "@/src/controllers/api/getGuildController";
import { getGuildDojoController } from "@/src/controllers/api/getGuildDojoController";
import { getGuildEventScoreController } from "@/src/controllers/api/getGuildEventScore";
import { getGuildLogController } from "@/src/controllers/api/getGuildLogController";
import { getIgnoredUsersController } from "@/src/controllers/api/getIgnoredUsersController";
import { getNewRewardSeedController } from "@/src/controllers/api/getNewRewardSeedController";
import { getProfileViewingDataPostController } from "@/src/controllers/dynamic/getProfileViewingDataController";
import { getPastWeeklyChallengesController } from "@/src/controllers/api/getPastWeeklyChallengesController";
import { getShipController } from "@/src/controllers/api/getShipController";
import { getVendorInfoController } from "@/src/controllers/api/getVendorInfoController";
import { getVoidProjectionRewardsController } from "@/src/controllers/api/getVoidProjectionRewardsController";
@ -193,12 +191,10 @@ apiRouter.get("/getFriends.php", getFriendsController);
apiRouter.get("/getGuild.php", getGuildController);
apiRouter.get("/getGuildContributions.php", getGuildContributionsController);
apiRouter.get("/getGuildDojo.php", getGuildDojoController);
apiRouter.get("/getGuildEventScore.php", getGuildEventScoreController);
apiRouter.get("/getGuildLog.php", getGuildLogController);
apiRouter.get("/getIgnoredUsers.php", getIgnoredUsersController);
apiRouter.get("/getMessages.php", inboxController); // unsure if this is correct, but needed for U17
apiRouter.get("/getNewRewardSeed.php", getNewRewardSeedController);
apiRouter.get("/getPastWeeklyChallenges.php", getPastWeeklyChallengesController)
apiRouter.get("/getShip.php", getShipController);
apiRouter.get("/getShipDecos.php", (_req, res) => { res.end(); }); // needed to log in on U22.8
apiRouter.get("/getVendorInfo.php", getVendorInfoController);

View File

@ -28,7 +28,6 @@ import { setBoosterController } from "@/src/controllers/custom/setBoosterControl
import { updateFingerprintController } from "@/src/controllers/custom/updateFingerprintController";
import { changeModularPartsController } from "@/src/controllers/custom/changeModularPartsController";
import { editSuitInvigorationUpgradeController } from "@/src/controllers/custom/editSuitInvigorationUpgradeController";
import { setAccountCheatController } from "@/src/controllers/custom/setAccountCheatController";
import { getConfigController, setConfigController } from "@/src/controllers/custom/configController";
@ -62,7 +61,6 @@ customRouter.post("/setBooster", setBoosterController);
customRouter.post("/updateFingerprint", updateFingerprintController);
customRouter.post("/changeModularParts", changeModularPartsController);
customRouter.post("/editSuitInvigorationUpgrade", editSuitInvigorationUpgradeController);
customRouter.post("/setAccountCheat", setAccountCheatController);
customRouter.post("/getConfig", getConfigController);
customRouter.post("/setConfig", setConfigController);

View File

@ -20,6 +20,11 @@ export interface IConfig {
skipTutorial?: boolean;
skipAllDialogue?: boolean;
unlockAllScans?: boolean;
infiniteCredits?: boolean;
infinitePlatinum?: boolean;
infiniteEndo?: boolean;
infiniteRegalAya?: boolean;
infiniteHelminthMaterials?: boolean;
claimingBlueprintRefundsIngredients?: boolean;
dontSubtractPurchaseCreditCost?: boolean;
dontSubtractPurchasePlatinumCost?: boolean;
@ -78,23 +83,8 @@ export interface IConfig {
resourceBoost?: boolean;
tennoLiveRelay?: boolean;
baroTennoConRelay?: boolean;
wolfHunt?: boolean;
longShadow?: boolean;
hallowedFlame?: boolean;
hallowedNightmares?: boolean;
hallowedNightmaresRewardsOverride?: number;
proxyRebellion?: boolean;
proxyRebellionRewardsOverride?: number;
galleonOfGhouls?: number;
ghoulEmergenceOverride?: boolean;
plagueStarOverride?: boolean;
starDaysOverride?: boolean;
dogDaysOverride?: boolean;
dogDaysRewardsOverride?: number;
bellyOfTheBeast?: boolean;
bellyOfTheBeastProgressOverride?: number;
eightClaw?: boolean;
eightClawProgressOverride?: number;
eidolonOverride?: string;
vallisOverride?: string;
duviriOverride?: string;

View File

@ -115,14 +115,7 @@ export const getGuildClient = async (
NumContributors: guild.CeremonyContributors?.length ?? 0,
CeremonyResetDate: guild.CeremonyResetDate ? toMongoDate(guild.CeremonyResetDate) : undefined,
AutoContributeFromVault: guild.AutoContributeFromVault,
AllianceId: guild.AllianceId ? toOid2(guild.AllianceId, account.BuildLabel) : undefined,
GoalProgress: guild.GoalProgress
? guild.GoalProgress.map(gp => ({
Count: gp.Count,
Tag: gp.Tag,
_id: { $oid: gp.goalId.toString() }
}))
: undefined
AllianceId: guild.AllianceId ? toOid2(guild.AllianceId, account.BuildLabel) : undefined
};
};
@ -816,85 +809,3 @@ export const getAllianceClient = async (
}
};
};
export const handleGuildGoalProgress = async (
guild: TGuildDatabaseDocument,
upload: { Count: number; Tag: string; goalId: Types.ObjectId }
): Promise<void> => {
guild.GoalProgress ??= [];
const goalProgress = guild.GoalProgress.find(x => x.goalId.equals(upload.goalId));
if (!goalProgress) {
guild.GoalProgress.push({
Count: upload.Count,
Tag: upload.Tag,
goalId: upload.goalId
});
}
const totalCount = (goalProgress?.Count ?? 0) + upload.Count;
const guildRewards = goalGuildRewardByTag[upload.Tag].rewards;
const tierGoals = goalGuildRewardByTag[upload.Tag].guildGoals[guild.Tier - 1];
const rewards = [];
if (tierGoals.length && guildRewards.length) {
for (let i = 0; i < tierGoals.length; i++) {
if (
tierGoals[i] &&
tierGoals[i] <= totalCount &&
(!goalProgress || goalProgress.Count < tierGoals[i]) &&
guildRewards[i]
) {
rewards.push(guildRewards[i]);
}
}
if (rewards.length) {
logger.debug(`guild goal rewards`, rewards);
guild.VaultDecoRecipes ??= [];
rewards.forEach(type => {
guild.VaultDecoRecipes!.push({
ItemType: type,
ItemCount: 1
});
});
}
}
if (goalProgress) {
goalProgress.Count += upload.Count;
}
await guild.save();
};
export const goalGuildRewardByTag: Record<string, { guildGoals: number[][]; rewards: string[] }> = {
JadeShadowsEvent: {
guildGoals: [
// I don't know what ClanGoal means
[15, 30, 45, 60],
[45, 90, 135, 180],
[150, 300, 450, 600],
[450, 900, 1350, 1800],
[1500, 3000, 4500, 6000]
],
rewards: [
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/JadeShadowsEventPewterTrophyRecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/JadeShadowsEventBronzeTrophyRecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/JadeShadowsEventSilverTrophyRecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/JadeShadowsEventGoldTrophyRecipe"
]
},
DuviriMurmurEvent: {
guildGoals: [
// I don't know what ClanGoal means
[260, 519, 779, 1038],
[779, 1557, 2336, 3114],
[2595, 5190, 7785, 10380],
[7785, 15570, 23355, 31140],
[29950, 51900, 77850, 103800]
],
rewards: [
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DuviriMurmurEventClayTrophyRecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DuviriMurmurEventBronzeTrophyRecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DuviriMurmurEventSilverTrophyRecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DuviriMurmurEventGoldTrophyRecipe"
]
}
};

View File

@ -44,22 +44,6 @@ import {
IKubrowPetDetailsClient,
IKubrowPetDetailsDatabase
} from "@/src/types/equipmentTypes";
import {
IApartmentClient,
IApartmentDatabase,
IFavouriteLoadout,
IFavouriteLoadoutDatabase,
IGetShipResponse,
IOrbiterClient,
IOrbiterDatabase,
IPersonalRoomsDatabase,
IPlantClient,
IPlantDatabase,
IPlanterClient,
IPlanterDatabase,
ITailorShop,
ITailorShopDatabase
} from "@/src/types/personalRoomsTypes";
const convertDate = (value: IMongoDate): Date => {
return new Date(parseInt(value.$date.$numberLong));
@ -445,57 +429,3 @@ export const importLoadOutPresets = (db: ILoadoutDatabase, client: ILoadOutPrese
db.OPERATOR_ADULT = client.OPERATOR_ADULT.map(convertLoadOutConfig);
db.DRIFTER = client.DRIFTER.map(convertLoadOutConfig);
};
const convertShip = (client: IOrbiterClient): IOrbiterDatabase => {
return {
...client,
ShipInterior: {
...client.ShipInterior,
Colors: Array.isArray(client.ShipInterior.Colors) ? {} : client.ShipInterior.Colors
},
FavouriteLoadoutId: client.FavouriteLoadoutId ? new Types.ObjectId(client.FavouriteLoadoutId.$oid) : undefined
};
};
const convertPlant = (client: IPlantClient): IPlantDatabase => {
return {
...client,
EndTime: convertDate(client.EndTime)
};
};
const convertPlanter = (client: IPlanterClient): IPlanterDatabase => {
return {
...client,
Plants: client.Plants.map(convertPlant)
};
};
const convertFavouriteLoadout = (client: IFavouriteLoadout): IFavouriteLoadoutDatabase => {
return {
...client,
LoadoutId: new Types.ObjectId(client.LoadoutId.$oid)
};
};
const convertApartment = (client: IApartmentClient): IApartmentDatabase => {
return {
...client,
Gardening: { Planters: client.Gardening.Planters.map(convertPlanter) },
FavouriteLoadouts: client.FavouriteLoadouts ? client.FavouriteLoadouts.map(convertFavouriteLoadout) : []
};
};
const convertTailorShop = (client: ITailorShop): ITailorShopDatabase => {
return {
...client,
Colors: Array.isArray(client.Colors) ? {} : client.Colors,
FavouriteLoadouts: client.FavouriteLoadouts ? client.FavouriteLoadouts.map(convertFavouriteLoadout) : []
};
};
export const importPersonalRooms = (db: IPersonalRoomsDatabase, client: Partial<IGetShipResponse>): void => {
if (client.Ship !== undefined) db.Ship = convertShip(client.Ship);
if (client.Apartment !== undefined) db.Apartment = convertApartment(client.Apartment);
if (client.TailorShop !== undefined) db.TailorShop = convertTailorShop(client.TailorShop);
};

View File

@ -1,11 +1,8 @@
import { ExportRecipes } from "warframe-public-export-plus";
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
import {
IAccountCheats,
IInfestedFoundryClient,
IInfestedFoundryDatabase
} from "@/src/types/inventoryTypes/inventoryTypes";
import { IInfestedFoundryClient, IInfestedFoundryDatabase } from "@/src/types/inventoryTypes/inventoryTypes";
import { addRecipes } from "@/src/services/inventoryService";
import { config } from "@/src/services/configService";
import { ITypeCount } from "@/src/types/commonTypes";
export const addInfestedFoundryXP = (infestedFoundry: IInfestedFoundryDatabase, delta: number): ITypeCount[] => {
@ -100,8 +97,8 @@ export const handleSubsumeCompletion = (inventory: TInventoryDatabaseDocument):
return recipeChanges;
};
export const applyCheatsToInfestedFoundry = (cheats: IAccountCheats, infestedFoundry: IInfestedFoundryClient): void => {
if (cheats.infiniteHelminthMaterials) {
export const applyCheatsToInfestedFoundry = (infestedFoundry: IInfestedFoundryClient): void => {
if (config.infiniteHelminthMaterials) {
infestedFoundry.Resources = [
{ ItemType: "/Lotus/Types/Items/InfestedFoundry/HelminthCalx", Count: 1000 },
{ ItemType: "/Lotus/Types/Items/InfestedFoundry/HelminthBiotics", Count: 1000 },

View File

@ -847,32 +847,6 @@ export const addItem = async (
return addMotorcycle(inventory, typeName);
}
break;
case "Lore":
if (typeName == "/Lotus/Types/Lore/Fragments/GrineerGhoulFragments/GhoulFragmentRewards") {
const fragmentType = getRandomElement([
"/Lotus/Types/Lore/Fragments/GrineerGhoulFragments/GhoulFragmentA",
"/Lotus/Types/Lore/Fragments/GrineerGhoulFragments/GhoulFragmentB",
"/Lotus/Types/Lore/Fragments/GrineerGhoulFragments/GhoulFragmentC",
"/Lotus/Types/Lore/Fragments/GrineerGhoulFragments/GhoulFragmentD",
"/Lotus/Types/Lore/Fragments/GrineerGhoulFragments/GhoulFragmentE",
"/Lotus/Types/Lore/Fragments/GrineerGhoulFragments/GhoulFragmentF",
"/Lotus/Types/Lore/Fragments/GrineerGhoulFragments/GhoulFragmentG",
"/Lotus/Types/Lore/Fragments/GrineerGhoulFragments/GhoulFragmentH",
"/Lotus/Types/Lore/Fragments/GrineerGhoulFragments/GhoulFragmentI",
"/Lotus/Types/Lore/Fragments/GrineerGhoulFragments/GhoulFragmentJ",
"/Lotus/Types/Lore/Fragments/GrineerGhoulFragments/GhoulFragmentK",
"/Lotus/Types/Lore/Fragments/GrineerGhoulFragments/GhoulFragmentL",
"/Lotus/Types/Lore/Fragments/GrineerGhoulFragments/GhoulFragmentM"
])!;
addLoreFragmentScans(inventory, [
{
Progress: 1,
Region: "",
ItemType: fragmentType
}
]);
}
break;
}
break;
}
@ -1227,8 +1201,8 @@ export const updateSlots = (
}
};
const isCurrencyTracked = (inventory: TInventoryDatabaseDocument, usePremium: boolean): boolean => {
return usePremium ? !inventory.infinitePlatinum : !inventory.infiniteCredits;
const isCurrencyTracked = (usePremium: boolean): boolean => {
return usePremium ? !config.infinitePlatinum : !config.infiniteCredits;
};
export const updateCurrency = (
@ -1237,7 +1211,7 @@ export const updateCurrency = (
usePremium: boolean,
inventoryChanges: IInventoryChanges = {}
): IInventoryChanges => {
if (price != 0 && isCurrencyTracked(inventory, usePremium)) {
if (price != 0 && isCurrencyTracked(usePremium)) {
if (usePremium) {
if (inventory.PremiumCreditsFree > 0) {
const premiumCreditsFreeDelta = Math.min(price, inventory.PremiumCreditsFree) * -1;
@ -2006,20 +1980,17 @@ export const addChallenges = async (
dbChallenge.Completed ??= [];
for (const completion of Completed!) {
if (dbChallenge.Completed.indexOf(completion) == -1) {
dbChallenge.Completed.push(completion);
if (completion == "challengeRewards") {
if (Name in challengeRewardsInboxMessages) {
await createMessage(account._id, [challengeRewardsInboxMessages[Name]]);
dbChallenge.Completed.push(completion);
// Would love to somehow let the client know about inbox or inventory changes, but there doesn't seem to anything for updateChallengeProgress.
continue;
}
logger.warn(`ignoring unknown challenge completion`, { challenge: Name, completion });
dbChallenge.Completed = [];
}
logger.warn(`ignoring unknown challenge completion`, { challenge: Name, completion });
}
}
} else {
dbChallenge.Completed = Completed;
}
}

View File

@ -50,7 +50,7 @@ import { getEntriesUnsafe } from "@/src/utils/ts-utils";
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
import { IMissionCredits, IMissionReward } from "@/src/types/missionTypes";
import { crackRelic } from "@/src/helpers/relicHelper";
import { createMessage, IMessageCreationTemplate } from "@/src/services/inboxService";
import { createMessage } from "@/src/services/inboxService";
import kuriaMessage50 from "@/static/fixed_responses/kuriaMessages/fiftyPercent.json";
import kuriaMessage75 from "@/static/fixed_responses/kuriaMessages/seventyFivePercent.json";
import kuriaMessage100 from "@/static/fixed_responses/kuriaMessages/oneHundredPercent.json";
@ -76,20 +76,13 @@ import {
} from "@/src/services/worldStateService";
import { config } from "@/src/services/configService";
import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json";
import { IGoal, ISyndicateMissionInfo } from "@/src/types/worldStateTypes";
import { ISyndicateMissionInfo } from "@/src/types/worldStateTypes";
import { fromOid } from "@/src/helpers/inventoryHelpers";
import { TAccountDocument } from "@/src/services/loginService";
import { ITypeCount } from "@/src/types/commonTypes";
import { IEquipmentClient } from "@/src/types/equipmentTypes";
import { Guild } from "@/src/models/guildModel";
import { handleGuildGoalProgress } from "@/src/services/guildService";
const getRotations = (rewardInfo: IRewardInfo, tierOverride?: number): number[] => {
// Disruption missions just tell us (https://onlyg.it/OpenWF/SpaceNinjaServer/issues/2599)
if (rewardInfo.rewardTierOverrides) {
return rewardInfo.rewardTierOverrides;
}
// For Spy missions, e.g. 3 vaults cracked = A, B, C
if (rewardInfo.VaultsCracked) {
const rotations: number[] = [];
@ -99,23 +92,14 @@ const getRotations = (rewardInfo: IRewardInfo, tierOverride?: number): number[]
return rotations;
}
const region = ExportRegions[rewardInfo.node] as IRegion | undefined;
const missionIndex: number | undefined = region?.missionIndex;
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
const missionIndex: number | undefined = ExportRegions[rewardInfo.node]?.missionIndex;
// For Rescue missions
if (missionIndex == 3 && rewardInfo.rewardTier) {
return [rewardInfo.rewardTier];
}
// 'rewardQualifications' is unreliable for non-endless railjack missions (https://onlyg.it/OpenWF/SpaceNinjaServer/issues/2586, https://onlyg.it/OpenWF/SpaceNinjaServer/issues/2612)
switch (region?.missionName) {
case "/Lotus/Language/Missions/MissionName_Railjack":
case "/Lotus/Language/Missions/MissionName_RailjackVolatile":
case "/Lotus/Language/Missions/MissionName_RailjackExterminate":
case "/Lotus/Language/Missions/MissionName_RailjackAssassinate":
return [0];
}
const rotationCount = rewardInfo.rewardQualifications?.length || 0;
// Empty or absent rewardQualifications should not give rewards when:
@ -630,103 +614,37 @@ export const addMissionInventoryUpdates = async (
if (goal && goal.Personal) {
inventory.PersonalGoalProgress ??= [];
const goalProgress = inventory.PersonalGoalProgress.find(x => x.goalId.equals(goal._id.$oid));
if (!goalProgress) {
if (goalProgress) {
goalProgress.Best = Math.max(goalProgress.Best, uploadProgress.Best);
goalProgress.Count += uploadProgress.Count;
} else {
inventory.PersonalGoalProgress.push({
Best: uploadProgress.Best,
Count: uploadProgress.Count,
Tag: goal.Tag,
goalId: new Types.ObjectId(goal._id.$oid)
});
}
const currentNode = inventoryUpdates.RewardInfo!.node;
let currentMissionKey;
if (currentNode == goal.Node) {
currentMissionKey = goal.MissionKeyName;
} else if (goal.ConcurrentNodes && goal.ConcurrentMissionKeyNames) {
for (let i = 0; i < goal.ConcurrentNodes.length; i++) {
if (currentNode == goal.ConcurrentNodes[i]) {
currentMissionKey = goal.ConcurrentMissionKeyNames[i];
break;
}
}
}
if (currentMissionKey && currentMissionKey in goalMessagesByKey) {
const totalCount = (goalProgress?.Count ?? 0) + uploadProgress.Count;
let reward;
if (goal.InterimGoals && goal.InterimRewards) {
for (let i = 0; i < goal.InterimGoals.length; i++) {
if (
goal.InterimGoals[i] &&
goal.InterimGoals[i] <= totalCount &&
(!goalProgress || goalProgress.Count < goal.InterimGoals[i]) &&
goal.InterimRewards[i]
) {
reward = goal.InterimRewards[i];
break;
}
}
}
if (
!reward &&
goal.Goal &&
goal.Goal <= totalCount &&
(!goalProgress || goalProgress.Count < goal.Goal) &&
goal.Reward
goal.Reward &&
goal.Reward.items &&
goal.MissionKeyName &&
goal.MissionKeyName in goalMessagesByKey
) {
reward = goal.Reward;
}
if (
!reward &&
goal.BonusGoal &&
goal.BonusGoal <= totalCount &&
(!goalProgress || goalProgress.Count < goal.BonusGoal) &&
goal.BonusReward
) {
reward = goal.BonusReward;
}
if (reward) {
if (currentMissionKey in goalMessagesByKey) {
// Send reward via inbox
const info = goalMessagesByKey[currentMissionKey];
const message: IMessageCreationTemplate = {
// Send reward via inbox
const info = goalMessagesByKey[goal.MissionKeyName];
await createMessage(inventory.accountOwnerId, [
{
sndr: info.sndr,
msg: info.msg,
att: goal.Reward.items.map(x => (isStoreItem(x) ? fromStoreItem(x) : x)),
sub: info.sub,
icon: info.icon,
highPriority: true
};
if (reward.items) {
message.att = reward.items.map(x => (isStoreItem(x) ? fromStoreItem(x) : x));
}
if (reward.countedItems) {
message.countedAtt = reward.countedItems;
}
if (reward.credits) {
message.RegularCredits = reward.credits;
}
await createMessage(inventory.accountOwnerId, [message]);
}
]);
}
}
if (goalProgress) {
goalProgress.Best = Math.max(goalProgress.Best!, uploadProgress.Best);
goalProgress.Count += uploadProgress.Count;
}
}
if (goal && goal.ClanGoal && inventory.GuildId) {
const guild = await Guild.findById(inventory.GuildId, "GoalProgress Tier VaultDecoRecipes");
if (guild) {
await handleGuildGoalProgress(guild, {
Count: uploadProgress.Count,
Tag: goal.Tag,
goalId: new Types.ObjectId(goal._id.$oid)
});
}
}
}
break;
@ -853,24 +771,26 @@ export const addMissionInventoryUpdates = async (
}
}
await createMessage(inventory.accountOwnerId, [
{
sndr: value.killed ? "/Lotus/Language/Bosses/Ordis" : value.nemesisName,
msg: value.killed ? manifest.killMessageBody : manifest.convertMessageBody,
arg: [
{
Key: "LICH_NAME",
Tag: value.nemesisName
}
],
att: att,
countedAtt: countedAtt,
attVisualOnly: true,
sub: value.killed ? manifest.killMessageSubject : manifest.convertMessageSubject,
icon: value.killed ? "/Lotus/Interface/Icons/Npcs/Ordis.png" : manifest.convertMessageIcon,
highPriority: true
}
]);
if (value.killed) {
await createMessage(inventory.accountOwnerId, [
{
sndr: "/Lotus/Language/Bosses/Ordis",
msg: manifest.messageBody,
arg: [
{
Key: "LICH_NAME",
Tag: value.nemesisName
}
],
att: att,
countedAtt: countedAtt,
attVisualOnly: true,
sub: manifest.messageTitle,
icon: "/Lotus/Interface/Icons/Npcs/Ordis.png",
highPriority: true
}
]);
}
inventory.Nemesis = undefined;
}
@ -1081,16 +1001,8 @@ export const addMissionRewards = async (
if (rewardInfo.goalId) {
const goal = getWorldState().Goals.find(x => x._id.$oid == rewardInfo.goalId);
if (goal) {
if (rewardInfo.node == goal.Node && goal.MissionKeyName) levelKeyName = goal.MissionKeyName;
if (goal.ConcurrentNodes && goal.ConcurrentMissionKeyNames) {
for (let i = 0; i < goal.ConcurrentNodes.length && i < goal.ConcurrentMissionKeyNames.length; i++) {
if (rewardInfo.node == goal.ConcurrentNodes[i]) {
levelKeyName = goal.ConcurrentMissionKeyNames[i];
break;
}
}
}
if (goal?.MissionKeyName) {
levelKeyName = goal.MissionKeyName;
}
}
@ -1342,8 +1254,6 @@ export const addMissionRewards = async (
}
}
AffiliationMods ??= [];
if (rewardInfo.JobStage != undefined && rewardInfo.jobId) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [jobType, unkIndex, hubNode, syndicateMissionId] = rewardInfo.jobId.split("_");
@ -1351,29 +1261,9 @@ export const addMissionRewards = async (
if (syndicateMissionId) {
pushClassicBounties(syndicateMissions, idToBountyCycle(syndicateMissionId));
}
let syndicateEntry: ISyndicateMissionInfo | IGoal | undefined = syndicateMissions.find(
m => m._id.$oid === syndicateMissionId
);
if (
[
"/Lotus/Types/Gameplay/Eidolon/Jobs/Events/InfestedPlainsBounty",
"/Lotus/Types/Gameplay/Eidolon/Jobs/Events/GhoulAlertBounty"
].some(prefix => jobType.startsWith(prefix))
) {
const { Goals } = getWorldState(undefined);
syndicateEntry = Goals.find(m => m._id.$oid === syndicateMissionId);
if (syndicateEntry) syndicateEntry.Tag = syndicateEntry.JobAffiliationTag!;
}
const syndicateEntry = syndicateMissions.find(m => m._id.$oid === syndicateMissionId);
if (syndicateEntry && syndicateEntry.Jobs) {
let currentJob = syndicateEntry.Jobs[rewardInfo.JobTier!];
if (
[
"/Lotus/Types/Gameplay/Eidolon/Jobs/Events/InfestedPlainsBounty",
"/Lotus/Types/Gameplay/Eidolon/Jobs/Events/GhoulAlertBounty"
].some(prefix => jobType.startsWith(prefix))
) {
currentJob = syndicateEntry.Jobs.find(j => j.jobType === jobType)!;
}
if (syndicateEntry.Tag === "EntratiSyndicate") {
if (
[
@ -1416,35 +1306,31 @@ export const addMissionRewards = async (
`Giving ${medallionAmount} medallions for the ${rewardInfo.JobStage} stage of the ${rewardInfo.JobTier} tier bounty`
);
} else {
const specialCase = [
{ endings: ["Heists/HeistProfitTakerBountyOne"], stage: 2, amount: 1000 },
{ endings: ["Hunts/AllTeralystsHunt"], stage: 2, amount: 5000 },
{
endings: [
"Hunts/TeralystHunt",
"Heists/HeistProfitTakerBountyTwo",
"Heists/HeistProfitTakerBountyThree",
"Heists/HeistProfitTakerBountyFour",
"Heists/HeistExploiterBountyOne"
],
amount: 1000
}
];
const specialCaseReward = specialCase.find(
rule =>
rule.endings.some(e => jobType.endsWith(e)) &&
(rule.stage === undefined || rewardInfo.JobStage === rule.stage)
);
if (specialCaseReward) {
addStanding(inventory, syndicateEntry.Tag, specialCaseReward.amount, AffiliationMods);
} else {
if (rewardInfo.JobTier! >= 0) {
addStanding(
inventory,
syndicateEntry.Tag,
Math.floor(currentJob.xpAmounts[rewardInfo.JobStage] / (rewardInfo.Q ? 0.8 : 1)),
AffiliationMods
);
} else {
if (jobType.endsWith("Heists/HeistProfitTakerBountyOne") && rewardInfo.JobStage === 2) {
addStanding(inventory, syndicateEntry.Tag, 1000, AffiliationMods);
}
if (jobType.endsWith("Hunts/AllTeralystsHunt") && rewardInfo.JobStage === 2) {
addStanding(inventory, syndicateEntry.Tag, 5000, AffiliationMods);
}
if (
[
"Hunts/TeralystHunt",
"Heists/HeistProfitTakerBountyTwo",
"Heists/HeistProfitTakerBountyThree",
"Heists/HeistProfitTakerBountyFour",
"Heists/HeistExploiterBountyOne"
].some(ending => jobType.endsWith(ending))
) {
addStanding(inventory, syndicateEntry.Tag, 1000, AffiliationMods);
}
}
}
}
@ -1781,19 +1667,7 @@ function getRandomMissionDrops(
if (syndicateMissionId) {
pushClassicBounties(syndicateMissions, idToBountyCycle(syndicateMissionId));
}
let syndicateEntry: ISyndicateMissionInfo | IGoal | undefined = syndicateMissions.find(
m => m._id.$oid === syndicateMissionId
);
if (
[
"/Lotus/Types/Gameplay/Eidolon/Jobs/Events/InfestedPlainsBounty",
"/Lotus/Types/Gameplay/Eidolon/Jobs/Events/GhoulAlertBounty"
].some(prefix => jobType.startsWith(prefix))
) {
const { Goals } = getWorldState(undefined);
syndicateEntry = Goals.find(m => m._id.$oid === syndicateMissionId);
if (syndicateEntry) syndicateEntry.Tag = syndicateEntry.JobAffiliationTag!;
}
const syndicateEntry = syndicateMissions.find(m => m._id.$oid === syndicateMissionId);
if (syndicateEntry && syndicateEntry.Jobs) {
let job = syndicateEntry.Jobs[RewardInfo.JobTier!];
@ -1878,14 +1752,6 @@ function getRandomMissionDrops(
}
}
}
if (
[
"/Lotus/Types/Gameplay/Eidolon/Jobs/Events/InfestedPlainsBounty",
"/Lotus/Types/Gameplay/Eidolon/Jobs/Events/GhoulAlertBounty"
].some(prefix => jobType.startsWith(prefix))
) {
job = syndicateEntry.Jobs.find(j => j.jobType === jobType)!;
}
rewardManifests = [job.rewards];
if (job.xpAmounts.length > 1) {
const curentStage = RewardInfo.JobStage! + 1;
@ -2014,36 +1880,6 @@ function getRandomMissionDrops(
}
});
// Railjack Abandoned Cache Rewards, Rotation A (Mandatory Objectives)
if (RewardInfo.POICompletions) {
if (region.cacheRewardManifest) {
const deck = ExportRewards[region.cacheRewardManifest];
for (let cache = 0; cache != RewardInfo.POICompletions; ++cache) {
const drop = getRandomRewardByChance(deck[0]);
if (drop) {
drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount, FromEnemyCache: true });
}
}
} else {
logger.error(`POI completed, but there was no cache reward manifest at ${RewardInfo.node}`);
}
}
// Railjack Abandoned Cache Rewards, Rotation B (Optional Objectives)
if (RewardInfo.LootDungeonCompletions) {
if (region.cacheRewardManifest) {
const deck = ExportRewards[region.cacheRewardManifest];
for (let cache = 0; cache != RewardInfo.LootDungeonCompletions; ++cache) {
const drop = getRandomRewardByChance(deck[1]);
if (drop) {
drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount, FromEnemyCache: true });
}
}
} else {
logger.error(`Loot dungeon completed, but there was no cache reward manifest at ${RewardInfo.node}`);
}
}
if (region.cacheRewardManifest && RewardInfo.EnemyCachesFound) {
const deck = ExportRewards[region.cacheRewardManifest];
for (let rotation = 0; rotation != RewardInfo.EnemyCachesFound; ++rotation) {
@ -2257,143 +2093,5 @@ const goalMessagesByKey: Record<string, { sndr: string; msg: string; sub: string
msg: "/Lotus/Language/Messages/GalleonRobbery2025RewardMsgC",
sub: "/Lotus/Language/Messages/GalleonRobbery2025MissionTitleC",
icon: "/Lotus/Interface/Icons/Npcs/VayHekPortrait.png"
},
"/Lotus/Types/Keys/TacAlertKeyWaterFightA": {
sndr: "/Lotus/Language/Bosses/BossKelaDeThaym",
msg: "/Lotus/Language/Inbox/WaterFightRewardMsgA",
sub: "/Lotus/Language/Inbox/WaterFightRewardSubjectA",
icon: "/Lotus/Interface/Icons/Npcs/Grineer/KelaDeThaym.png"
},
"/Lotus/Types/Keys/TacAlertKeyWaterFightB": {
sndr: "/Lotus/Language/Bosses/BossKelaDeThaym",
msg: "/Lotus/Language/Inbox/WaterFightRewardMsgB",
sub: "/Lotus/Language/Inbox/WaterFightRewardSubjectB",
icon: "/Lotus/Interface/Icons/Npcs/Grineer/KelaDeThaym.png"
},
"/Lotus/Types/Keys/TacAlertKeyWaterFightC": {
sndr: "/Lotus/Language/Bosses/BossKelaDeThaym",
msg: "/Lotus/Language/Inbox/WaterFightRewardMsgC",
sub: "/Lotus/Language/Inbox/WaterFightRewardSubjectC",
icon: "/Lotus/Interface/Icons/Npcs/Grineer/KelaDeThaym.png"
},
"/Lotus/Types/Keys/TacAlertKeyWaterFightD": {
sndr: "/Lotus/Language/Bosses/BossKelaDeThaym",
msg: "/Lotus/Language/Inbox/WaterFightRewardMsgD",
sub: "/Lotus/Language/Inbox/WaterFightRewardSubjectD",
icon: "/Lotus/Interface/Icons/Npcs/Grineer/KelaDeThaym.png"
},
"/Lotus/Types/Keys/WolfTacAlertReduxA": {
sndr: "/Lotus/Language/Bosses/NoraNight",
msg: "/Lotus/Language/Inbox/WolfTacAlertBody",
sub: "/Lotus/Language/Inbox/WolfTacAlertTitle",
icon: "/Lotus/Interface/Icons/Npcs/Seasonal/NoraNight.png"
},
"/Lotus/Types/Keys/WolfTacAlertReduxB": {
sndr: "/Lotus/Language/Bosses/NoraNight",
msg: "/Lotus/Language/Inbox/WolfTacAlertBody",
sub: "/Lotus/Language/Inbox/WolfTacAlertTitle",
icon: "/Lotus/Interface/Icons/Npcs/Seasonal/NoraNight.png"
},
"/Lotus/Types/Keys/WolfTacAlertReduxD": {
sndr: "/Lotus/Language/Bosses/NoraNight",
msg: "/Lotus/Language/Inbox/WolfTacAlertBody",
sub: "/Lotus/Language/Inbox/WolfTacAlertTitle",
icon: "/Lotus/Interface/Icons/Npcs/Seasonal/NoraNight.png"
},
"/Lotus/Types/Keys/WolfTacAlertReduxC": {
sndr: "/Lotus/Language/Bosses/NoraNight",
msg: "/Lotus/Language/Inbox/WolfTacAlertBody",
sub: "/Lotus/Language/Inbox/WolfTacAlertTitle",
icon: "/Lotus/Interface/Icons/Npcs/Seasonal/NoraNight.png"
},
"/Lotus/Types/Keys/LanternEndlessEventKeyA": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/G1Quests/GenericEventRewardMsgDesc",
sub: "/Lotus/Language/G1Quests/GenericTacAlertRewardMsgTitle",
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
},
"/Lotus/Types/Keys/LanternEndlessEventKeyB": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/G1Quests/GenericEventRewardMsgDesc",
sub: "/Lotus/Language/G1Quests/GenericTacAlertRewardMsgTitle",
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
},
"/Lotus/Types/Keys/LanternEndlessEventKeyD": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/G1Quests/GenericEventRewardMsgDesc",
sub: "/Lotus/Language/G1Quests/GenericTacAlertRewardMsgTitle",
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
},
"/Lotus/Types/Keys/LanternEndlessEventKeyC": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/G1Quests/GenericEventRewardMsgDesc",
sub: "/Lotus/Language/G1Quests/GenericTacAlertRewardMsgTitle",
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
},
"/Lotus/Types/Keys/TacAlertKeyHalloween": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsBonusBody",
sub: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsBonusTitle",
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
},
"/Lotus/Types/Keys/TacAlertKeyHalloweenBonus": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsBody",
sub: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsTitle",
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
},
"/Lotus/Types/Keys/TacAlertKeyHalloweenTimeAttack": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsBody",
sub: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsTitle",
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
},
"/Lotus/Types/Keys/TacAlertKeyProxyRebellionOne": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/G1Quests/RazorbackArmadaRewardBody",
sub: "/Lotus/Language/G1Quests/GenericTacAlertSmallRewardMsgTitle",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
},
"/Lotus/Types/Keys/TacAlertKeyProxyRebellionTwo": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/G1Quests/RazorbackArmadaRewardBody",
sub: "/Lotus/Language/G1Quests/GenericTacAlertSmallRewardMsgTitle",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
},
"/Lotus/Types/Keys/TacAlertKeyProxyRebellionThree": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/G1Quests/RazorbackArmadaRewardBody",
sub: "/Lotus/Language/G1Quests/GenericTacAlertSmallRewardMsgTitle",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
},
"/Lotus/Types/Keys/TacAlertKeyProxyRebellionFour": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/G1Quests/GenericTacAlertBadgeRewardMsgDesc",
sub: "/Lotus/Language/G1Quests/GenericTacAlertBadgeRewardMsgTitle",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
},
"/Lotus/Types/Keys/TacAlertKeyProjectNightwatchEasy": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/G1Quests/ProjectNightwatchRewardMsgA",
sub: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionOneTitle",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
},
"/Lotus/Types/Keys/TacAlertKeyProjectNightwatch": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionRewardBody",
sub: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionTwoTitle",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
},
"/Lotus/Types/Keys/TacAlertKeyProjectNightwatchHard": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionRewardBody",
sub: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionThreeTitle",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
},
"/Lotus/Types/Keys/TacAlertKeyProjectNightwatchBonus": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionRewardBody",
sub: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionFourTitle",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
}
};

View File

@ -1,4 +1,4 @@
import { parseSlotPurchaseName, slotPurchaseNameToSlotName } from "@/src/helpers/purchaseHelpers";
import { parseSlotPurchaseName } from "@/src/helpers/purchaseHelpers";
import { getSubstringFromKeyword } from "@/src/helpers/stringHelpers";
import {
addBooster,
@ -14,6 +14,7 @@ import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
import {
IPurchaseRequest,
IPurchaseResponse,
SlotPurchase,
IInventoryChanges,
PurchaseSource,
IPurchaseParams
@ -36,9 +37,6 @@ import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/invento
import { fromStoreItem, toStoreItem } from "@/src/services/itemDataService";
import { DailyDeal } from "@/src/models/worldStateModel";
import { fromMongoDate, toMongoDate } from "@/src/helpers/inventoryHelpers";
import { Guild } from "@/src/models/guildModel";
import { handleGuildGoalProgress } from "@/src/services/guildService";
import { Types } from "mongoose";
export const getStoreItemCategory = (storeItem: string): string => {
const storeItemString = getSubstringFromKeyword(storeItem, "StoreItems/");
@ -140,22 +138,6 @@ export const handlePurchase = async (
updateCurrency(inventory, offer.PremiumPrice[0], true, prePurchaseInventoryChanges);
}
}
if (
inventory.GuildId &&
offer.ItemPrices &&
manifest.VendorInfo.TypeName ==
"/Lotus/Types/Game/VendorManifests/Events/DuviriMurmurInvasionVendorManifest"
) {
const guild = await Guild.findById(inventory.GuildId, "GoalProgress Tier VaultDecoRecipes");
const goal = getWorldState().Goals.find(x => x.Tag == "DuviriMurmurEvent");
if (guild && goal) {
await handleGuildGoalProgress(guild, {
Count: offer.ItemPrices[0].ItemCount * purchaseRequest.PurchaseParams.Quantity,
Tag: goal.Tag,
goalId: new Types.ObjectId(goal._id.$oid)
});
}
}
if (!config.dontSubtractPurchaseItemCost) {
if (offer.ItemPrices) {
handleItemPrices(
@ -346,7 +328,7 @@ export const handlePurchase = async (
purchaseResponse.InventoryChanges.MiscItems ??= [];
purchaseResponse.InventoryChanges.MiscItems.push(invItem);
}
} else if (!inventory.infiniteRegalAya) {
} else if (!config.infiniteRegalAya) {
inventory.PrimeTokens -= offer.PrimePrice! * purchaseRequest.PurchaseParams.Quantity;
purchaseResponse.InventoryChanges.PrimeTokens ??= 0;
@ -490,6 +472,19 @@ export const handleStoreItemAcquisition = async (
return purchaseResponse;
};
export const slotPurchaseNameToSlotName: SlotPurchase = {
SuitSlotItem: { name: "SuitBin", purchaseQuantity: 1 },
TwoSentinelSlotItem: { name: "SentinelBin", purchaseQuantity: 2 },
TwoWeaponSlotItem: { name: "WeaponBin", purchaseQuantity: 2 },
SpaceSuitSlotItem: { name: "SpaceSuitBin", purchaseQuantity: 1 },
TwoSpaceWeaponSlotItem: { name: "SpaceWeaponBin", purchaseQuantity: 2 },
MechSlotItem: { name: "MechBin", purchaseQuantity: 1 },
TwoOperatorWeaponSlotItem: { name: "OperatorAmpBin", purchaseQuantity: 2 },
RandomModSlotItem: { name: "RandomModBin", purchaseQuantity: 3 },
TwoCrewShipSalvageSlotItem: { name: "CrewShipSalvageBin", purchaseQuantity: 2 },
CrewMemberSlotItem: { name: "CrewMemberBin", purchaseQuantity: 1 }
};
// // extra = everything above the base +2 slots (depending on slot type)
// // new slot above base = extra + 1 and slots +1
// // new frame = slots -1

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,6 @@
import { Types } from "mongoose";
import { IOid, IMongoDate, IOidWithLegacySupport, ITypeCount } from "@/src/types/commonTypes";
import {
IFusionTreasure,
IMiscItem,
IGoalProgressDatabase,
IGoalProgressClient
} from "@/src/types/inventoryTypes/inventoryTypes";
import { IFusionTreasure, IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
import { IPictureFrameInfo } from "@/src/types/personalRoomsTypes";
import { IFriendInfo } from "@/src/types/friendTypes";
@ -28,8 +23,6 @@ export interface IGuildClient {
CrossPlatformEnabled?: boolean;
AutoContributeFromVault?: boolean;
AllianceId?: IOidWithLegacySupport;
GoalProgress?: IGoalProgressClient[];
}
export interface IGuildDatabase {
@ -70,8 +63,6 @@ export interface IGuildDatabase {
TechChanges?: IGuildLogEntryContributable[];
RosterActivity?: IGuildLogEntryRoster[];
ClassChanges?: IGuildLogEntryNumber[];
GoalProgress?: IGoalProgressDatabase[];
}
export interface ILongMOTD {

View File

@ -19,15 +19,6 @@ export type InventoryDatabaseEquipment = {
[_ in TEquipmentKey]: IEquipmentDatabase[];
};
// Fields specific to SNS
export interface IAccountCheats {
infiniteCredits?: boolean;
infinitePlatinum?: boolean;
infiniteEndo?: boolean;
infiniteRegalAya?: boolean;
infiniteHelminthMaterials?: boolean;
}
export interface IInventoryDatabase
extends Omit<
IInventoryClient,
@ -70,8 +61,7 @@ export interface IInventoryDatabase
| "PersonalGoalProgress"
| TEquipmentKey
>,
InventoryDatabaseEquipment,
IAccountCheats {
InventoryDatabaseEquipment {
accountOwnerId: Types.ObjectId;
Created: Date;
TrainingDate: Date;
@ -109,7 +99,7 @@ export interface IInventoryDatabase
QualifyingInvasions: IInvasionProgressDatabase[];
LastInventorySync?: Types.ObjectId;
EndlessXP?: IEndlessXpProgressDatabase[];
PersonalGoalProgress?: IGoalProgressDatabase[];
PersonalGoalProgress?: IPersonalGoalProgressDatabase[];
}
export interface IQuestKeyDatabase {
@ -318,7 +308,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
HWIDProtectEnabled?: boolean;
KubrowPetPrints: IKubrowPetPrintClient[];
AlignmentReplay?: IAlignment;
PersonalGoalProgress?: IGoalProgressClient[];
PersonalGoalProgress?: IPersonalGoalProgressClient[];
ThemeStyle: string;
ThemeBackground: string;
ThemeSounds: string;
@ -730,7 +720,7 @@ export enum UpgradeType {
export interface ILoreFragmentScan {
Progress: number;
Region: string;
Region?: string;
ItemType: string;
}
@ -895,8 +885,8 @@ export interface IPeriodicMissionCompletionResponse extends Omit<IPeriodicMissio
date: IMongoDate;
}
export interface IGoalProgressClient {
Best?: number;
export interface IPersonalGoalProgressClient {
Best: number;
Count: number;
Tag: string;
_id: IOid;
@ -904,7 +894,7 @@ export interface IGoalProgressClient {
//ReceivedClanReward1?: boolean;
}
export interface IGoalProgressDatabase extends Omit<IGoalProgressClient, "_id"> {
export interface IPersonalGoalProgressDatabase extends Omit<IPersonalGoalProgressClient, "_id"> {
goalId: Types.ObjectId;
}

View File

@ -23,19 +23,12 @@ export interface IMissionCredits {
DailyMissionBonus?: boolean;
}
export interface IMissionInventoryUpdateResponseRailjackInterstitial extends Partial<IMissionCredits> {
export interface IMissionInventoryUpdateResponse extends Partial<IMissionCredits> {
ConquestCompletedMissionsCount?: number;
InventoryJson?: string;
MissionRewards?: IMissionReward[];
InventoryChanges?: IInventoryChanges;
FusionPoints?: number;
SyndicateXPItemReward?: number;
AffiliationMods?: IAffiliationMods[];
}
export interface IMissionInventoryUpdateResponse extends IMissionInventoryUpdateResponseRailjackInterstitial {
InventoryJson?: string;
}
export interface IMissionInventoryUpdateResponseBackToDryDock {
InventoryJson: string;
}

View File

@ -90,7 +90,7 @@ export interface IGardeningDatabase {
export interface IApartmentClient {
Gardening: IGardeningClient;
Rooms: IRoom[];
FavouriteLoadouts?: IFavouriteLoadout[];
FavouriteLoadouts: IFavouriteLoadout[];
VideoWallBackdrop?: string;
Soundscape?: string;
}
@ -210,7 +210,7 @@ export interface ITailorShopDatabase {
}
export interface ITailorShop extends Omit<ITailorShopDatabase, "FavouriteLoadouts"> {
FavouriteLoadouts?: IFavouriteLoadout[];
FavouriteLoadouts: IFavouriteLoadout[];
}
export type RoomsType = { Name: string; MaxCapacity: number; PlacedDecos: Types.DocumentArray<IPlacedDecosDatabase> };

View File

@ -148,7 +148,6 @@ export type IMissionInventoryUpdateRequest = {
MultiProgress: unknown[];
}[];
InvasionProgress?: IInvasionProgressClient[];
RJ?: boolean;
ConquestMissionsCompleted?: number;
duviriSuitSelection?: string;
duviriPistolSelection?: string;
@ -185,10 +184,7 @@ export interface IRewardInfo {
NemesisHintProgress?: number;
EOM_AFK?: number;
rewardQualifications?: string; // did a Survival for 5 minutes and this was "1"
rewardTierOverrides?: number[]; // Disruption
PurgatoryRewardQualifications?: string;
POICompletions?: number;
LootDungeonCompletions?: number;
rewardSeed?: number | bigint;
periodicMissionTag?: string;
T?: number; // Duviri

View File

@ -5,14 +5,12 @@ export interface IWorldState {
Version: number; // for goals
BuildLabel: string;
Time: number;
InGameMarket: IInGameMarket;
Goals: IGoal[];
Alerts: [];
Sorties: ISortie[];
LiteSorties: ILiteSortie[];
SyndicateMissions: ISyndicateMissionInfo[];
ActiveMissions: IFissure[];
FlashSales: IFlashSale[];
GlobalUpgrades: IGlobalUpgrade[];
Invasions: IInvasion[];
NodeOverrides: INodeOverride[];
@ -39,73 +37,19 @@ export interface IGoal {
_id: IOid;
Activation: IMongoDate;
Expiry: IMongoDate;
Count?: number;
HealthPct?: number;
Icon: string;
Count: number;
Goal: number;
Success: number;
Personal: boolean;
Bounty?: boolean;
ClampNodeScores?: boolean;
Desc: string;
ToolTip?: string;
Faction?: string;
Goal?: number;
InterimGoals?: number[];
BonusGoal?: number;
ClanGoal?: number[];
Success?: number;
Personal?: boolean;
Community?: boolean;
Best?: boolean; // Fist one on Event Tab
Bounty?: boolean; // Tactical Alert
ClampNodeScores?: boolean;
Transmission?: string;
InstructionalItem?: string;
ItemType?: string;
Icon: string;
Tag: string;
PrereqGoalTags?: string[];
Node?: string;
VictimNode?: string;
ConcurrentMissionKeyNames?: string[];
ConcurrentNodeReqs?: number[];
ConcurrentNodes?: string[];
RegionIdx?: number;
Regions?: number[];
Node: string;
MissionKeyName?: string;
Reward?: IMissionReward;
InterimRewards?: IMissionReward[];
BonusReward?: IMissionReward;
JobAffiliationTag?: string;
Jobs?: ISyndicateJob[];
PreviousJobs?: ISyndicateJob[];
JobCurrentVersion?: IOid;
JobPreviousVersion?: IOid;
ScoreVar?: string;
ScoreMaxTag?: string;
ScoreLocTag?: string;
NightLevel?: string;
}
export interface ISyndicateJob {
jobType?: string;
rewards: string;
masteryReq?: number;
minEnemyLevel: number;
maxEnemyLevel: number;
xpAmounts: number[];
endless?: boolean;
locationTag?: string;
isVault?: boolean;
requiredItems?: string[];
useRequiredItemsAsMiscItemFee?: boolean;
}
export interface ISyndicateMissionInfo {
@ -115,7 +59,17 @@ export interface ISyndicateMissionInfo {
Tag: string;
Seed: number;
Nodes: string[];
Jobs?: ISyndicateJob[];
Jobs?: {
jobType?: string;
rewards: string;
masteryReq: number;
minEnemyLevel: number;
maxEnemyLevel: number;
xpAmounts: number[];
endless?: boolean;
locationTag?: string;
isVault?: boolean;
}[];
}
export interface IGlobalUpgrade {
@ -311,7 +265,6 @@ export interface IEndlessXpChoice {
export interface ISeasonChallenge {
_id: IOid;
Daily?: boolean;
Permanent?: boolean; // only for getPastWeeklyChallenges response
Activation: IMongoDate;
Expiry: IMongoDate;
Challenge: string;
@ -350,37 +303,6 @@ export type TCircuitGameMode =
| "Assassination"
| "Alchemy";
export interface IFlashSale {
TypeName: string;
ShowInMarket: boolean;
HideFromMarket: boolean;
SupporterPack: boolean;
Discount: number;
BogoBuy: number;
BogoGet: number;
PremiumOverride: number;
RegularOverride: number;
ProductExpiryOverride?: IMongoDate;
StartDate: IMongoDate;
EndDate: IMongoDate;
}
export interface IInGameMarket {
LandingPage: ILandingPage;
}
export interface ILandingPage {
Categories: IGameMarketCategory[];
}
export interface IGameMarketCategory {
CategoryName: string;
Name: string;
Icon: string;
AddToMenu?: boolean;
Items?: string[];
}
export interface ITmp {
cavabegin: string;
PurchasePlatformLockEnabled: boolean; // Seems unused

View File

@ -388,11 +388,11 @@
<div class="card" style="height: 400px;">
<h5 class="card-header" data-loc="inventory_hoverboards"></h5>
<div class="card-body overflow-auto">
<form class="input-group mb-3" onsubmit="doAcquireModularEquipment('Hoverboards');return false;">
<input class="form-control" id="acquire-type-Hoverboards-HB_DECK" list="datalist-ModularParts-HB_DECK" />
<input class="form-control" id="acquire-type-Hoverboards-HB_ENGINE" list="datalist-ModularParts-HB_ENGINE" />
<input class="form-control" id="acquire-type-Hoverboards-HB_FRONT" list="datalist-ModularParts-HB_FRONT" />
<input class="form-control" id="acquire-type-Hoverboards-HB_JET" list="datalist-ModularParts-HB_JET" />
<form class="input-group mb-3" onsubmit="doAcquireModularEquipment('HoverBoards');return false;">
<input class="form-control" id="acquire-type-HoverBoards-HB_DECK" list="datalist-ModularParts-HB_DECK" />
<input class="form-control" id="acquire-type-HoverBoards-HB_ENGINE" list="datalist-ModularParts-HB_ENGINE" />
<input class="form-control" id="acquire-type-HoverBoards-HB_FRONT" list="datalist-ModularParts-HB_FRONT" />
<input class="form-control" id="acquire-type-HoverBoards-HB_JET" list="datalist-ModularParts-HB_JET" />
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
</form>
<table class="table table-hover w-100">
@ -663,6 +663,26 @@
<input class="form-check-input" type="checkbox" id="unlockAllScans" />
<label class="form-check-label" for="unlockAllScans" data-loc="cheats_unlockAllScans"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="infiniteCredits" />
<label class="form-check-label" for="infiniteCredits" data-loc="cheats_infiniteCredits"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="infinitePlatinum" />
<label class="form-check-label" for="infinitePlatinum" data-loc="cheats_infinitePlatinum"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="infiniteEndo" />
<label class="form-check-label" for="infiniteEndo" data-loc="cheats_infiniteEndo"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="infiniteRegalAya" />
<label class="form-check-label" for="infiniteRegalAya" data-loc="cheats_infiniteRegalAya"></label>
</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">
<input class="form-check-input" type="checkbox" id="claimingBlueprintRefundsIngredients" />
<label class="form-check-label" for="claimingBlueprintRefundsIngredients" data-loc="cheats_claimingBlueprintRefundsIngredients"></label>
@ -871,28 +891,8 @@
<div class="col-md-6">
<div class="card mb-3">
<h5 class="card-header" data-loc="cheats_account"></h5>
<div class="card-body" id="account-cheats">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="infiniteCredits" />
<label class="form-check-label" for="infiniteCredits" data-loc="cheats_infiniteCredits"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="infinitePlatinum" />
<label class="form-check-label" for="infinitePlatinum" data-loc="cheats_infinitePlatinum"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="infiniteEndo" />
<label class="form-check-label" for="infiniteEndo" data-loc="cheats_infiniteEndo"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="infiniteRegalAya" />
<label class="form-check-label" for="infiniteRegalAya" data-loc="cheats_infiniteRegalAya"></label>
</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="mt-2 mb-2 d-flex flex-wrap gap-2">
<div class="card-body">
<div class="mb-2 d-flex flex-wrap gap-2">
<button class="btn btn-primary" onclick="debounce(doUnlockAllMissions);" data-loc="cheats_unlockAllMissions"></button>
<button class="btn btn-primary" onclick="debounce(markAllAsRead);" data-loc="cheats_markAllAsRead"></button>
<button class="btn btn-primary" onclick="doUnlockAllFocusSchools();" data-loc="cheats_unlockAllFocusSchools"></button>
@ -937,57 +937,8 @@
<input class="form-check-input" type="checkbox" id="worldState.varziaFullyStocked" />
<label class="form-check-label" for="worldState.varziaFullyStocked" data-loc="worldState_varziaFullyStocked"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="worldState.wolfHunt" />
<label class="form-check-label" for="worldState.wolfHunt" data-loc="worldState_wolfHunt"></label>
<abbr data-loc-inc="worldState_galleonOfGhouls"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="worldState.longShadow" />
<label class="form-check-label" for="worldState.longShadow" data-loc="worldState_longShadow"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="worldState.hallowedFlame" />
<label class="form-check-label" for="worldState.hallowedFlame" data-loc="worldState_hallowedFlame"></label>
<abbr data-loc-inc="worldState_hallowedNightmares|worldState_dogDays"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
</div>
<div class="form-group mt-2 d-flex gap-2">
<div class="flex-fill">
<label class="form-label" for="worldState.hallowedNightmares" data-loc="worldState_hallowedNightmares"></label>
<abbr data-loc-inc="worldState_hallowedFlame|worldState_dogDays"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
<select class="form-control" id="worldState.hallowedNightmares" data-default="false">
<option value="true" data-loc="enabled"></option>
<option value="false" data-loc="disabled"></option>
</select>
</div>
<div class="flex-fill">
<label class="form-label" for="worldState.hallowedNightmaresRewardsOverride" data-loc="worldState_hallowedNightmaresRewards"></label>
<select class="form-control" id="worldState.hallowedNightmaresRewardsOverride" data-default="0">
<option value="0" data-loc="worldState_from_year" data-loc-year="2018"></option>
<option value="1" data-loc="worldState_from_year" data-loc-year="2016"></option>
<option value="2" data-loc="worldState_from_year" data-loc-year="2015"></option>
</select>
</div>
</div>
<div class="form-group mt-2 d-flex gap-2">
<div class="flex-fill">
<label class="form-label" for="worldState.proxyRebellion" data-loc="worldState_proxyRebellion"></label>
<select class="form-control" id="worldState.proxyRebellion" data-default="false">
<option value="true" data-loc="enabled"></option>
<option value="false" data-loc="disabled"></option>
</select>
</div>
<div class="flex-fill">
<label class="form-label" for="worldState.proxyRebellionRewardsOverride" data-loc="worldState_proxyRebellionRewards"></label>
<select class="form-control" id="worldState.proxyRebellionRewardsOverride" data-default="0">
<option value="0" data-loc="worldState_from_year" data-loc-year="2019"></option>
<option value="1" data-loc="worldState_from_year" data-loc-year="2018"></option>
</select>
</div>
</div>
<div class="form-group mt-2">
<label class="form-label" for="worldState.galleonOfGhouls" data-loc="worldState_galleonOfGhouls"></label>
<abbr data-loc-inc="worldState_wolfHunt"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
<select class="form-control" id="worldState.galleonOfGhouls" data-default="0">
<option value="0" data-loc="disabled"></option>
<option value="1" data-loc="worldState_we1"></option>
@ -995,22 +946,6 @@
<option value="3" data-loc="worldState_we3"></option>
</select>
</div>
<div class="form-group mt-2">
<label class="form-label" for="worldState.ghoulEmergenceOverride" data-loc="worldState_ghoulEmergence"></label>
<select class="form-control" id="worldState.ghoulEmergenceOverride" data-default="null">
<option value="null" data-loc="normal"></option>
<option value="true" data-loc="enabled"></option>
<option value="false" data-loc="disabled"></option>
</select>
</div>
<div class="form-group mt-2">
<label class="form-label" for="worldState.plagueStarOverride" data-loc="worldState_plagueStar"></label>
<select class="form-control" id="worldState.plagueStarOverride" data-default="null">
<option value="null" data-loc="normal"></option>
<option value="true" data-loc="enabled"></option>
<option value="false" data-loc="disabled"></option>
</select>
</div>
<div class="form-group mt-2">
<label class="form-label" for="worldState.starDaysOverride" data-loc="worldState_starDays"></label>
<select class="form-control" id="worldState.starDaysOverride" data-default="null">
@ -1019,53 +954,6 @@
<option value="false" data-loc="disabled"></option>
</select>
</div>
<div class="form-group mt-2 d-flex gap-2">
<div class="flex-fill">
<label class="form-label" for="worldState.dogDaysOverride" data-loc="worldState_dogDays"></label>
<abbr data-loc-inc="worldState_hallowedFlame|worldState_hallowedNightmares"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
<select class="form-control" id="worldState.dogDaysOverride" data-default="null">
<option value="null" data-loc="normal"></option>
<option value="true" data-loc="enabled"></option>
<option value="false" data-loc="disabled"></option>
</select>
</div>
<div class="flex-fill">
<label class="form-label" for="worldState.dogDaysRewardsOverride" data-loc="worldState_dogDaysRewards"></label>
<select class="form-control" id="worldState.dogDaysRewardsOverride" data-default="null">
<option value="null" data-loc="normal"></option>
<option value="3" data-loc="worldState_from_year" data-loc-year="2025"></option>
<option value="2" data-loc="worldState_from_year" data-loc-year="2024"></option>
<option value="1" data-loc="worldState_from_year" data-loc-year="2023"></option>
<option value="0" data-loc="worldState_pre_year" data-loc-year="2023"></option>
</select>
</div>
</div>
<div class="form-group mt-2 d-flex gap-2">
<div class="flex-fill">
<label class="form-label" for="worldState.bellyOfTheBeast" data-loc="worldState_bellyOfTheBeast"></label>
<select class="form-control" id="worldState.bellyOfTheBeast" data-default="false">
<option value="true" data-loc="enabled"></option>
<option value="false" data-loc="disabled"></option>
</select>
</div>
<div class="flex-fill">
<label class="form-label" for="worldState.bellyOfTheBeastProgressOverride" data-loc="worldState_bellyOfTheBeastProgressOverride"></label>
<input id="worldState.bellyOfTheBeastProgressOverride" class="form-control" type="number" min="0" max="100" data-default="0" />
</div>
</div>
<div class="form-group mt-2 d-flex gap-2">
<div class="flex-fill">
<label class="form-label" for="worldState.eightClaw" data-loc="worldState_eightClaw"></label>
<select class="form-control" id="worldState.eightClaw" data-default="false">
<option value="true" data-loc="enabled"></option>
<option value="false" data-loc="disabled"></option>
</select>
</div>
<div class="flex-fill">
<label class="form-label" for="worldState.eightClawProgressOverride" data-loc="worldState_eightClawProgressOverride"></label>
<input id="worldState.eightClawProgressOverride" class="form-control" type="number" min="0" max="100" data-default="0" />
</div>
</div>
<div class="form-group mt-2">
<label class="form-label" for="worldState.eidolonOverride" data-loc="worldState_eidolonOverride"></label>
<select class="form-control" id="worldState.eidolonOverride" data-default="">
@ -1147,10 +1035,7 @@
</div>
</div>
<div data-route="/webui/import" data-title="Import | OpenWF WebUI">
<p>
<span data-loc="import_importNote"></span>
<span data-loc="import_importNote2"></span>
</p>
<p data-loc="import_importNote"></p>
<textarea class="form-control" id="import-inventory" style="height: calc(100vh - 300px)"></textarea>
<button class="btn btn-primary mt-3" onclick="doImport();" data-loc="import_submit"></button>
<p class="mt-3 mb-1" data-loc="import_samples"></p>

View File

@ -18,7 +18,7 @@ const sendAuth = isRegister => {
window.ws.send(
JSON.stringify({
auth: {
email: localStorage.getItem("email").toLowerCase(),
email: localStorage.getItem("email"),
password: wp.encSync(localStorage.getItem("password")),
isRegister
}
@ -28,8 +28,7 @@ const sendAuth = isRegister => {
};
function openWebSocket() {
const wsProto = location.protocol === "https:" ? "wss://" : "ws://";
window.ws = new WebSocket(wsProto + location.host + "/custom/ws");
window.ws = new WebSocket("/custom/ws");
window.ws.onopen = () => {
ws_is_open = true;
sendAuth(false);
@ -202,17 +201,6 @@ function updateLocElements() {
document.querySelectorAll("[data-loc-placeholder]").forEach(elm => {
elm.placeholder = loc(elm.getAttribute("data-loc-placeholder"));
});
document.querySelectorAll("[data-loc-inc]").forEach(elm => {
const incWith = elm
.getAttribute("data-loc-inc")
.split("|")
.map(key => loc(key))
.join(", ");
elm.title = `${loc("worldState_incompatibleWith")} ${incWith}`;
});
document.querySelectorAll("[data-loc-year]").forEach(elm => {
elm.innerHTML = elm.innerHTML.replace("|YEAR|", elm.getAttribute("data-loc-year"));
});
}
function setActiveLanguage(lang) {
@ -223,7 +211,7 @@ function setActiveLanguage(lang) {
document.querySelector("[data-lang=" + lang + "]").classList.add("active");
window.dictPromise = new Promise(resolve => {
const webui_lang = ["en", "ru", "fr", "de", "zh", "es", "uk"].indexOf(lang) == -1 ? "en" : lang;
const webui_lang = ["en", "ru", "fr", "de", "zh", "es"].indexOf(lang) == -1 ? "en" : lang;
let script = document.getElementById("translations");
if (script) document.documentElement.removeChild(script);
@ -508,9 +496,6 @@ function fetchItemList() {
uniqueLevelCaps = items;
} else if (type == "Syndicates") {
items.forEach(item => {
if (item.uniqueName === "ConclaveSyndicate") {
return;
}
if (item.uniqueName.startsWith("RadioLegion")) {
item.name += " (" + item.uniqueName + ")";
}
@ -605,8 +590,6 @@ function fetchItemList() {
}
fetchItemList();
const accountCheats = document.querySelectorAll("#account-cheats input[id]");
// Assumes that caller revalidates authz
function updateInventory() {
const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
@ -1307,10 +1290,7 @@ function updateInventory() {
abilityOverrideFormLabel.setAttribute("data-loc", "abilityOverride_label");
abilityOverrideFormLabel.innerHTML = loc("abilityOverride_label");
abilityOverrideFormLabel.classList = "form-label";
abilityOverrideFormLabel.setAttribute(
"for",
`abilityOverride-ability-config-${i}`
);
abilityOverrideFormLabel.setAttribute("for", "abilityOverride-ability");
abilityOverrideForm.appendChild(abilityOverrideFormLabel);
const abilityOverrideInputGroup = document.createElement("div");
@ -1318,7 +1298,7 @@ function updateInventory() {
abilityOverrideForm.appendChild(abilityOverrideInputGroup);
const abilityOverrideInput = document.createElement("input");
abilityOverrideInput.id = `abilityOverride-ability-config-${i}`;
abilityOverrideInput.id = "abilityOverride-ability";
abilityOverrideInput.classList = "form-control";
abilityOverrideInput.setAttribute("list", "datalist-Abilities");
if (config.AbilityOverride) {
@ -1338,7 +1318,7 @@ function updateInventory() {
abilityOverrideInputGroup.appendChild(abilityOverrideOnSlot);
const abilityOverrideSecondInput = document.createElement("input");
abilityOverrideSecondInput.id = `abilityOverride-ability-index-config-${i}`;
abilityOverrideSecondInput.id = "abilityOverride-ability-index";
abilityOverrideSecondInput.classList = "form-control";
abilityOverrideSecondInput.setAttribute("type", "number");
abilityOverrideSecondInput.setAttribute("min", "0");
@ -1475,10 +1455,6 @@ function updateInventory() {
}
document.getElementById("Boosters-list").appendChild(tr);
});
for (const elm of accountCheats) {
elm.checked = !!data[elm.id];
}
});
});
}
@ -2115,8 +2091,6 @@ function doAcquireModMax() {
alert("doAcquireModMax: " + uniqueName);
}
// Cheats route
const uiConfigs = [...$(".config-form input[id], .config-form select[id]")].map(x => x.id);
for (const id of uiConfigs) {
@ -2201,6 +2175,8 @@ function doSaveConfigStringArray(id) {
});
}
// Cheats route
single.getRoute("/webui/cheats").on("beforeload", function () {
let interval;
interval = setInterval(() => {
@ -2312,23 +2288,6 @@ function doIntrinsicsUnlockAll() {
});
}
document.querySelectorAll("#account-cheats input[type=checkbox]").forEach(elm => {
elm.onchange = function () {
revalidateAuthz().then(() => {
$.post({
url: "/custom/setAccountCheat?" + window.authz /*+ "&wsid=" + wsid*/,
contentType: "application/json",
data: JSON.stringify({
key: elm.id,
value: elm.checked
})
});
});
};
});
// Mods route
function doAddAllMods() {
let modsAll = new Set();
for (const child of document.getElementById("datalist-mods").children) {
@ -3127,8 +3086,8 @@ function handleAbilityOverride(event, configIndex) {
event.preventDefault();
const urlParams = new URLSearchParams(window.location.search);
const action = event.submitter.value;
const Ability = getKey(document.getElementById(`abilityOverride-ability-config-${configIndex}`));
const Index = document.getElementById(`abilityOverride-ability-index-config-${configIndex}`).value;
const Ability = getKey(document.getElementById("abilityOverride-ability"));
const Index = document.getElementById("abilityOverride-ability-index").value;
revalidateAuthz().then(() => {
$.post({
url: "/custom/abilityOverride?" + window.authz,

View File

@ -11,8 +11,7 @@
margin-left: 7rem;
}
body.logged-in:has([data-lang="de"].active) #main-content,
body.logged-in:has([data-lang="uk"].active) #main-content {
body.logged-in:has([data-lang="de"].active) #main-content {
margin-left: 8rem;
}
@ -29,12 +28,9 @@ body:not(.logged-in) .user-dropdown {
display: none;
}
/* font awesome icons */
svg {
td.text-end > a > svg {
fill: currentColor;
height: 1em;
}
td.text-end > a > svg {
margin-left: 0.5em;
margin-bottom: 4px; /* to centre the icon */
}

View File

@ -242,29 +242,11 @@ dict = {
worldState_creditBoost: `Event Booster: Credit`,
worldState_affinityBoost: `Event Booster: Erfahrung`,
worldState_resourceBoost: `Event Booster: Ressourcen`,
worldState_tennoLiveRelay: `TennoLive Relais`,
worldState_baroTennoConRelay: `Baros TennoCon Relais`,
worldState_tennoLiveRelay: `[UNTRANSLATED] TennoLive Relay`,
worldState_baroTennoConRelay: `[UNTRANSLATED] Baro's TennoCon Relay`,
worldState_starDays: `Sternen-Tage`,
worldState_galleonOfGhouls: `Galeone der Ghule`,
worldState_ghoulEmergence: `Ghul Ausrottung`,
worldState_plagueStar: `Plagenstern`,
worldState_dogDays: `Hitzefrei`,
worldState_dogDaysRewards: `[UNTRANSLATED] Dog Days Rewards`,
worldState_wolfHunt: `Wolfsjagd (2025)`,
worldState_longShadow: `Lange Schatten`,
worldState_hallowedFlame: `Geweihte Flamme`,
worldState_hallowedNightmares: `Geweihte Albträume`,
worldState_hallowedNightmaresRewards: `[UNTRANSLATED] Hallowed Nightmares Rewards`,
worldState_proxyRebellion: `Proxy-Rebellion`,
worldState_proxyRebellionRewards: `[UNTRANSLATED] Proxy Rebellion Rewards`,
worldState_bellyOfTheBeast: `Das Innere der Bestie`,
worldState_bellyOfTheBeastProgressOverride: `[UNTRANSLATED] Belly of the Beast Progress`,
worldState_eightClaw: `Acht Klauen`,
worldState_eightClawProgressOverride: `[UNTRANSLATED] Eight Claw Progress`,
worldState_from_year: `[UNTRANSLATED] from |YEAR|`,
worldState_pre_year: `[UNTRANSLATED] pre |YEAR|`,
worldState_incompatibleWith: `[UNTRANSLATED] Incompatible with:`,
enabled: `Aktiviert`,
enabled: `[UNTRANSLATED] Enabled`,
disabled: `Deaktiviert`,
worldState_we1: `Wochenende 1`,
worldState_we2: `Wochenende 2`,
@ -307,8 +289,7 @@ dict = {
worldState_varziaFullyStocked: `Varzia hat volles Inventar`,
worldState_varziaOverride: `Varzia-Angebotsüberschreibung`,
import_importNote: `[UNTRANSLATED] You can provide a full or partial <code>inventory.php</code> or <code>getShip.php</code> response (client representation) here.`,
import_importNote2: `Alle Felder, die vom Importer unterstützt werden, <b>werden in deinem Account überschrieben</b>.`,
import_importNote: `Du kannst hier eine vollständige oder teilweise Inventarantwort (Client-Darstellung) einfügen. Alle Felder, die vom Importer unterstützt werden, <b>werden in deinem Account überschrieben</b>.`,
import_submit: `Absenden`,
import_samples: `Beispiele:`,
import_samples_maxFocus: `Alle Fokus-Schulen maximiert`,

View File

@ -245,24 +245,6 @@ dict = {
worldState_baroTennoConRelay: `Baro's TennoCon Relay`,
worldState_starDays: `Star Days`,
worldState_galleonOfGhouls: `Galleon of Ghouls`,
worldState_ghoulEmergence: `Ghoul Purge`,
worldState_plagueStar: `Plague Star`,
worldState_dogDays: `Dog Days`,
worldState_dogDaysRewards: `Dog Days Rewards`,
worldState_wolfHunt: `Wolf Hunt (2025)`,
worldState_longShadow: `Long Shadow`,
worldState_hallowedFlame: `Hallowed Flame`,
worldState_hallowedNightmares: `Hallowed Nightmares`,
worldState_hallowedNightmaresRewards: `Hallowed Nightmares Rewards`,
worldState_proxyRebellion: `Proxy Rebellion`,
worldState_proxyRebellionRewards: `Proxy Rebellion Rewards`,
worldState_bellyOfTheBeast: `Belly of the Beast`,
worldState_bellyOfTheBeastProgressOverride: `Belly of the Beast Progress`,
worldState_eightClaw: `Eight Claw`,
worldState_eightClawProgressOverride: `Eight Claw Progress`,
worldState_from_year: `from |YEAR|`,
worldState_pre_year: `pre |YEAR|`,
worldState_incompatibleWith: `Incompatible with:`,
enabled: `Enabled`,
disabled: `Disabled`,
worldState_we1: `Weekend 1`,
@ -306,8 +288,7 @@ dict = {
worldState_varziaFullyStocked: `Varzia Fully Stocked`,
worldState_varziaOverride: `Varzia Rotation Override`,
import_importNote: `You can provide a full or partial <code>inventory.php</code> or <code>getShip.php</code> response (client representation) here.`,
import_importNote2: `All fields that are supported by the importer <b>will be overwritten</b> in your account.`,
import_importNote: `You can provide a full or partial inventory response (client respresentation) here. All fields that are supported by the importer <b>will be overwritten</b> in your account.`,
import_submit: `Submit`,
import_samples: `Samples:`,
import_samples_maxFocus: `All Focus Schools Maxed Out`,

View File

@ -36,7 +36,7 @@ dict = {
code_succRemoved: `Eliminado exitosamente.`,
code_buffsNumber: `Cantidad de mejoras`,
code_cursesNumber: `Cantidad de maldiciones`,
code_rerollsNumber: `Cantidad de rerolls`,
code_rerollsNumber: `Cantidad de reintentos`,
code_viewStats: `Ver estadísticas`,
code_rank: `Rango`,
code_rankUp: `Subir de rango`,
@ -121,11 +121,11 @@ dict = {
currency_PrimeTokens: `Aya Real`,
currency_owned: `Tienes |COUNT|.`,
detailedView_archonShardsLabel: `Ranuras de Fragmento de Arconte`,
detailedView_archonShardsLabel: `Ranuras de Fragmento de Archón`,
detailedView_archonShardsDescription: `Puedes usar estas ranuras ilimitadas para aplicar una amplia variedad de mejoras`,
detailedView_archonShardsDescription2: `Ten en cuenta que cada fragmento de arconte tarda un poco en aplicarse al cargar`,
detailedView_valenceBonusLabel: `Bonus de Valéncia`,
detailedView_valenceBonusDescription: `Puedes establecer o quitar el bonus de valencia de tu arma.`,
detailedView_archonShardsDescription2: `Ten en cuenta que cada fragmento de archón tarda un poco en aplicarse al cargar`,
detailedView_valenceBonusLabel: `Bônus de Valência`,
detailedView_valenceBonusDescription: `Puedes establecer o quitar el bono de valencia de tu arma.`,
detailedView_modularPartsLabel: `Cambiar partes modulares`,
detailedView_suitInvigorationLabel: `Vigorización de Warframe`,
detailedView_loadoutLabel: `Equipamientos`,
@ -156,8 +156,8 @@ dict = {
invigorations_defensiveLabel: `Mejora Defensiva`,
invigorations_expiryLabel: `Caducidad de Mejoras (opcional)`,
abilityOverride_label: `Intercambio de Habilidad`,
abilityOverride_onSlot: `en el espacio`,
abilityOverride_label: `[UNTRANSLATED] Ability Override`,
abilityOverride_onSlot: `[UNTRANSLATED] on slot`,
mods_addRiven: `Agregar Agrietado`,
mods_fingerprint: `Huella digital`,
@ -180,18 +180,18 @@ dict = {
cheats_infiniteEndo: `Endo infinito`,
cheats_infiniteRegalAya: `Aya Real infinita`,
cheats_infiniteHelminthMaterials: `Materiales Helminto infinitos`,
cheats_claimingBlueprintRefundsIngredients: `Reclamar planos devuelve los ingredientes`,
cheats_dontSubtractPurchaseCreditCost: `No restar costo en créditos al comprar`,
cheats_dontSubtractPurchasePlatinumCost: `No restar costo en platino al comprar`,
cheats_dontSubtractPurchaseItemCost: `No restar costo de ítem al comprar`,
cheats_dontSubtractPurchaseStandingCost: `No restar costo en reputación al comprar`,
cheats_claimingBlueprintRefundsIngredients: `Reclamar ingredientes devueltos por planos`,
cheats_dontSubtractPurchaseCreditCost: `No restar costo en créditos de la compra`,
cheats_dontSubtractPurchasePlatinumCost: `No restar costo en platino de la compra`,
cheats_dontSubtractPurchaseItemCost: `No restar costo de ítem en la compra`,
cheats_dontSubtractPurchaseStandingCost: `No restar costo en reputación de la compra`,
cheats_dontSubtractVoidTraces: `No descontar vestigios del Vacío`,
cheats_dontSubtractConsumables: `No restar consumibles`,
cheats_unlockAllShipFeatures: `Desbloquear todas las funciones de nave`,
cheats_unlockAllShipDecorations: `Desbloquear todas las decoraciones de nave`,
cheats_unlockAllFlavourItems: `Desbloquear todos los <abbr title="Conjuntos de animaciones, glifos, paletas, etc.">ítems estéticos</abbr>`,
cheats_unlockAllSkins: `Desbloquear todas las skins`,
cheats_unlockAllCapturaScenes: `Desbloquear todas las escenas de Captura`,
cheats_unlockAllSkins: `Desbloquear todas las apariencias`,
cheats_unlockAllCapturaScenes: `Desbloquear todas las escenas Captura`,
cheats_unlockAllDecoRecipes: `Desbloquear todas las recetas decorativas del dojo`,
cheats_universalPolarityEverywhere: `Polaridad universal en todas partes`,
cheats_unlockDoubleCapacityPotatoesEverywhere: `Patatas en todas partes`,
@ -208,7 +208,7 @@ dict = {
cheats_baroAlwaysAvailable: `Baro siempre disponible`,
cheats_baroFullyStocked: `Baro con stock completo`,
cheats_syndicateMissionsRepeatable: `Misiones de sindicato rejugables`,
cheats_unlockAllProfitTakerStages: `Desbloquea todas las etapas del Roba-ganancias`,
cheats_unlockAllProfitTakerStages: `Deslobquea todas las etapas del Roba-ganancias`,
cheats_instantFinishRivenChallenge: `Terminar desafío de agrietado inmediatamente`,
cheats_instantResourceExtractorDrones: `Drones de extracción de recursos instantáneos`,
cheats_noResourceExtractorDronesDamage: `Sin daño a los drones extractores de recursos`,
@ -242,29 +242,11 @@ dict = {
worldState_creditBoost: `Potenciador de Créditos`,
worldState_affinityBoost: `Potenciador de Afinidad`,
worldState_resourceBoost: `Potenciador de Recursos`,
worldState_tennoLiveRelay: `Repetidor de TennoLive`,
worldState_baroTennoConRelay: `Repetidor de Baro de la TennoCon`,
worldState_tennoLiveRelay: `[UNTRANSLATED] TennoLive Relay`,
worldState_baroTennoConRelay: `[UNTRANSLATED] Baro's TennoCon Relay`,
worldState_starDays: `Días estelares`,
worldState_galleonOfGhouls: `Galeón de Gules`,
worldState_ghoulEmergence: `Purga de Gules`,
worldState_plagueStar: `Estrella Infestada`,
worldState_dogDays: `Canícula`,
worldState_dogDaysRewards: `Recompensas de Canícula`,
worldState_wolfHunt: `Cacería del Lobo (2025)`,
worldState_longShadow: `Sombra Prolongada`,
worldState_hallowedFlame: `Llama Sagrada`,
worldState_hallowedNightmares: `Pesadillas Sagradas`,
worldState_hallowedNightmaresRewards: `Recompensas de Pesadillas Sagradas`,
worldState_proxyRebellion: `Rebelión Proxy`,
worldState_proxyRebellionRewards: `Recompensas de Rebelión Proxy`,
worldState_bellyOfTheBeast: `Vientre de la Bestia`,
worldState_bellyOfTheBeastProgressOverride: `[UNTRANSLATED] Belly of the Beast Progress`,
worldState_eightClaw: `Octava Garra`,
worldState_eightClawProgressOverride: `[UNTRANSLATED] Eight Claw Progress`,
worldState_from_year: `de |YEAR|`,
worldState_pre_year: `antes de |YEAR|`,
worldState_incompatibleWith: `No compatible con:`,
enabled: `Activado`,
enabled: `[UNTRANSLATED] Enabled`,
disabled: `Desactivado`,
worldState_we1: `Semana 1`,
worldState_we2: `Semana 2`,
@ -307,8 +289,7 @@ dict = {
worldState_varziaFullyStocked: `Varzia con stock completo`,
worldState_varziaOverride: `Cambio en rotación de Varzia`,
import_importNote: `[UNTRANSLATED] You can provide a full or partial <code>inventory.php</code> or <code>getShip.php</code> response (client representation) here.`,
import_importNote2: `Todos los campos compatibles con el importador <b>serán sobrescritos</b> en tu cuenta.`,
import_importNote: `Puedes proporcionar una respuesta de inventario completa o parcial (representación del cliente) aquí. Todos los campos compatibles con el importador <b>serán sobrescritos</b> en tu cuenta.`,
import_submit: `Enviar`,
import_samples: `Muestras:`,
import_samples_maxFocus: `Todas las escuelas de enfoque al máximo`,
@ -323,7 +304,7 @@ dict = {
upgrade_WarframeBlastProc: `+|VAL| de escudos al matar con daño de explosión`,
upgrade_WarframeCastingSpeed: `+|VAL|% de velocidad de lanzamiento de habilidades`,
upgrade_WarframeCorrosiveDamageBoost: `+|VAL|% de daño de habilidades a enemigos con estado corrosivo`,
upgrade_WarframeCorrosiveStack: `Aumenta los stacks máximos de estado corrosivo en +|VAL|`,
upgrade_WarframeCorrosiveStack: `Aumenta los acumuladores máximos de estado corrosivo en +|VAL|`,
upgrade_WarframeCritDamageBoost: `+|VAL|% de daño crítico cuerpo a cuerpo (se duplica con más de 500 de energía)`,
upgrade_WarframeElectricDamage: `+|VAL1|% de daño eléctrico en armas primarias (+|VAL2|% por fragmento adicional)`,
upgrade_WarframeElectricDamageBoost: `+|VAL|% de daño de habilidades a enemigos con estado eléctrico`,
@ -347,30 +328,30 @@ dict = {
upgrade_AvatarLootRadar: `+7m de radar de botín`,
upgrade_WeaponAmmoMax: `+15% de munición máxima`,
upgrade_EnemyArmorReductionAura: `-3% de armadura enemiga`,
upgrade_OnExecutionAmmo: `Recarga al 100% el cargador primario y secundario tras ejecución (Mercy)`,
upgrade_OnExecutionHealthDrop: `100% de probabilidad de soltar un orbe de salud tras ejecución (Mercy)`,
upgrade_OnExecutionEnergyDrop: `50% de probabilidad de soltar un orbe de energía tras ejecución (Mercy)`,
upgrade_OnExecutionAmmo: `Recarga al 100% el cargador primario y secundario tras ejecución (Misericordia)`,
upgrade_OnExecutionHealthDrop: `100% de probabilidad de soltar un orbe de salud tras ejecución (Misericordia)`,
upgrade_OnExecutionEnergyDrop: `50% de probabilidad de soltar un orbe de energía tras ejecución (Misericordia)`,
upgrade_OnFailHackReset: `+50% de probabilidad de reintento al fallar un hackeo`,
upgrade_DamageReductionOnHack: `75% de reducción de daño al hackear`,
upgrade_OnExecutionReviveCompanion: `Las ejecuciones reducen el tiempo de recuperación del compañero en 15s`,
upgrade_OnExecutionParkourSpeed: `+60% de velocidad de parkour durante 15s tras una ejecución (Mercy)`,
upgrade_OnExecutionParkourSpeed: `+60% de velocidad de parkour durante 15s tras una ejecución`,
upgrade_AvatarTimeLimitIncrease: `+8s para hackear`,
upgrade_ElectrifyOnHack: `Electrocuta a los enemigos en un radio de 20m al hackear`,
upgrade_OnExecutionTerrify: `50% de probabilidad de que enemigos en un radio de 15m entren en pánico por 8s tras una ejecución (Mercy)`,
upgrade_OnExecutionTerrify: `50% de probabilidad de que enemigos en un radio de 15m entren en pánico por 8s tras una ejecución`,
upgrade_OnHackLockers: `Desbloquea 5 casilleros en un radio de 20m tras hackear`,
upgrade_OnExecutionBlind: `Ciega a los enemigos en un radio de 18m tras una ejecución (Mercy)`,
upgrade_OnExecutionDrainPower: `La próxima habilidad usada gana +50% de fuerza al realizar tras una ejecución (Mercy)`,
upgrade_OnExecutionBlind: `Ciega a los enemigos en un radio de 18m tras una ejecución`,
upgrade_OnExecutionDrainPower: `La próxima habilidad usada gana +50% de fuerza al realizar un remate (Mercy)`,
upgrade_OnHackSprintSpeed: `+75% de velocidad de carrera durante 15s después de hackear`,
upgrade_SwiftExecute: `+50% de velocidad al ejecutar remates (Mercy)`,
upgrade_OnHackInvis: `Invisible durante 15 segundos después de hackear`,
damageType_Electricity: `Eletricidad`,
damageType_Fire: `Calor`,
damageType_Freeze: `Frío`,
damageType_Impact: `Impacto`,
damageType_Electricity: `Eletricidade`,
damageType_Fire: `Ígneo`,
damageType_Freeze: `Glacial`,
damageType_Impact: `Colisivo`,
damageType_Magnetic: `Magnético`,
damageType_Poison: `Tóxico`,
damageType_Radiation: `Radiactivo`,
damageType_Radiation: `Radioativo`,
theme_dark: `Tema Oscuro`,
theme_light: `Tema Claro`,

View File

@ -156,8 +156,8 @@ dict = {
invigorations_defensiveLabel: `Amélioration défensive`,
invigorations_expiryLabel: `Expiration de l'invigoration (optionnel)`,
abilityOverride_label: `Remplacement de pouvoir`,
abilityOverride_onSlot: `Sur l'emplacement`,
abilityOverride_label: `[UNTRANSLATED] Ability Override`,
abilityOverride_onSlot: `[UNTRANSLATED] on slot`,
mods_addRiven: `Ajouter un riven`,
mods_fingerprint: `Empreinte`,
@ -242,29 +242,11 @@ dict = {
worldState_creditBoost: `Booster de Crédit`,
worldState_affinityBoost: `Booster d'Affinité`,
worldState_resourceBoost: `Booster de Ressource`,
worldState_tennoLiveRelay: `Relais TennoLive`,
worldState_baroTennoConRelay: `Relais Baro TennoCon`,
worldState_tennoLiveRelay: `[UNTRANSLATED] TennoLive Relay`,
worldState_baroTennoConRelay: `[UNTRANSLATED] Baro's TennoCon Relay`,
worldState_starDays: `Jours Stellaires`,
worldState_galleonOfGhouls: `Galion des Goules`,
worldState_ghoulEmergence: `Purge des Goules`,
worldState_plagueStar: `Fléau Céleste`,
worldState_dogDays: `Bataille d'Eau`,
worldState_dogDaysRewards: `[UNTRANSLATED] Dog Days Rewards`,
worldState_wolfHunt: `Chasse au Loup (2025)`,
worldState_longShadow: `La Propagation des Ombres`,
worldState_hallowedFlame: `Flamme Hantée`,
worldState_hallowedNightmares: `Cauchemars Hantés`,
worldState_hallowedNightmaresRewards: `[UNTRANSLATED] Hallowed Nightmares Rewards`,
worldState_proxyRebellion: `Rébellion Proxy`,
worldState_proxyRebellionRewards: `[UNTRANSLATED] Proxy Rebellion Rewards`,
worldState_bellyOfTheBeast: `Ventre de la Bête`,
worldState_bellyOfTheBeastProgressOverride: `[UNTRANSLATED] Belly of the Beast Progress`,
worldState_eightClaw: `Huitième Griffe`,
worldState_eightClawProgressOverride: `[UNTRANSLATED] Eight Claw Progress`,
worldState_from_year: `[UNTRANSLATED] from |YEAR|`,
worldState_pre_year: `[UNTRANSLATED] pre |YEAR|`,
worldState_incompatibleWith: `[UNTRANSLATED] Incompatible with:`,
enabled: `Activé`,
enabled: `[UNTRANSLATED] Enabled`,
disabled: `Désactivé`,
worldState_we1: `Weekend 1`,
worldState_we2: `Weekend 2`,
@ -307,8 +289,7 @@ dict = {
worldState_varziaFullyStocked: `Stock de Varzia au max`,
worldState_varziaOverride: `Rotation de Varzia`,
import_importNote: `[UNTRANSLATED] You can provide a full or partial <code>inventory.php</code> or <code>getShip.php</code> response (client representation) here.`,
import_importNote2: `[UNTRANSLATED] All fields that are supported by the importer <b>will be overwritten</b> in your account.`,
import_importNote: `Import manuel. Toutes les modifcations supportées par l'inventaire <b>écraseront celles présentes dans la base de données</b>.`,
import_submit: `Soumettre`,
import_samples: `Échantillons :`,
import_samples_maxFocus: `Toutes les écoles de focus au rang max`,

View File

@ -1,14 +1,14 @@
// Russian translation by AMelonInsideLemon, LoseFace
// Russian translation by AMelonInsideLemon
dict = {
general_inventoryUpdateNote: `Примечание: Чтобы увидеть изменения в игре, вам нужно повторно синхронизировать свой инвентарь, например, используя команду /sync загрузчика, посетив Додзё/Реле или перезагрузив игру.`,
general_inventoryUpdateNote: `[UNTRANSLATED] Note: To see changes in-game, you need to resync your inventory, e.g. using the bootstrapper's /sync command, visiting a dojo/relay, or relogging.`,
general_addButton: `Добавить`,
general_setButton: `Установить`,
general_none: `Отсутствует`,
general_bulkActions: `Массовые действия`,
general_loading: `Загрузка...`,
general_loading: `[UNTRANSLATED] Loading...`,
code_loginFail: `Не удалось войти. Проверьте адрес электронной почты и пароль.`,
code_regFail: `Не удалось зарегистрироваться. Учетная запись уже существует?`,
code_loginFail: `[UNTRANSLATED] Login failed. Double-check the email and password.`,
code_regFail: `[UNTRANSLATED] Registration failed. Account already exists?`,
code_changeNameConfirm: `Какое имя вы хотите установить для своей учетной записи?`,
code_deleteAccountConfirm: `Вы уверены, что хотите удалить аккаунт |DISPLAYNAME| (|EMAIL|)? Это действие нельзя отменить.`,
code_archgun: `Арч-Пушка`,
@ -25,35 +25,35 @@ dict = {
code_traumaticPeculiar: `Травмирующая Странность`,
code_starter: `|MOD| (Повреждённый)`,
code_badItem: `(Самозванец)`,
code_maxRank: `Макс. ранг`,
code_maxRank: `Максимальный ранг`,
code_rename: `Переименовать`,
code_renamePrompt: `Введите новое имя:`,
code_remove: `Удалить`,
code_addItemsConfirm: `Вы уверены, что хотите добавить |COUNT| предметов на ваш аккаунт?`,
code_succRankUp: `Ранг успешно повышен.`,
code_succRankUp: `Ранг успешно повышен`,
code_noEquipmentToRankUp: `Нет снаряжения для повышения ранга.`,
code_succAdded: `Успешно добавлено.`,
code_succRemoved: `Успешно удалено.`,
code_buffsNumber: `Количество позитивных эффектов`,
code_cursesNumber: `Количество негативных эффектов`,
code_rerollsNumber: `Количество рероллов`,
code_buffsNumber: `Количество усилений`,
code_cursesNumber: `Количество проклятий`,
code_rerollsNumber: `Количество циклов`,
code_viewStats: `Просмотр характеристики`,
code_rank: `Ранг`,
code_rankUp: `Повысить ранг`,
code_rankDown: `Понизить ранг`,
code_rankUp: `Повысить Ранг`,
code_rankDown: `Понизить Ранг`,
code_count: `Количество`,
code_focusAllUnlocked: `Все школы Фокуса уже разблокированы.`,
code_focusUnlocked: `Разблокировано |COUNT| новых школ Фокуса! Для отображения изменений в игре потребуется обновление инвентаря. Посещение навигации — самый простой способ этого добиться.`,
code_focusAllUnlocked: `Все школы фокуса уже разблокированы.`,
code_focusUnlocked: `Разблокировано |COUNT| новых школ фокуса! Для отображения изменений в игре потребуется обновление инвентаря. Посещение навигации — самый простой способ этого добиться.`,
code_addModsConfirm: `Вы уверены, что хотите добавить |COUNT| модов на ваш аккаунт?`,
code_succImport: `Успешно импортировано.`,
code_succRelog: `Готово. Обратите внимание, что вам нужно будет перезайти, чтобы увидеть изменения в игре.`,
code_nothingToDo: `Готово. Нечего делать.`,
code_succRelog: `[UNTRANSLATED] Done. Please note that you'll need to relog to see a difference in-game.`,
code_nothingToDo: `[UNTRANSLATED] Done. There was nothing to do.`,
code_gild: `Улучшить`,
code_moa: `МОА`,
code_zanuka: `Гончая`,
code_stage: `Этап`,
code_complete: `Завершить`,
code_nextStage: `Следующий этап`,
code_nextStage: `Cледующий этап`,
code_prevStage: `Предыдущий этап`,
code_reset: `Сбросить`,
code_setInactive: `Сделать квест неактивным`,
@ -63,7 +63,7 @@ dict = {
code_mature: `Подготовить к сражениям`,
code_unmature: `Регрессия генетического старения`,
code_succChange: `Успешно изменено.`,
code_requiredInvigorationUpgrade: `Вы должны выбрать как атакующее, так и вспомогательное улучшение.`,
code_requiredInvigorationUpgrade: `[UNTRANSLATED] You must select both an offensive & defensive upgrade.`,
login_description: `Войдите, используя учетные данные OpenWF (те же, что и в игре при подключении к этому серверу).`,
login_emailLabel: `Адрес электронной почты`,
login_passwordLabel: `Пароль`,
@ -83,7 +83,7 @@ dict = {
inventory_pistols: `Вторичное оружие`,
inventory_melee: `Оружие ближнего боя`,
inventory_spaceSuits: `Арчвинги`,
inventory_spaceGuns: `Оружие Арчвинга`,
inventory_spaceGuns: `Оружие арчвинга`,
inventory_spaceMelee: `Оружие ближнего боя арчвинга`,
inventory_mechSuits: `Некрамехи`,
inventory_sentinels: `Стражи`,
@ -93,22 +93,22 @@ dict = {
inventory_moaPets: `МОА`,
inventory_kubrowPets: `Звери`,
inventory_evolutionProgress: `Прогресс эволюции Инкарнонов`,
inventory_Boosters: `Бустеры`,
inventory_bulkAddSuits: `Добавить отсутствующие Варфреймы`,
inventory_Boosters: `[UNTRANSLATED] Boosters`,
inventory_bulkAddSuits: `Добавить отсутствующие варфреймы`,
inventory_bulkAddWeapons: `Добавить отсутствующее оружие`,
inventory_bulkAddSpaceSuits: `Добавить отсутствующие Арчвинги`,
inventory_bulkAddSpaceWeapons: `Добавить отсутствующее оружие Арчвингов`,
inventory_bulkAddSentinels: `Добавить отсутствующих Стражей`,
inventory_bulkAddSentinelWeapons: `Добавить отсутствующее оружие Стражей`,
inventory_bulkAddEvolutionProgress: `Добавить отсутствующий прогресс эволюции Инкарнонов`,
inventory_bulkRankUpSuits: `Макс. ранг всех Варфреймов`,
inventory_bulkRankUpWeapons: `Макс. ранг всего оружия`,
inventory_bulkRankUpSpaceSuits: `Макс. ранг всех Арчвингов`,
inventory_bulkRankUpSpaceWeapons: `Макс. ранг всего оружия Арчвингов`,
inventory_bulkRankUpSentinels: `Макс. ранг всех Стражей`,
inventory_bulkRankUpSentinelWeapons: `Макс. ранг всего оружия Стражей`,
inventory_bulkRankUpEvolutionProgress: `Макс. ранг всех эволюций Инкарнонов`,
inventory_maxPlexus: `Макс. ранг Плексуса`,
inventory_bulkAddSpaceSuits: `Добавить отсутствующие арчвинги`,
inventory_bulkAddSpaceWeapons: `Добавить отсутствующее оружие арчвингов`,
inventory_bulkAddSentinels: `Добавить отсутствующих стражей`,
inventory_bulkAddSentinelWeapons: `Добавить отсутствующее оружие стражей`,
inventory_bulkAddEvolutionProgress: `Добавить отсуствующий прогресс эволюции Инкарнонов`,
inventory_bulkRankUpSuits: `Максимальный ранг всех варфреймов`,
inventory_bulkRankUpWeapons: `Максимальный ранг всего оружия`,
inventory_bulkRankUpSpaceSuits: `Максимальный ранг всех арчвингов`,
inventory_bulkRankUpSpaceWeapons: `Максимальный ранг всего оружия арчвингов`,
inventory_bulkRankUpSentinels: `Максимальный ранг всех стражей`,
inventory_bulkRankUpSentinelWeapons: `Максимальный ранг всего оружия стражей`,
inventory_bulkRankUpEvolutionProgress: `Максимальный ранг всех эволюций Инкарнонов`,
inventory_maxPlexus: `[UNTRANSLATED] Max Rank Plexus`,
quests_list: `Квесты`,
quests_completeAll: `Завершить все квесты`,
@ -121,72 +121,72 @@ dict = {
currency_PrimeTokens: `Королевские Айя`,
currency_owned: `У тебя |COUNT|.`,
detailedView_archonShardsLabel: `Ячейки осколков Архонта`,
detailedView_archonShardsLabel: `Ячейки осколков архонта`,
detailedView_archonShardsDescription: `Вы можете использовать эти неограниченные ячейки для установки множества улучшений.`,
detailedView_archonShardsDescription2: `Обратите внимание: каждый осколок Архонта применяется с задержкой при загрузке.`,
detailedView_archonShardsDescription2: `Обратите внимание: каждый фрагмент архонта применяется с задержкой при загрузке.`,
detailedView_valenceBonusLabel: `Бонус Валентности`,
detailedView_valenceBonusDescription: `Вы можете установить или убрать бонус Валентности с вашего оружия.`,
detailedView_modularPartsLabel: `Изменить модульные части`,
detailedView_suitInvigorationLabel: `Воодушевление Варфрейма`,
detailedView_valenceBonusDescription: `Вы можете установить или убрать бонус валентности с вашего оружия.`,
detailedView_modularPartsLabel: `Изменить Модульные Части`,
detailedView_suitInvigorationLabel: `[UNTRANSLATED] Warframe Invigoration`,
detailedView_loadoutLabel: `Конфигурации`,
invigorations_offensive_AbilityStrength: `+200% к силе способностей.`,
invigorations_offensive_AbilityRange: `+100% к зоне поражения способностей.`,
invigorations_offensive_AbilityDuration: `+100% к длительности способностей.`,
invigorations_offensive_MeleeDamage: `+250% к урону оружия ближнего боя.`,
invigorations_offensive_PrimaryDamage: `+250% к урону основного оружия.`,
invigorations_offensive_SecondaryDamage: `+250% к урону вторичного оружия.`,
invigorations_offensive_PrimaryCritChance: `+200% к шансу крит. урона для основного оружия.`,
invigorations_offensive_SecondaryCritChance: `+200% к шансу крит. урона для вторичного оружия.`,
invigorations_offensive_MeleeCritChance: `+200% у шансу крит. урона для оружия ближнего боя.`,
invigorations_offensive_AbilityStrength: `[UNTRANSLATED] +200% Ability Strength`,
invigorations_offensive_AbilityRange: `[UNTRANSLATED] +100% Ability Range`,
invigorations_offensive_AbilityDuration: `[UNTRANSLATED] +100% Ability Duration`,
invigorations_offensive_MeleeDamage: `[UNTRANSLATED] +250% Melee Damage`,
invigorations_offensive_PrimaryDamage: `[UNTRANSLATED] +250% Primary Damage`,
invigorations_offensive_SecondaryDamage: `[UNTRANSLATED] +250% Secondary Damage`,
invigorations_offensive_PrimaryCritChance: `[UNTRANSLATED] +200% Primary Critical Chance`,
invigorations_offensive_SecondaryCritChance: `[UNTRANSLATED] +200% Secondary Critical Chance`,
invigorations_offensive_MeleeCritChance: `[UNTRANSLATED] +200% Melee Critical Chance`,
invigorations_utility_AbilityEfficiency: `+75% к энергоэффективности способностей.`,
invigorations_utility_SprintSpeed: `+75% к скорости бега.`,
invigorations_utility_ParkourVelocity: `+75% к скорости паркура.`,
invigorations_utility_HealthMax: `+1000 к здоровью.`,
invigorations_utility_EnergyMax: `+200% к макс. запасу энергии.`,
invigorations_utility_StatusImmune: `Иммунитет к статусным эффектам.`,
invigorations_utility_ReloadSpeed: `+75% к скорости перезарядки.`,
invigorations_utility_HealthRegen: `+25 к регенерации здоровья в секунду.`,
invigorations_utility_ArmorMax: `+1000 к брони.`,
invigorations_utility_Jumps: `+5 сбросов прыжка.`,
invigorations_utility_EnergyRegen: `+2 к регенерации энергии в секунду.`,
invigorations_utility_AbilityEfficiency: `[UNTRANSLATED] +75% Ability Efficiency`,
invigorations_utility_SprintSpeed: `[UNTRANSLATED] +75% Sprint Speed`,
invigorations_utility_ParkourVelocity: `[UNTRANSLATED] +75% Parkour Velocity`,
invigorations_utility_HealthMax: `[UNTRANSLATED] +1000 Health`,
invigorations_utility_EnergyMax: `[UNTRANSLATED] +200% Energy Max`,
invigorations_utility_StatusImmune: `[UNTRANSLATED] Immune to Status Effects`,
invigorations_utility_ReloadSpeed: `[UNTRANSLATED] +75% Reload Speed`,
invigorations_utility_HealthRegen: `[UNTRANSLATED] +25 Health Regen/s`,
invigorations_utility_ArmorMax: `[UNTRANSLATED] +1000 Armor`,
invigorations_utility_Jumps: `[UNTRANSLATED] +5 Jump Resets`,
invigorations_utility_EnergyRegen: `[UNTRANSLATED] +2 Energy Regen/s`,
invigorations_offensiveLabel: `Атакующее улучшение`,
invigorations_defensiveLabel: `Вспомогательное улучшение`,
invigorations_expiryLabel: `Срок действия Воодушевления (необязательно)`,
invigorations_offensiveLabel: `[UNTRANSLATED] Offensive Upgrade`,
invigorations_defensiveLabel: `[UNTRANSLATED] Defensive Upgrade`,
invigorations_expiryLabel: `[UNTRANSLATED] Upgrades Expiry (optional)`,
abilityOverride_label: `Переопределение способности`,
abilityOverride_onSlot: `в ячейке`,
mods_addRiven: `Добавить мод Разлома`,
mods_addRiven: `Добавить Мод Разлома`,
mods_fingerprint: `Отпечаток`,
mods_fingerprintHelp: `Нужна помощь с отпечатком?`,
mods_rivens: `Моды Разлома`,
mods_mods: `Моды`,
mods_addMax: `Добавить макс. улучшенный`,
mods_addMax: `[UNTRANSLATED] Add Maxed`,
mods_addMissingUnrankedMods: `Добавить недостающие моды без ранга`,
mods_removeUnranked: `Удалить моды без ранга`,
mods_addMissingMaxRankMods: `Добавить недостающие моды макс. ранга`,
mods_addMissingMaxRankMods: `Добавить недостающие моды максимального ранга`,
cheats_administratorRequirement: `Вы должны быть администратором для использования этой функции. Чтобы стать администратором, добавьте <code>\"|DISPLAYNAME|\"</code> в <code>administratorNames</code> в config.json.`,
cheats_server: `Сервер`,
cheats_skipTutorial: `Пропустить обучение`,
cheats_skipAllDialogue: `Пропустить все диалоги`,
cheats_unlockAllScans: `Разблокировать все сканирования`,
cheats_unlockAllMissions: `Разблокировать все миссии`,
cheats_unlockAllMissions_ok: `Успех. Пожалуйста, обратите внимание, что вам нужно будет войти в Додзё/Реле или перезайти, чтобы клиент обновил звездную карту.`,
cheats_infiniteCredits: `Бесконечные Кредиты`,
cheats_infinitePlatinum: `Бесконечная Платина`,
cheats_infiniteEndo: `Бесконечное Эндо`,
cheats_unlockAllMissions_ok: `[UNTRANSLATED] Success. Please note that you'll need to enter a dojo/relay or relog for the client to refresh the star chart.`,
cheats_infiniteCredits: `Бесконечные кредиты`,
cheats_infinitePlatinum: `Бесконечная платина`,
cheats_infiniteEndo: `Бесконечное эндо`,
cheats_infiniteRegalAya: `Бесконечная Королевская Айя`,
cheats_infiniteHelminthMaterials: `Бесконечные секреции Гельминта`,
cheats_claimingBlueprintRefundsIngredients: `Возврат ингредиентов чертежей`,
cheats_dontSubtractPurchaseCreditCost: `Не вычитать стоимость Кредитов при покупке`,
cheats_dontSubtractPurchasePlatinumCost: `Не вычитать стоимость Платины при покупке`,
cheats_dontSubtractPurchaseItemCost: `Не вычитать стоимость предметов при покупке`,
cheats_dontSubtractPurchaseStandingCost: `Не вычитать стоимость репутации при покупке`,
cheats_dontSubtractVoidTraces: `Не вычитать количество Отголосков Бездны`,
cheats_dontSubtractConsumables: `Не вычитать количество расходников`,
cheats_infiniteHelminthMaterials: `Бесконечные Выделения Гельминта`,
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_dontSubtractConsumables: `Не уменьшать количество расходников`,
cheats_unlockAllShipFeatures: `Разблокировать все функции корабля`,
cheats_unlockAllShipDecorations: `Разблокировать все украшения корабля`,
cheats_unlockAllFlavourItems: `Разблокировать все <abbr title="Наборы анимаций, глифы, палитры и т. д.">уникальные предметы</abbr>`,
@ -194,186 +194,167 @@ dict = {
cheats_unlockAllCapturaScenes: `Разблокировать все сцены Каптуры`,
cheats_unlockAllDecoRecipes: `Разблокировать все рецепты декораций Дoдзё`,
cheats_universalPolarityEverywhere: `Универсальная полярность везде`,
cheats_unlockDoubleCapacityPotatoesEverywhere: `Реакторы/Катализаторы орокин везде`,
cheats_unlockDoubleCapacityPotatoesEverywhere: `Катализаторы везде`,
cheats_unlockExilusEverywhere: `Адаптеры Эксилус везде`,
cheats_unlockArcanesEverywhere: `Адаптеры для Мистификаторов везде`,
cheats_unlockArcanesEverywhere: `Адаптеры для мистификаторов везде`,
cheats_noDailyStandingLimits: `Без ежедневных лимитов репутации`,
cheats_noDailyFocusLimit: `Без ежедневных лимитов Фокуса`,
cheats_noArgonCrystalDecay: `Без распада Аргоновых кристаллов`,
cheats_noDailyFocusLimit: `Без ежедневных лимитов фокуса`,
cheats_noArgonCrystalDecay: `Без распада аргоновых кристаллов`,
cheats_noMasteryRankUpCooldown: `Повышение ранга мастерства без кулдауна`,
cheats_noVendorPurchaseLimits: `Отсутствие лимитов на покупки у торговцев`,
cheats_noDeathMarks: `Без меток смерти`,
cheats_noVendorPurchaseLimits: `Отсутствие лимитов на покупки у вендоров`,
cheats_noDeathMarks: `Без меток сметри`,
cheats_noKimCooldowns: `Чаты KIM без кулдауна`,
cheats_fullyStockedVendors: `Полностью укомплектованные торговцы`,
cheats_baroAlwaysAvailable: `Баро всегда доступен`,
cheats_baroFullyStocked: `Баро полностью укомплектован`,
cheats_syndicateMissionsRepeatable: `Повторять миссии синдиката`,
cheats_unlockAllProfitTakerStages: `Разблокировать все этапы Сферы извлечения прибыли`,
cheats_instantFinishRivenChallenge: `Мгновенное завершение испытания мода Разлома`,
cheats_instantResourceExtractorDrones: `Мгновенно добывающие Дроны-сборщики`,
cheats_noResourceExtractorDronesDamage: `Без урона по Дронам-сборщикам`,
cheats_skipClanKeyCrafting: `Пропустить создание кланового ключа`,
cheats_noDojoRoomBuildStage: `Мгновенное строительство комнат Додзё`,
cheats_noDojoDecoBuildStage: `Мгновенное строительство декораций Додзё`,
cheats_fastDojoRoomDestruction: `Мгновенные уничтожение комнат Додзё`,
cheats_noDojoResearchCosts: `Бесплатные исследование Додзё`,
cheats_noDojoResearchTime: `Мгновенные исследование Додзё`,
cheats_fastClanAscension: `Мгновенное вознесение клана`,
cheats_missionsCanGiveAllRelics: `Миссии могут давать все реликвии`,
cheats_exceptionalRelicsAlwaysGiveBronzeReward: `Необычные реликвии всегда дают бронзовую награду`,
cheats_flawlessRelicsAlwaysGiveSilverReward: `Бесподобные реликвии всегда дают серебряную награду`,
cheats_radiantRelicsAlwaysGiveGoldReward: `Сияющие реликвии всегда дают золотую награду`,
cheats_unlockAllSimarisResearchEntries: `Разблокировать все записи исследований Симэриса`,
cheats_disableDailyTribute: `Отключить ежедневные награды`,
cheats_spoofMasteryRank: `Поддельный ранг мастерства (-1 для отключения)`,
cheats_relicRewardItemCountMultiplier: `Мультипликатор количества предметов награды реликвии`,
cheats_nightwaveStandingMultiplier: `Мультипликатор репутации Ночной волны`,
cheats_save: `Сохранить`,
cheats_fullyStockedVendors: `[UNTRANSLATED] Fully Stocked Vendors`,
cheats_baroAlwaysAvailable: `[UNTRANSLATED] Baro Always Available`,
cheats_baroFullyStocked: `[UNTRANSLATED] Baro Fully Stocked`,
cheats_syndicateMissionsRepeatable: `[UNTRANSLATED] Syndicate Missions Repeatable`,
cheats_unlockAllProfitTakerStages: `[UNTRANSLATED] Unlock All Profit Taker Stages`,
cheats_instantFinishRivenChallenge: `[UNTRANSLATED] Instant Finish Riven Challenge`,
cheats_instantResourceExtractorDrones: `Мгновенные Экстракторы Ресурсов`,
cheats_noResourceExtractorDronesDamage: `Без урона по дронам-сборщикам`,
cheats_skipClanKeyCrafting: `Пропустить крафт кланового ключа`,
cheats_noDojoRoomBuildStage: `Мгновенное Строительтво Комнат Додзё`,
cheats_noDojoDecoBuildStage: `Мгновенное Строительтво Декораций Додзё`,
cheats_fastDojoRoomDestruction: `Мгновенные Уничтожение Комнат Додзё`,
cheats_noDojoResearchCosts: `Бесплатные Исследование Додзё`,
cheats_noDojoResearchTime: `Мгновенные Исследование Додзё`,
cheats_fastClanAscension: `Мгновенное Вознесение Клана`,
cheats_missionsCanGiveAllRelics: `[UNTRANSLATED] Missions Can Give All Relics`,
cheats_exceptionalRelicsAlwaysGiveBronzeReward: `[UNTRANSLATED] Exceptional Relics Always Give Bronze Reward`,
cheats_flawlessRelicsAlwaysGiveSilverReward: `[UNTRANSLATED] Flawless Relics Always Give Silver Reward`,
cheats_radiantRelicsAlwaysGiveGoldReward: `[UNTRANSLATED] Radiant Relics Always Give Gold Reward`,
cheats_unlockAllSimarisResearchEntries: `[UNTRANSLATED] Unlock All Simaris Research Entries`,
cheats_disableDailyTribute: `[UNTRANSLATED] Disable Daily Tribute`,
cheats_spoofMasteryRank: `Подделанный ранг мастерства (-1 для отключения)`,
cheats_relicRewardItemCountMultiplier: `[UNTRANSLATED] Relic Reward Item Count Multiplier`,
cheats_nightwaveStandingMultiplier: `[UNTRANSLATED] Nightwave Standing Multiplier`,
cheats_save: `[UNTRANSLATED] Save`,
cheats_account: `Аккаунт`,
cheats_unlockAllFocusSchools: `Разблокировать все школы Фокуса`,
cheats_unlockAllFocusSchools: `Разблокировать все школы фокуса`,
cheats_helminthUnlockAll: `Полностью улучшить Гельминта`,
cheats_addMissingSubsumedAbilities: `Добавить отсутствующие поглощённые способности`,
cheats_intrinsicsUnlockAll: `Полностью улучшить Модуляры`,
cheats_changeSupportedSyndicate: `Поддерживаемый синдикат`,
cheats_changeButton: `Изменить`,
cheats_markAllAsRead: `Пометить все входящие как прочитанные`,
cheats_markAllAsRead: `[UNTRANSLATED] Mark Inbox As Read`,
worldState: `Состояние мира`,
worldState_creditBoost: `Глобальный бустер Кредитов`,
worldState_affinityBoost: `Глобальный бустер Синтеза`,
worldState_resourceBoost: `Глобальный бустер Ресурсов`,
worldState_tennoLiveRelay: `Реле TennoLive`,
worldState_baroTennoConRelay: `Реле Баро TennoCon`,
worldState_starDays: `Звёздные дни`,
worldState_galleonOfGhouls: `Галеон Гулей`,
worldState_ghoulEmergence: `Избавление от гулей`,
worldState_plagueStar: `Чумная звезда`,
worldState_dogDays: `Знойные дни`,
worldState_dogDaysRewards: `Награды Знойных дней`,
worldState_wolfHunt: `Волчья Охота (2025)`,
worldState_longShadow: `Длинная Тень`,
worldState_hallowedFlame: `Священное пламя`,
worldState_hallowedNightmares: `Священные кошмары`,
worldState_hallowedNightmaresRewards: `Награды Священных кошмаров`,
worldState_proxyRebellion: `Восстание роботов`,
worldState_proxyRebellionRewards: `Награды Восстания роботов`,
worldState_bellyOfTheBeast: `Чрево зверя`,
worldState_bellyOfTheBeastProgressOverride: `Прогресс Чрева зверя`,
worldState_eightClaw: `Восемь когтей`,
worldState_eightClawProgressOverride: `Прогресс Восьми когтей`,
worldState_from_year: `из |YEAR|`,
worldState_pre_year: `до |YEAR|`,
worldState_incompatibleWith: `Несовместимо с:`,
enabled: `Включено`,
disabled: `Отключено`,
worldState_we1: `Выходные 1`,
worldState_we2: `Выходные 2`,
worldState_we3: `Выходные 3`,
worldState_eidolonOverride: `Цикл Равнин Эйдолона/Деймоса`,
worldState_day: `День/Фэз`,
worldState_night: `Ночь/Воум`,
worldState_vallisOverride: `Цикл Долины сфер`,
worldState_warm: `Тепло`,
worldState_cold: `Холод`,
worldState_duviriOverride: `Цикл Дувири`,
worldState_joy: `Радость`,
worldState_anger: `Гнев`,
worldState_envy: `Зависть`,
worldState_sorrow: `Печаль`,
worldState_fear: `Страх`,
worldState_nightwaveOverride: `Сезон Ночной волны`,
worldState_RadioLegionIntermission13Syndicate: `Микс Норы, Диск 9`,
worldState_RadioLegionIntermission12Syndicate: `Микс Норы, Диск 8`,
worldState_RadioLegionIntermission11Syndicate: `Микс Норы, Диск 7`,
worldState_RadioLegionIntermission10Syndicate: `Микс Норы, Диск 6`,
worldState_RadioLegionIntermission9Syndicate: `Микс Норы, Диск 5`,
worldState_RadioLegionIntermission8Syndicate: `Микс Норы, Диск 4`,
worldState_RadioLegionIntermission7Syndicate: `Микс Норы, Диск 3`,
worldState_RadioLegionIntermission6Syndicate: `Микс Норы, Диск 2`,
worldState_RadioLegionIntermission5Syndicate: `Микс Норы, Диск 1`,
worldState_RadioLegionIntermission4Syndicate: `Выбор Норы`,
worldState_RadioLegionIntermission3Syndicate: `Антракт III`,
worldState_RadioLegion3Syndicate: `Стеклодув`,
worldState_RadioLegionIntermission2Syndicate: `Антракт II`,
worldState_RadioLegion2Syndicate: `Эмиссар`,
worldState_RadioLegionIntermissionSyndicate: `Антракт I`,
worldState_RadioLegionSyndicate: `Волк Сатурна Шесть`,
worldState_fissures: `Разрывы бездны`,
normal: `Стандартные`,
worldState_allAtOnceNormal: `Все сразу, в обычном режиме`,
worldState_allAtOnceSteelPath: `Все сразу, в режиме Стального Пути`,
worldState_theCircuitOverride: `Типы миссий в подземелье Дувири`,
worldState_darvoStockMultiplier: `Множитель запасов Дарво`,
worldState_varziaFullyStocked: `Полный ассортимент Варзии`,
worldState_varziaOverride: `Изменение ротации Варзии`,
worldState: `[UNTRANSLATED] World State`,
worldState_creditBoost: `[UNTRANSLATED] Credit Boost`,
worldState_affinityBoost: `[UNTRANSLATED] Affinity Boost`,
worldState_resourceBoost: `[UNTRANSLATED] Resource Boost`,
worldState_tennoLiveRelay: `[UNTRANSLATED] TennoLive Relay`,
worldState_baroTennoConRelay: `[UNTRANSLATED] Baro's TennoCon Relay`,
worldState_starDays: `[UNTRANSLATED] Star Days`,
worldState_galleonOfGhouls: `[UNTRANSLATED] Galleon of Ghouls`,
enabled: `[UNTRANSLATED] Enabled`,
disabled: `[UNTRANSLATED] Disabled`,
worldState_we1: `[UNTRANSLATED] Weekend 1`,
worldState_we2: `[UNTRANSLATED] Weekend 2`,
worldState_we3: `[UNTRANSLATED] Weekend 3`,
worldState_eidolonOverride: `[UNTRANSLATED] Eidolon/Deimos Override`,
worldState_day: `[UNTRANSLATED] Day/Fass`,
worldState_night: `[UNTRANSLATED] Night/Vome`,
worldState_vallisOverride: `[UNTRANSLATED] Orb Vallis Override`,
worldState_warm: `[UNTRANSLATED] Warm`,
worldState_cold: `[UNTRANSLATED] Cold`,
worldState_duviriOverride: `[UNTRANSLATED] Duviri Override`,
worldState_joy: `[UNTRANSLATED] Joy`,
worldState_anger: `[UNTRANSLATED] Anger`,
worldState_envy: `[UNTRANSLATED] Envy`,
worldState_sorrow: `[UNTRANSLATED] Sorrow`,
worldState_fear: `[UNTRANSLATED] Fear`,
worldState_nightwaveOverride: `[UNTRANSLATED] Nightwave Override`,
worldState_RadioLegionIntermission13Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 9`,
worldState_RadioLegionIntermission12Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 8`,
worldState_RadioLegionIntermission11Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 7`,
worldState_RadioLegionIntermission10Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 6`,
worldState_RadioLegionIntermission9Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 5`,
worldState_RadioLegionIntermission8Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 4`,
worldState_RadioLegionIntermission7Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 3`,
worldState_RadioLegionIntermission6Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 2`,
worldState_RadioLegionIntermission5Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 1`,
worldState_RadioLegionIntermission4Syndicate: `[UNTRANSLATED] Nora's Choice`,
worldState_RadioLegionIntermission3Syndicate: `[UNTRANSLATED] Intermission III`,
worldState_RadioLegion3Syndicate: `[UNTRANSLATED] Glassmaker`,
worldState_RadioLegionIntermission2Syndicate: `[UNTRANSLATED] Intermission II`,
worldState_RadioLegion2Syndicate: `[UNTRANSLATED] The Emissary`,
worldState_RadioLegionIntermissionSyndicate: `[UNTRANSLATED] Intermission I`,
worldState_RadioLegionSyndicate: `[UNTRANSLATED] The Wolf of Saturn Six`,
worldState_fissures: `[UNTRANSLATED] Fissures`,
normal: `[UNTRANSLATED] Normal`,
worldState_allAtOnceNormal: `[UNTRANSLATED] All At Once, Normal`,
worldState_allAtOnceSteelPath: `[UNTRANSLATED] All At Once, Steel Path`,
worldState_theCircuitOverride: `[UNTRANSLATED] The Circuit Override`,
worldState_darvoStockMultiplier: `[UNTRANSLATED] Darvo Stock Multiplier`,
worldState_varziaFullyStocked: `Полный Ассортимент Варзии`,
worldState_varziaOverride: `Изменение Ротации Варзии`,
import_importNote: `Вы можете загрузить полный или частичный ответ <code>inventory.php</code> или <code>getShip.php</code> (клиентское представление) здесь. `,
import_importNote2: `Все поддерживаемые поля <b>будут перезаписаны</b> в вашем аккаунте.`,
import_importNote: `Вы можете загрузить полный или частичный ответ инвентаря (клиентское представление) здесь. Все поддерживаемые поля <b>будут перезаписаны</b> в вашем аккаунте.`,
import_submit: `Отправить`,
import_samples: `Пример:`,
import_samples_maxFocus: `Все школы Фокуса макс. уровня`,
import_samples: `[UNTRANSLATED] Samples:`,
import_samples_maxFocus: `[UNTRANSLATED] All Focus Schools Maxed Out`,
upgrade_Equilibrium: `Подбор сфер здоровья даёт +|VAL|% энергии. Подбор сфер энергии даёт +|VAL|% здоровья.`,
upgrade_MeleeCritDamage: `+|VAL|% к крит. урону в ближнем бою.`,
upgrade_PrimaryStatusChance: `+|VAL|% к шансу статуса основного оружия.`,
upgrade_SecondaryCritChance: `+|VAL|% к шансу крит. урона от вторичного оружия.`,
upgrade_WarframeAbilityDuration: `+|VAL|% к длительности способностей.`,
upgrade_WarframeAbilityStrength: `+|VAL|% к силе способностей.`,
upgrade_WarframeArmorMax: `+|VAL| к броне.`,
upgrade_WarframeBlastProc: `Регенерирует +|VAL| щитов, когда вы убиваете врага, наложив статус Взрыва.`,
upgrade_WarframeCastingSpeed: `+|VAL|% к скорости применения способностей.`,
upgrade_WarframeCorrosiveDamageBoost: `Даёт +|VAL|% урона от сопсобнстй по врагам, находящимся под действием статуса Коррозии.`,
upgrade_WarframeCorrosiveStack: `Увеличить макс. количество стаков статуса Коррози на +|VAL|.`,
upgrade_WarframeCritDamageBoost: `Даёт +|VAL|% крит. урона в ближнем бою. Когда макс. энергия превышает 500, увеличение урона удваивается.`,
upgrade_WarframeElectricDamage: `Даёт +|VAL1|% Электрического урона основному оружию. Получите дополнительно +|VAL2|% за каждый экипированный багровый, лазурный или фиолетовый осколок архонта (Комбинируется с модами).`,
upgrade_WarframeElectricDamageBoost: `Даёт +|VAL|% урон аот спсобностей по врагам, находящимся под действием статуса Электричества.`,
upgrade_WarframeEnergyMax: `+|VAL| к запасу энергии.`,
upgrade_WarframeGlobeEffectEnergy: `+|VAL|% к эффективности сфер энергии.`,
upgrade_WarframeGlobeEffectHealth: `+|VAL|% к эффективности сфер здоровья.`,
upgrade_WarframeHealthMax: `+|VAL| к здоровью.`,
upgrade_WarframeHPBoostFromImpact: `Даёт +|VAL1| здоровья за каждого врага, убитого с помощью Взрывного урона. Макс. |VAL2| здоровья.`,
upgrade_WarframeParkourVelocity: `+|VAL|% к скорости паркура.`,
upgrade_WarframeRadiationDamageBoost: `Даёт +|VAL|% урона от способностей по врагам, находящимся под действием статуса Радиации.`,
upgrade_WarframeHealthRegen: `+|VAL| к восстановлению здоровья в секунду.`,
upgrade_WarframeShieldMax: `+|VAL| к мощности щитов.`,
upgrade_WarframeStartingEnergy: `+|VAL|% к макс. энергии при появлении.`,
upgrade_WarframeToxinDamage: `Статусный эффект Токсина наносит на +|VAL|% больше урона.`,
upgrade_WarframeToxinHeal: `Восстанавливает +|VAL| здоровья кадый раз, когда враги получают урон от эффекта статуса Токсина.`,
upgrade_WeaponCritBoostFromHeat: `Увеличивает шанс крит. урона вторичным оружием на |VAL1|% каждый раз, когда вы убиваете врага, назодящегося под действием статуса Огня. Макс.: |VAL2|%.`,
upgrade_AvatarAbilityRange: `+7.5% к зоне поражения способностей.`,
upgrade_AvatarAbilityEfficiency: `+5% к энергоэффективности способностей.`,
upgrade_AvatarEnergyRegen: `+0.5 к регенерации энергии в секунду.`,
upgrade_AvatarEnemyRadar: `+5м обнаружение врагов.`,
upgrade_AvatarLootRadar: `+7м к радиусу обнаружения добычи.`,
upgrade_WeaponAmmoMax: `+15% макс. боеприпасов.`,
upgrade_EnemyArmorReductionAura: `Враги теряют -3% брони.`,
upgrade_OnExecutionAmmo: `Убийство Милосердием пополняет магазины основного и вторичного оружия на 100%.`,
upgrade_OnExecutionHealthDrop: `+100% шанс выпадения сферы здоровья при убийстве Милосердием.`,
upgrade_OnExecutionEnergyDrop: `+50% шанс выпадения сферы энергии при убийстве Милосердием.`,
upgrade_OnFailHackReset: `+50% шанс доволнительной попытки взлома в случае неудачи.`,
upgrade_DamageReductionOnHack: `Уменьшает урон на 75% во время взлома.`,
upgrade_OnExecutionReviveCompanion: `Убийства Милосердием уменьшают время восстановления компаньона на 15 секунд.`,
upgrade_OnExecutionParkourSpeed: `+60% к скорости паркура после убийства Милосердием на 15 секунд.`,
upgrade_AvatarTimeLimitIncrease: `+8 секунд на взлом.`,
upgrade_ElectrifyOnHack: `Шокирует врагов в радиусе 20м во время взлома.`,
upgrade_OnExecutionTerrify: `50% шанс, что при убийстве Милосердием враги в радиусе 15м будут параллизованы от страха на 8 секунд.`,
upgrade_OnHackLockers: `Открывает 5 контейнеров в радиусе 20м после взлома.`,
upgrade_OnExecutionBlind: `Ослепляет врагов в радиусе 18м при убийстве Милосердием.`,
upgrade_OnExecutionDrainPower: `Следующая способность, применённая после убийства Милосердием, получает +50% к силе способности.`,
upgrade_OnHackSprintSpeed: `+75% к скорости бега после взлома на 15 секунд.`,
upgrade_SwiftExecute: `Увеличивает скорость добиваний Милосердием на 50%.`,
upgrade_OnHackInvis: `Невидимсть на 15 секунд после взлома.`,
upgrade_Equilibrium: `[UNTRANSLATED] +|VAL|% Energy from Health pickups, +|VAL|% Health from Energy pickups`,
upgrade_MeleeCritDamage: `[UNTRANSLATED] +|VAL|% Melee Critical Damage`,
upgrade_PrimaryStatusChance: `[UNTRANSLATED] +|VAL|% Primary Status Chance`,
upgrade_SecondaryCritChance: `[UNTRANSLATED] +|VAL|% Secondary Critical Chance`,
upgrade_WarframeAbilityDuration: `[UNTRANSLATED] +|VAL|% Ability Duration`,
upgrade_WarframeAbilityStrength: `[UNTRANSLATED] +|VAL|% Ability Strength`,
upgrade_WarframeArmorMax: `[UNTRANSLATED] +|VAL| Armor`,
upgrade_WarframeBlastProc: `[UNTRANSLATED] +|VAL| Shields on kill with Blast Damage`,
upgrade_WarframeCastingSpeed: `[UNTRANSLATED] +|VAL|% Casting Speed`,
upgrade_WarframeCorrosiveDamageBoost: `[UNTRANSLATED] +|VAL|% Ability Damage on enemies affected by Corrosion Status`,
upgrade_WarframeCorrosiveStack: `[UNTRANSLATED] Increase max stacks of Corrosion Status by +|VAL|`,
upgrade_WarframeCritDamageBoost: `[UNTRANSLATED] +|VAL|% Melee Critical Damage (Doubles over 500 Energy)`,
upgrade_WarframeElectricDamage: `[UNTRANSLATED] +|VAL1|% Primary Electricity Damage (+|VAL2|% per additional Shard)`,
upgrade_WarframeElectricDamageBoost: `[UNTRANSLATED] +|VAL|% Ability Damage on enemies affected by Electricity Status`,
upgrade_WarframeEnergyMax: `[UNTRANSLATED] +|VAL| Energy Max`,
upgrade_WarframeGlobeEffectEnergy: `[UNTRANSLATED] +|VAL|% Energy Orb Effectiveness`,
upgrade_WarframeGlobeEffectHealth: `[UNTRANSLATED] +|VAL|% Health Orb Effectiveness`,
upgrade_WarframeHealthMax: `[UNTRANSLATED] +|VAL| Health`,
upgrade_WarframeHPBoostFromImpact: `[UNTRANSLATED] +|VAL1| Health on kill with Blast Damage (Max |VAL2| Health)`,
upgrade_WarframeParkourVelocity: `[UNTRANSLATED] +|VAL|% Parkour Velocity`,
upgrade_WarframeRadiationDamageBoost: `[UNTRANSLATED] +|VAL|% Ability Damage on enemies affected by Radiation Status`,
upgrade_WarframeHealthRegen: `[UNTRANSLATED] +|VAL| Health Regen/s`,
upgrade_WarframeShieldMax: `[UNTRANSLATED] +|VAL| Shield`,
upgrade_WarframeStartingEnergy: `[UNTRANSLATED] +|VAL|% Energy on Spawn`,
upgrade_WarframeToxinDamage: `[UNTRANSLATED] +|VAL|% Toxin Status Effect Damage`,
upgrade_WarframeToxinHeal: `[UNTRANSLATED] +|VAL| Health on damaging enemies with Toxin Status`,
upgrade_WeaponCritBoostFromHeat: `[UNTRANSLATED] +|VAL1|% Secondary Critical Chance per Heat-affected enemy killed (Max |VAL2|%)`,
upgrade_AvatarAbilityRange: `[UNTRANSLATED] +7.5% Ability Range`,
upgrade_AvatarAbilityEfficiency: `[UNTRANSLATED] +5% Ability Efficiency`,
upgrade_AvatarEnergyRegen: `[UNTRANSLATED] +0.5 Energy Regen/s`,
upgrade_AvatarEnemyRadar: `[UNTRANSLATED] +5m Enemy Radar`,
upgrade_AvatarLootRadar: `[UNTRANSLATED] +7m Loot Radar`,
upgrade_WeaponAmmoMax: `[UNTRANSLATED] +15% Ammo Max`,
upgrade_EnemyArmorReductionAura: `[UNTRANSLATED] -3% Enemy Armor`,
upgrade_OnExecutionAmmo: `[UNTRANSLATED] +100% Primary and Secondary Magazine Refill on Mercy`,
upgrade_OnExecutionHealthDrop: `[UNTRANSLATED] +100% Health Orb Chance on Mercy`,
upgrade_OnExecutionEnergyDrop: `[UNTRANSLATED] +50% Energy Orb Chance on Mercy`,
upgrade_OnFailHackReset: `[UNTRANSLATED] +50% Hacking Retry Chance`,
upgrade_DamageReductionOnHack: `[UNTRANSLATED] +75% Damage Reduction while Hacking`,
upgrade_OnExecutionReviveCompanion: `[UNTRANSLATED] Mercy Kills reduce Companion Recovery by 15s`,
upgrade_OnExecutionParkourSpeed: `[UNTRANSLATED] +60% Parkour Speed after a Mercy for 15s`,
upgrade_AvatarTimeLimitIncrease: `[UNTRANSLATED] +8s to Hacking`,
upgrade_ElectrifyOnHack: `[UNTRANSLATED] Shock enemies within 20m while Hacking`,
upgrade_OnExecutionTerrify: `[UNTRANSLATED] +50% chance for enemies within 15m to cower in fear for 8 seconds on Mercy`,
upgrade_OnHackLockers: `[UNTRANSLATED] Unlock 5 lockers within 20m after Hacking`,
upgrade_OnExecutionBlind: `[UNTRANSLATED] Blind enemies within 18m on Mercy`,
upgrade_OnExecutionDrainPower: `[UNTRANSLATED] Next ability cast gains +50% Ability Strength on Mercy`,
upgrade_OnHackSprintSpeed: `[UNTRANSLATED] +75% Sprint Speed for 15s after Hacking`,
upgrade_SwiftExecute: `[UNTRANSLATED] +50% Mercy Kill Speed`,
upgrade_OnHackInvis: `[UNTRANSLATED] Invisible for 15 seconds after Hacking`,
damageType_Electricity: `Электрический`,
damageType_Fire: `Огненный`,
damageType_Freeze: `Холодовой`,
damageType_Impact: `Ударный`,
damageType_Magnetic: `Магнитный`,
damageType_Poison: `Токсичный`,
damageType_Radiation: `Радиационный`,
damageType_Electricity: `Электричество`,
damageType_Fire: `Огонь`,
damageType_Freeze: `Холод`,
damageType_Impact: `Удар`,
damageType_Magnetic: `Магнит`,
damageType_Poison: `Токсин`,
damageType_Radiation: `Радиация`,
theme_dark: `Темная тема`,
theme_light: `Светлая тема`,
theme_dark: `[UNTRANSLATED] Dark Theme`,
theme_light: `[UNTRANSLATED] Light Theme`,
prettier_sucks_ass: ``
};

View File

@ -1,379 +0,0 @@
// Ukrainian translation by LoseFace
dict = {
general_inventoryUpdateNote: `Пам'ятка: Щоб побачити зміни в грі, вам потрібно повторно синхронізувати своє спорядження, наприклад, використовуючи команду /sync завантажувача, відвідавши Доджьо/Реле або перезавантаживши гру.`,
general_addButton: `Добавити`,
general_setButton: `Встановити`,
general_none: `Відсутній`,
general_bulkActions: `Масові дії`,
general_loading: `Завантаження...`,
code_loginFail: `Не вдалося увійти. Перевірте адресу електронної пошти та пароль.`,
code_regFail: `Не вдалося зареєструватися. Обліковий запис вже існує?`,
code_changeNameConfirm: `Яке ім'я ви хочете встановити для свого облікового запису?`,
code_deleteAccountConfirm: `Ви впевнені, що хочете видалити обліковий запис |DISPLAYNAME| (|EMAIL|)? Цю дію не можна скасувати.`,
code_archgun: `Арк-гармата`,
code_melee: `Холодна зброя`,
code_pistol: `Пістолет`,
code_rifle: `Гвинтівка`,
code_shotgun: `Рушниця`,
code_kitgun: `Складостріл`,
code_zaw: `Зо`,
code_moteAmp: `Порошинка`,
code_amp: `Підсилювач`,
code_kDrive: `К-Драйв`,
code_legendaryCore: `Легендарне ядро`,
code_traumaticPeculiar: `Особливе травмування`,
code_starter: `|MOD| (Пошкоджений)`,
code_badItem: `(Самозванець)`,
code_maxRank: `Макс. рівень`,
code_rename: `Перейменувати`,
code_renamePrompt: `Введіть нове ім'я:`,
code_remove: `Видалити`,
code_addItemsConfirm: `Ви впевнені, що хочете додати |COUNT| предметів на ваш обліковий запис?`,
code_succRankUp: `Рівень успішно підвищено`,
code_noEquipmentToRankUp: `Немає спорядження для підвищення рівня.`,
code_succAdded: `Успішно додано.`,
code_succRemoved: `Успішно видалено.`,
code_buffsNumber: `Кількість позитивних ефектів`,
code_cursesNumber: `Кількість негативних ефектів`,
code_rerollsNumber: `Кількість рероллів`,
code_viewStats: `Перегляд характеристики`,
code_rank: `Рівень`,
code_rankUp: `Підвищити рівень`,
code_rankDown: `Понизити рівень`,
code_count: `Кількість`,
code_focusAllUnlocked: `Всі школи Фокусу вже розблоковані.`,
code_focusUnlocked: `Розблоковано |COUNT| нових шкіл Фокусу! Для відображення змін в грі знадобиться оновлення спорядження. Відвідування навігації — найпростіший спосіб цього досягти.`,
code_addModsConfirm: `Ви впевнені, що хочете додати |COUNT| модифікаторів на ваш обліковий запис?`,
code_succImport: `Успішно імпортовано.`,
code_succRelog: `Готово. Зверніть увагу, що вам потрібно буде перезайти, щоб побачити зміни в грі.`,
code_nothingToDo: `Готово. Немає що робити.`,
code_gild: `Покращити`,
code_moa: `МОА`,
code_zanuka: `Гончак`,
code_stage: `Етап`,
code_complete: `Завершити`,
code_nextStage: `Наступний етап`,
code_prevStage: `Попередній етап`,
code_reset: `Скинути`,
code_setInactive: `Зробити пригоду неактивною`,
code_completed: `Завершено`,
code_active: `Активний`,
code_pigment: `Барвник`,
code_mature: `Виростити для бою`,
code_unmature: `Обернути старіння`,
code_succChange: `Успішно змінено.`,
code_requiredInvigorationUpgrade: `Ви повинні вибрати як атакуюче, так і допоміжне вдосконалення.`,
login_description: `Увійдіть, використовуючи облікові дані OpenWF (ті ж, що й у грі при підключенні до цього серверу).`,
login_emailLabel: `Адреса електронної пошти`,
login_passwordLabel: `Пароль`,
login_loginButton: `Увійти`,
login_registerButton: `Зареєструватися`,
navbar_logout: `Вийти`,
navbar_renameAccount: `Перейменувати обліковий запис`,
navbar_deleteAccount: `Видалити обліковий запис`,
navbar_inventory: `Спорядження`,
navbar_mods: `Модифікатори`,
navbar_quests: `Пригоди`,
navbar_cheats: `Чити`,
navbar_import: `Імпорт`,
inventory_addItems: `Додати предмети`,
inventory_suits: `Ворфрейми`,
inventory_longGuns: `Основна зброя`,
inventory_pistols: `Допоміжна зброя`,
inventory_melee: `Холодна зброя`,
inventory_spaceSuits: `Арквінґи`,
inventory_spaceGuns: `Зброя Арквінґів`,
inventory_spaceMelee: `Холодна зброя Арквінґів`,
inventory_mechSuits: `Некрамехи`,
inventory_sentinels: `Вартові`,
inventory_sentinelWeapons: `Зброя Вартових`,
inventory_operatorAmps: `Підсилювачі`,
inventory_hoverboards: `К-Драйви`,
inventory_moaPets: `МОА`,
inventory_kubrowPets: `Тварини`,
inventory_evolutionProgress: `Прогрес еволюції Інкарнонів`,
inventory_Boosters: `Посилення`,
inventory_bulkAddSuits: `Додати відсутні Ворфрейми`,
inventory_bulkAddWeapons: `Додати відсутню зброю`,
inventory_bulkAddSpaceSuits: `Додати відсутні Арквінґи`,
inventory_bulkAddSpaceWeapons: `Додати відсутню зброю Арквінґів`,
inventory_bulkAddSentinels: `Додати відсутніх Вартових`,
inventory_bulkAddSentinelWeapons: `Додати відсутню зброю Вартових`,
inventory_bulkAddEvolutionProgress: `Додати відсутній прогрес еволюції Інкарнонів`,
inventory_bulkRankUpSuits: `Макс. рівень всіх Ворфреймів`,
inventory_bulkRankUpWeapons: `Макс. рівень всієї зброї`,
inventory_bulkRankUpSpaceSuits: `Макс. рівень всіх Арквінґів`,
inventory_bulkRankUpSpaceWeapons: `Макс. рівень всієї зброї Арквінґів`,
inventory_bulkRankUpSentinels: `Макс. рівень всіх Вартових`,
inventory_bulkRankUpSentinelWeapons: `Макс. рівень всієї зброї Вартових`,
inventory_bulkRankUpEvolutionProgress: `Макс. рівень всіх еволюцій Інкарнонів`,
inventory_maxPlexus: `Макс. рівень Плексу`,
quests_list: `Пригоди`,
quests_completeAll: `Закінчити всі пригоди`,
quests_resetAll: `Скинути прогрес всіх пригод`,
quests_giveAll: `Видати всі пригоди`,
currency_RegularCredits: `Кредити`,
currency_PremiumCredits: `Платина`,
currency_FusionPoints: `Ендо`,
currency_PrimeTokens: `Королівські Ая`,
currency_owned: `У тебе |COUNT|.`,
detailedView_archonShardsLabel: `Комірки уламків Архонта`,
detailedView_archonShardsDescription: `Ви можете використовувати ці необмежені комірки для встановлення безлічі вдосконалень.`,
detailedView_archonShardsDescription2: `Зверніть увагу: кожен уламок Архонта застосовується з затримкою при завантаженні.`,
detailedView_valenceBonusLabel: `Ознака Валентності`,
detailedView_valenceBonusDescription: `Ви можете встановити або прибрати ознаку Валентності з вашої зброї.`,
detailedView_modularPartsLabel: `Змінити модульні частини`,
detailedView_suitInvigorationLabel: `Зміцнення Ворфрейма`,
detailedView_loadoutLabel: `Конфігурації`,
invigorations_offensive_AbilityStrength: `+200% до потужності здібностей.`,
invigorations_offensive_AbilityRange: `+100% до досяжності здібностей.`,
invigorations_offensive_AbilityDuration: `+100% до тривалості дії здібностей.`,
invigorations_offensive_MeleeDamage: `+250% до шкоди від холодної зброї.`,
invigorations_offensive_PrimaryDamage: `+250% до шкоди від основної зброї.`,
invigorations_offensive_SecondaryDamage: `+250% до шкоди від допоміжної зброї.`,
invigorations_offensive_PrimaryCritChance: `+200% до ймовірності критичної шкоди від основної зброї.`,
invigorations_offensive_SecondaryCritChance: `+200% до ймовірності критичної шкоди від допоміжної зброї.`,
invigorations_offensive_MeleeCritChance: `+200% до ймовірності критичної шкоди від холодної зброї.`,
invigorations_utility_AbilityEfficiency: `+75% до ощадливості здібностей.`,
invigorations_utility_SprintSpeed: `+75% до швидкості бігу.`,
invigorations_utility_ParkourVelocity: `+75% до швидкості паркуру.`,
invigorations_utility_HealthMax: `+1000 до здоров'я.`,
invigorations_utility_EnergyMax: `+200% до макс. енергії.`,
invigorations_utility_StatusImmune: `Імунітет до ефектів стану.`,
invigorations_utility_ReloadSpeed: `+75% до швидкості перезаряджання.`,
invigorations_utility_HealthRegen: `+25 до відновлення здоров'я на секунду.`,
invigorations_utility_ArmorMax: `+1000 до захисту.`,
invigorations_utility_Jumps: `+5 Оновлень стрибків.`,
invigorations_utility_EnergyRegen: `+2 до відновлення енергії на секунду.`,
invigorations_offensiveLabel: `Атакуюче вдосконалення`,
invigorations_defensiveLabel: `Допоміжне вдосконалення`,
invigorations_expiryLabel: `Термін дії Зміцнення (необов'язково)`,
abilityOverride_label: `Перевизначення здібностей`,
abilityOverride_onSlot: `у комірці`,
mods_addRiven: `Добавити модифікатор Розколу`,
mods_fingerprint: `Відбиток`,
mods_fingerprintHelp: `Потрібна допомога з відбитком?`,
mods_rivens: `Модифікатори Розколу`,
mods_mods: `Модифікатори`,
mods_addMax: `Добавити макс. вдосконалений`,
mods_addMissingUnrankedMods: `Добавити недостаючі модифікатори без рівня`,
mods_removeUnranked: `Видалити модифікатори без рівня`,
mods_addMissingMaxRankMods: `Добавити недостаючі модифікатори макс. рівня`,
cheats_administratorRequirement: `Ви повинні бути адміністратором для використання цієї функції. Щоб стати адміністратором, додайте <code>\"|DISPLAYNAME|\"</code> в <code>administratorNames</code> в config.json.`,
cheats_server: `Сервер`,
cheats_skipTutorial: `Пропустити навчання`,
cheats_skipAllDialogue: `Пропустити всі діалоги`,
cheats_unlockAllScans: `Розблокувати всі сканування`,
cheats_unlockAllMissions: `Розблокувати всі місії`,
cheats_unlockAllMissions_ok: `Успіх. Будь ласка, зверніть увагу, що вам потрібно буде увійти в Доджьо/Реле або перезайти, щоб клієнт оновив Зоряну мапу.`,
cheats_infiniteCredits: `Бескінечні Кредити`,
cheats_infinitePlatinum: `Бескінечна Платина`,
cheats_infiniteEndo: `Бескінечне Ендо`,
cheats_infiniteRegalAya: `Бескінечна Королівська Ая`,
cheats_infiniteHelminthMaterials: `Бескінечні секреції Гельмінта`,
cheats_claimingBlueprintRefundsIngredients: `Повернення інгредієнтів креслеників`,
cheats_dontSubtractPurchaseCreditCost: `Не вираховувати вартість Кредитів при купівлі`,
cheats_dontSubtractPurchasePlatinumCost: `Не вираховувати вартість Платини при купівлі`,
cheats_dontSubtractPurchaseItemCost: `Не вираховувати вартість предметів при купівлі`,
cheats_dontSubtractPurchaseStandingCost: `Не вираховувати вартість репутації при купівлі`,
cheats_dontSubtractVoidTraces: `Не вираховувати кількість Відлуння`,
cheats_dontSubtractConsumables: `Не вираховувати кількість витратних матеріалів`,
cheats_unlockAllShipFeatures: `Розблокувати всі функції судна`,
cheats_unlockAllShipDecorations: `Розблокувати всі прикраси судна`,
cheats_unlockAllFlavourItems: `Розблокувати всі <abbr title="Набори анімацій, гліфи, палітри і т. д.">унікальні предмети</abbr>`,
cheats_unlockAllSkins: `Розблокувати всі скіни`,
cheats_unlockAllCapturaScenes: `Розблокувати всі сцени Світлописця`,
cheats_unlockAllDecoRecipes: `Розблокувати всі рецепти декорацій Доджьо`,
cheats_universalPolarityEverywhere: `Будь-яка полярність скрізь`,
cheats_unlockDoubleCapacityPotatoesEverywhere: `Орокінські Реактори/Каталізатори скрізь`,
cheats_unlockExilusEverywhere: `Ексилотримач скрізь`,
cheats_unlockArcanesEverywhere: `Тримач Містифікаторів скрізь`,
cheats_noDailyStandingLimits: `Без щоденних лімітів репутації`,
cheats_noDailyFocusLimit: `Без щоденних лімітів Фокусу`,
cheats_noArgonCrystalDecay: `Без розпаду Аргонових кристалів`,
cheats_noMasteryRankUpCooldown: `Підвищення ранга майстерності без очікування`,
cheats_noVendorPurchaseLimits: `Відсутність лімітів на купівлю у продавців`,
cheats_noDeathMarks: `Без позначок смерті`,
cheats_noKimCooldowns: `Чати KIM без очікування`,
cheats_fullyStockedVendors: `Повністю укомплектовані продавці`,
cheats_baroAlwaysAvailable: `Баро завжди доступний`,
cheats_baroFullyStocked: `Баро повністю укомплектований`,
cheats_syndicateMissionsRepeatable: `Повторювати місії синдиката`,
cheats_unlockAllProfitTakerStages: `Розблокувати всі етапи Привласнювачки`,
cheats_instantFinishRivenChallenge: `Миттєве завершення випробування модифікатора Розколу`,
cheats_instantResourceExtractorDrones: `Миттєво добуваючі Дрони-видобувачі`,
cheats_noResourceExtractorDronesDamage: `Без шкоди по Дронам-видобувачам`,
cheats_skipClanKeyCrafting: `Пропустити створення кланового ключа`,
cheats_noDojoRoomBuildStage: `Миттєве будівництво кімнат Доджьо`,
cheats_noDojoDecoBuildStage: `Миттєве будівництво декорацій Доджьо`,
cheats_fastDojoRoomDestruction: `Миттєве знищення кімнат Доджьо`,
cheats_noDojoResearchCosts: `Безкоштовні дослідження Доджьо`,
cheats_noDojoResearchTime: `Миттєві дослідження Доджьо`,
cheats_fastClanAscension: `Миттєве піднесення клану`,
cheats_missionsCanGiveAllRelics: `Місії можуть давати всі реліквії`,
cheats_exceptionalRelicsAlwaysGiveBronzeReward: `Вийняткові реліквії завжди дають бронзову нагороду`,
cheats_flawlessRelicsAlwaysGiveSilverReward: `Бездоганні реліквії завжди дають срібну нагороду`,
cheats_radiantRelicsAlwaysGiveGoldReward: `Сяйнисті реліквії завжди дають золоту нагороду`,
cheats_unlockAllSimarisResearchEntries: `Розблокувати всі записи досліджень Симаріса`,
cheats_disableDailyTribute: `Вимкнути щоденні нагороди`,
cheats_spoofMasteryRank: `Підроблений ранг майстерності (-1 для вимкнення)`,
cheats_relicRewardItemCountMultiplier: `Множник кількості предметів нагороди реліквії`,
cheats_nightwaveStandingMultiplier: `Множник репутації Нічної хвилі`,
cheats_save: `Зберегти`,
cheats_account: `Обліковий запис`,
cheats_unlockAllFocusSchools: `Розблокувати всі школи Фокусу`,
cheats_helminthUnlockAll: `Повністю покращити Гельмінта`,
cheats_addMissingSubsumedAbilities: `Додати відсутні поглинуті здібності`,
cheats_intrinsicsUnlockAll: `Повністю покращити Кваліфікації`,
cheats_changeSupportedSyndicate: `Підтримуваний синдикат`,
cheats_changeButton: `Змінити`,
cheats_markAllAsRead: `Помітити всі вхідні як прочитані`,
worldState: `Стан світу`,
worldState_creditBoost: `Глобальне посилення Кредитів`,
worldState_affinityBoost: `Глобальне посилення Синтезу`,
worldState_resourceBoost: `Глобальне посилення Ресурсів`,
worldState_tennoLiveRelay: `Реле TennoLive`,
worldState_baroTennoConRelay: `Реле Баро TennoCon`,
worldState_starDays: `Зоряні дні`,
worldState_galleonOfGhouls: `Гульський галеон`,
worldState_ghoulEmergence: `Зачищення від гулів`,
worldState_plagueStar: `Морова зірка`,
worldState_dogDays: `Спекотні дні`,
worldState_dogDaysRewards: `Нагороди Спекотних днів`,
worldState_wolfHunt: `Полювання на Вовка (2025)`,
worldState_longShadow: `Довга тінь`,
worldState_hallowedFlame: `Священне полум'я`,
worldState_hallowedNightmares: `Священні жахіття`,
worldState_hallowedNightmaresRewards: `Нагороди Священних жахіть`,
worldState_proxyRebellion: `Повстання роботів`,
worldState_proxyRebellionRewards: `Нагороди Повстання роботів`,
worldState_bellyOfTheBeast: `У лігві звіра`,
worldState_bellyOfTheBeastProgressOverride: `Прогрес У лігві звіра`,
worldState_eightClaw: `Вісім кігтів`,
worldState_eightClawProgressOverride: `Прогрес Восьми кігтів`,
worldState_from_year: `з |YEAR|`,
worldState_pre_year: `до |YEAR|`,
worldState_incompatibleWith: `Несумісне з:`,
enabled: `Увімкнено`,
disabled: `Вимкнено`,
worldState_we1: `Вихідні 1`,
worldState_we2: `Вихідні 2`,
worldState_we3: `Вихідні 3`,
worldState_eidolonOverride: `Цикл Рівнин Ейдолонів/Деймоса`,
worldState_day: `День/Фасс`,
worldState_night: `Ніч/Воум`,
worldState_vallisOverride: `Цикл Долини куль`,
worldState_warm: `Тепло`,
worldState_cold: `Холод`,
worldState_duviriOverride: `Цикл Дувірі`,
worldState_joy: `Радість`,
worldState_anger: `Злість`,
worldState_envy: `Заздрість`,
worldState_sorrow: `Журба`,
worldState_fear: `Страх`,
worldState_nightwaveOverride: `Сезон Нічної хвилі`,
worldState_RadioLegionIntermission13Syndicate: `Вибірка Нори 9`,
worldState_RadioLegionIntermission12Syndicate: `Вибірка Нори 8`,
worldState_RadioLegionIntermission11Syndicate: `Вибірка Нори 7`,
worldState_RadioLegionIntermission10Syndicate: `Вибірка Нори 6`,
worldState_RadioLegionIntermission9Syndicate: `Вибірка Нори 5`,
worldState_RadioLegionIntermission8Syndicate: `Вибірка Нори 4`,
worldState_RadioLegionIntermission7Syndicate: `Вибірка Нори 3`,
worldState_RadioLegionIntermission6Syndicate: `Вибірка Нори 2`,
worldState_RadioLegionIntermission5Syndicate: `Вибірка Нори 1`,
worldState_RadioLegionIntermission4Syndicate: `Вибір Нори`,
worldState_RadioLegionIntermission3Syndicate: `Антракт III`,
worldState_RadioLegion3Syndicate: `Скляр`,
worldState_RadioLegionIntermission2Syndicate: `Антракт II`,
worldState_RadioLegion2Syndicate: `Емісар`,
worldState_RadioLegionIntermissionSyndicate: `Антракт I`,
worldState_RadioLegionSyndicate: `Вовк із Сатурна-6`,
worldState_fissures: `Прориви порожнечі`,
normal: `Стандартні`,
worldState_allAtOnceNormal: `Всі одразу, в звичайному режимі`,
worldState_allAtOnceSteelPath: `Всі одразу, в режимі Шляху Сталі`,
worldState_theCircuitOverride: `Типи місій у підземеллі Дувірі`,
worldState_darvoStockMultiplier: `Множник запасів Дарво`,
worldState_varziaFullyStocked: `Повний асортимент Варзії`,
worldState_varziaOverride: `Зміна ротації Варзії`,
import_importNote: `[UNTRANSLATED] You can provide a full or partial <code>inventory.php</code> or <code>getShip.php</code> response (client representation) here.`,
import_importNote2: `Всі підтримувані поля <b>будуть перезаписані</b> у вашому акаунті.`,
import_submit: `Відправити`,
import_samples: `Приклад:`,
import_samples_maxFocus: `Всі школи Фокусу макс. рівня`,
upgrade_Equilibrium: `Згустки здоров'я дають +|VAL|% енергії, згустки енергії дають +|VAL|% здоров'я.`,
upgrade_MeleeCritDamage: `+|VAL|% до критичної шкоди від холодної зброї.`,
upgrade_PrimaryStatusChance: `+|VAL|% до ймовірності ефекту стану від основної зброї.`,
upgrade_SecondaryCritChance: `+|VAL|% до ймовірності критичної шкоди від допоміжної зброї.`,
upgrade_WarframeAbilityDuration: `+|VAL|% до тривалості дії здібностей.`,
upgrade_WarframeAbilityStrength: `+|VAL|% до потужності здібностей.`,
upgrade_WarframeArmorMax: `+|VAL| до захисту.`,
upgrade_WarframeBlastProc: `Відновлює +|VAL| щитів, коли ви вбиваєте ворога Вибуховою шкодою.`,
upgrade_WarframeCastingSpeed: `+|VAL|% до швидкості застосування здібностей.`,
upgrade_WarframeCorrosiveDamageBoost: `Дає +|VAL|% до шкоди від здібностей ворогам під впливом Корозійної шкоди.`,
upgrade_WarframeCorrosiveStack: `Збільшує макс. кількість накопичень Коррозійних ефектів стану на +|VAL|.`,
upgrade_WarframeCritDamageBoost: `Дає +|VAL|% до критичної шкоди холодної зброї. Коли макс. енергія перевищує 500, то збільшення шкоди подвоюється.`,
upgrade_WarframeElectricDamage: `Дає +|VAL1|% до Електричної шкоди від основної зрої. Додатково дає +|VAL2|% за споряджений багряний, блакитний чи фіолетовий архонтовий уламок (Поєднується з модифікаторами).`,
upgrade_WarframeElectricDamageBoost: `Дає +|VAL|% до шкоди від здібностей ворогам під впливом Електричної шкоди.`,
upgrade_WarframeEnergyMax: `+|VAL| до макс. енергії.`,
upgrade_WarframeGlobeEffectEnergy: `+|VAL|% до дієвості згустків енергії.`,
upgrade_WarframeGlobeEffectHealth: `+|VAL|% до дієвості згустків здоров'я.`,
upgrade_WarframeHealthMax: `+|VAL| до здоров'я.`,
upgrade_WarframeHPBoostFromImpact: `Отримайте +|VAL1| здоров'я за ворога, вбитого Вибуховою шкодою. Макс. — |VAL2| здоров'я.`,
upgrade_WarframeParkourVelocity: `+|VAL|% до швидкості паркуру.`,
upgrade_WarframeRadiationDamageBoost: `Дає +|VAL|% до шкоди від здібностей ворогам під впливом Радіаційної шкоди.`,
upgrade_WarframeHealthRegen: `+|VAL| до відновлення здоров'я на секунду.`,
upgrade_WarframeShieldMax: `+|VAL| до місткості щитів.`,
upgrade_WarframeStartingEnergy: `+|VAL|% до початкової макс. енергії.`,
upgrade_WarframeToxinDamage: `Токсичні ефекти стану завдаватимуть на +|VAL|% більше шкоди.`,
upgrade_WarframeToxinHeal: `Відновлює +|VAL| здоров'я за кожен раз як вороги отримують шкоду від Токсичних ефектів стану.`,
upgrade_WeaponCritBoostFromHeat: `Збільшує ймовірність критичної шкоди від допоміжної зброї на |VAL1|% щоразу, коли ви вбиваєте ворога під впливом Термічного ефекту стану. Накопичується до |VAL2|%.`,
upgrade_AvatarAbilityRange: `+7.5% Досяжність Здібностей.`,
upgrade_AvatarAbilityEfficiency: `+5% Ощадливість Здібностей.`,
upgrade_AvatarEnergyRegen: `+0.5 Відновлення Енергії в секунду.`,
upgrade_AvatarEnemyRadar: `+5м Виявлення ворогів.`,
upgrade_AvatarLootRadar: `+7м Виявлення здобичі.`,
upgrade_WeaponAmmoMax: `+15% Макс. Набоїв.`,
upgrade_EnemyArmorReductionAura: `-3% Захист Ворогів.`,
upgrade_OnExecutionAmmo: `+100% Заповнення Магазина Основного і Допоміжного Озброєння при вбивстві Милосердям.`,
upgrade_OnExecutionHealthDrop: `+100% Імовірність Падіння згустка здоров'я при вбивстві Милосердям.`,
upgrade_OnExecutionEnergyDrop: `+50% Імовірність Падіння згустка Енергії при вбивстві Милосердям.`,
upgrade_OnFailHackReset: `+50% Імовірність Повтора Зламу.`,
upgrade_DamageReductionOnHack: `+75% Зменшення Шкоди під час Зламу.`,
upgrade_OnExecutionReviveCompanion: `Вбивства Милосердям зменшують час відновлення Компаньйона на 15 секунд.`,
upgrade_OnExecutionParkourSpeed: `+60% Швидкість Паркура після вбивства Милосердям на 15 секунд.`,
upgrade_AvatarTimeLimitIncrease: `+8 секунд до Зламу.`,
upgrade_ElectrifyOnHack: `Шокувати ворогів в межах 20м під час Зламу.`,
upgrade_OnExecutionTerrify: `+50% Імовірність, що вороги в межах 15м будуть тремтіти від страху протягом 8 секунд після вбивства Милосердям.`,
upgrade_OnHackLockers: `Відкрити 5 шафок в межах 20м після Зламу.`,
upgrade_OnExecutionBlind: `Засліпити ворогів в межах 18м після вбивства Милосердям.`,
upgrade_OnExecutionDrainPower: `Наступне застосування здібності отримує +50% Потужності Здібності після вбивства Милосердям.`,
upgrade_OnHackSprintSpeed: `+75% Швидкість Бігу протягом 15 секунд після Зламу.`,
upgrade_SwiftExecute: `+50% Швидкість Вбивства Милосердям.`,
upgrade_OnHackInvis: `Невидимість протягом 15 секунд після Зламу.`,
damageType_Electricity: `Електричний`,
damageType_Fire: `Термічний`,
damageType_Freeze: `Крижаний`,
damageType_Impact: `Ударний`,
damageType_Magnetic: `Магнетичний`,
damageType_Poison: `Токсичний`,
damageType_Radiation: `Радіаційний`,
theme_dark: `Темна тема`,
theme_light: `Світла тема`,
prettier_sucks_ass: ``
};

View File

@ -1,16 +1,16 @@
// Chinese translation by meb154, bishan178, nyaoouo, qianlishun, CrazyZhang, Corvus, & qingchun
// Chinese translation by meb154, bishan178, nyaoouo, qianlishun, CrazyZhang & Corvus
dict = {
general_inventoryUpdateNote: `注意: 要在游戏中查看更改,您需要重新同步库存,例如使用客户端的 /sync 命令,访问道场/中继站或重新登录。`,
general_inventoryUpdateNote: `注意:要在游戏中查看更改,您需要重新同步库存,例如使用引导程序的 /sync 命令、访问道场/中继站或重新登录客户端.`,
general_addButton: `添加`,
general_setButton: `设置`,
general_none: ``,
general_bulkActions: `批量操作`,
general_loading: `加载中...`,
code_loginFail: `登录失败。请检查邮箱和密码。`,
code_regFail: `注册失败。账号是否已存在?`,
code_loginFail: `登录失败.请检查邮箱和密码.`,
code_regFail: `注册失败.账号已存在.`,
code_changeNameConfirm: `您想将账户名称更改为?`,
code_deleteAccountConfirm: `确定要删除您的账户 |DISPLAYNAME|(|EMAIL|) 吗?此操作不可撤销。`,
code_deleteAccountConfirm: `确定要删除账户 |DISPLAYNAME|(|EMAIL|)吗?此操作不可撤销。`,
code_archgun: `空战`,
code_melee: `近战`,
code_pistol: `手枪`,
@ -23,17 +23,17 @@ dict = {
code_kDrive: `K式悬浮板`,
code_legendaryCore: `传奇核心`,
code_traumaticPeculiar: `创伤怪奇`,
code_starter: `|MOD| (有瑕疵的)`,
code_starter: `|MOD|(有瑕疵的)`,
code_badItem: `(Imposter)`,
code_maxRank: `满级`,
code_rename: `重命名`,
code_renamePrompt: `输入新的自定义名称`,
code_renamePrompt: `输入新的自定义名称:`,
code_remove: `移除`,
code_addItemsConfirm: `确定要向您的账户添加 |COUNT| 件物品吗?`,
code_addItemsConfirm: `确定要向账户添加|COUNT|件物品吗?`,
code_succRankUp: `等级已提升`,
code_noEquipmentToRankUp: `没有可升级的装备`,
code_succAdded: `添加成功`,
code_succRemoved: `移除成功`,
code_noEquipmentToRankUp: `没有可升级的装备`,
code_succAdded: `已成功添加。`,
code_succRemoved: `已成功移除。`,
code_buffsNumber: `增益数量`,
code_cursesNumber: `负面数量`,
code_rerollsNumber: `洗卡次数`,
@ -42,12 +42,12 @@ dict = {
code_rankUp: `等级提升`,
code_rankDown: `等级下降`,
code_count: `数量`,
code_focusAllUnlocked: `所有专精学派均已解锁`,
code_focusUnlocked: `已解锁 |COUNT| 个新专精学派!需要游戏内仓库更新才能生效,您可以通过访问星图来触发仓库更新`,
code_addModsConfirm: `确定要向您的账户添加 |COUNT| 张MOD吗?`,
code_succImport: `导入成功`,
code_succRelog: `完成。需要重新登录游戏才能看到变化。`,
code_nothingToDo: `完成。没有可执行的操作。`,
code_focusAllUnlocked: `所有专精学派均已解锁`,
code_focusUnlocked: `已解锁|COUNT|个新专精学派!需要游戏内仓库更新才能生效,您可以通过访问星图来触发仓库更新.`,
code_addModsConfirm: `确定要向账户添加|COUNT|张MOD吗?`,
code_succImport: `导入成功`,
code_succRelog: `完成. 需要重新登录游戏才能看到变化.`,
code_nothingToDo: `完成. 没有可执行的操作.`,
code_gild: `镀金`,
code_moa: `恐鸟`,
code_zanuka: `猎犬`,
@ -62,9 +62,9 @@ dict = {
code_pigment: `颜料`,
code_mature: `成长并战备`,
code_unmature: `逆转衰老基因`,
code_succChange: `更改成功`,
code_requiredInvigorationUpgrade: `您必须同时选择一个进攻型和一个功能型活化属性`,
login_description: `使用您的 OpenWF 账户凭证登录(与游戏内连接本服务器时使用的昵称相同)`,
code_succChange: `更改成功.`,
code_requiredInvigorationUpgrade: `您必须同时选择一个进攻型和一个功能型活化属性.`,
login_description: `使用您的 OpenWF 账户凭证登录(与游戏内连接本服务器时使用的昵称相同).`,
login_emailLabel: `电子邮箱`,
login_passwordLabel: `密码`,
login_loginButton: `登录`,
@ -125,7 +125,7 @@ dict = {
detailedView_archonShardsDescription: `您可以使用这些无限插槽应用各种强化效果`,
detailedView_archonShardsDescription2: `请注意,在加载时,每个执政官源力石都需要一定的时间来生效。`,
detailedView_valenceBonusLabel: `效价加成`,
detailedView_valenceBonusDescription: `您可以设置或移除武器上的效价加成`,
detailedView_valenceBonusDescription: `您可以设置或移除武器上的效价加成.`,
detailedView_modularPartsLabel: `更换部件`,
detailedView_suitInvigorationLabel: `编辑战甲活化属性`,
detailedView_loadoutLabel: `配置`,
@ -168,19 +168,19 @@ dict = {
mods_addMissingUnrankedMods: `添加所有缺失的Mods`,
mods_removeUnranked: `删除所有未升级的Mods`,
mods_addMissingMaxRankMods: `添加所有缺失的满级Mods`,
cheats_administratorRequirement: `您必须是管理员才能使用此功能。要成为管理员,请在 config.json 中将 <code>|DISPLAYNAME|</code> 添加到 <code>administratorNames</code>`,
cheats_administratorRequirement: `您必须是管理员才能使用此功能.要成为管理员,请将 <code>|DISPLAYNAME|</code> 添加到 config.json 的 <code>administratorNames</code> 中.`,
cheats_server: `服务器`,
cheats_skipTutorial: `跳过教程`,
cheats_skipAllDialogue: `跳过所有对话`,
cheats_unlockAllScans: `解锁所有扫描`,
cheats_unlockAllMissions: `解锁所有星图`,
cheats_unlockAllMissions_ok: `操作成功请注意,您需要进入道场/中继站或重新登录以刷新星图数据。`,
cheats_unlockAllMissions: `解锁所有任务`,
cheats_unlockAllMissions_ok: `操作成功.请注意,您需要进入道场/中继站或重新登录客户端以刷新星图数据。`,
cheats_infiniteCredits: `无限现金`,
cheats_infinitePlatinum: `无限白金`,
cheats_infiniteEndo: `无限内融核心`,
cheats_infiniteRegalAya: `无限御品阿耶`,
cheats_infiniteHelminthMaterials: `无限Helminth材料`,
cheats_claimingBlueprintRefundsIngredients: `蓝图制造完成领取后返还材料`,
cheats_claimingBlueprintRefundsIngredients: `取消蓝图制造时返还材料`,
cheats_dontSubtractPurchaseCreditCost: `购物时不减少现金花费`,
cheats_dontSubtractPurchasePlatinumCost: `购物时不减少白金花费`,
cheats_dontSubtractPurchaseItemCost: `购物时不减少物品花费`,
@ -242,28 +242,10 @@ dict = {
worldState_creditBoost: `现金加成`,
worldState_affinityBoost: `经验加成`,
worldState_resourceBoost: `资源加成`,
worldState_tennoLiveRelay: `TennoLive中继站`,
worldState_baroTennoConRelay: `Baro的TennoCon中继站`,
worldState_tennoLiveRelay: `TennoLive 中继站`,
worldState_baroTennoConRelay: `[UNTRANSLATED] Baro's TennoCon Relay`,
worldState_starDays: `活动:星日`,
worldState_galleonOfGhouls: `战术警报:尸鬼的帆船战舰`,
worldState_ghoulEmergence: `尸鬼净化`,
worldState_plagueStar: `瘟疫之星`,
worldState_dogDays: `三伏天`,
worldState_dogDaysRewards: `[UNTRANSLATED] Dog Days Rewards`,
worldState_wolfHunt: `恶狼狩猎 (2025)`,
worldState_longShadow: `暗夜长影`,
worldState_hallowedFlame: `万圣之焰`,
worldState_hallowedNightmares: `万圣噩梦`,
worldState_hallowedNightmaresRewards: `[UNTRANSLATED] Hallowed Nightmares Rewards`,
worldState_proxyRebellion: `机械叛乱`,
worldState_proxyRebellionRewards: `[UNTRANSLATED] Proxy Rebellion Rewards`,
worldState_bellyOfTheBeast: `兽之腹`,
worldState_bellyOfTheBeastProgressOverride: `[UNTRANSLATED] Belly of the Beast Progress`,
worldState_eightClaw: `八爪`,
worldState_eightClawProgressOverride: `[UNTRANSLATED] Eight Claw Progress`,
worldState_from_year: `[UNTRANSLATED] from |YEAR|`,
worldState_pre_year: `[UNTRANSLATED] pre |YEAR|`,
worldState_incompatibleWith: `[UNTRANSLATED] Incompatible with:`,
enabled: `启用`,
disabled: `关闭/取消配置`,
worldState_we1: `活动阶段:第一周`,
@ -307,8 +289,7 @@ dict = {
worldState_varziaFullyStocked: `瓦奇娅开启全部库存商品`,
worldState_varziaOverride: `瓦奇娅(Prime重生)轮换状态`,
import_importNote: `[UNTRANSLATED] You can provide a full or partial <code>inventory.php</code> or <code>getShip.php</code> response (client representation) here.`,
import_importNote2: `支持的所有字段<b>将被覆盖</b>到您的账户中。`,
import_importNote: `您可以在此处提供完整或部分库存响应(客户端表示).支持的所有字段<b>将被覆盖</b>到您的账户中.`,
import_submit: `提交`,
import_samples: `示例:`,
import_samples_maxFocus: `所有专精学派完全精通`,