Compare commits

...

19 Commits

Author SHA1 Message Date
956ba38b7d fix(webui): handle name already being taken at rename (#2659)
Closes #2643

Reviewed-on: OpenWF/SpaceNinjaServer#2659
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-08-17 13:12:40 -07:00
660c3f3ddf fix(webui): differentiate between nonce invalidation & forced logout (#2658)
Closes #2642

Reviewed-on: OpenWF/SpaceNinjaServer#2658
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-08-17 13:12:29 -07:00
024b806af1 feat(webui): display Favorite items first (#2656)
Closes #2653

Reviewed-on: OpenWF/SpaceNinjaServer#2656
Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com>
Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
2025-08-17 13:12:06 -07:00
b885d7766c feat: warframe anniversary goals (#2640)
Also adds `useAnniversaryTagForOldGoals` to display old Goals in GUI
Re #1103

Reviewed-on: OpenWF/SpaceNinjaServer#2640
Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com>
Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
2025-08-17 13:11:55 -07:00
d0743654dd feat: orphix venom (#2637)
Without rotation on last mission
Re #1103
Thanks to https://wiki.warframe.com/w/World_State/Example

Reviewed-on: OpenWF/SpaceNinjaServer#2637
Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com>
Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
2025-08-16 09:52:58 -07:00
cddd2cdd2b chore: fix inconsistencies with getGuildEventScoreController (#2641)
bring it more in line with the rest of the codebase

Reviewed-on: OpenWF/SpaceNinjaServer#2641
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-08-16 09:52:36 -07:00
62a6042c9c fix(webui): save ProgressOverride value (#2638)
Reviewed-on: OpenWF/SpaceNinjaServer#2638
Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com>
Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
2025-08-16 05:42:09 -07:00
e8d4d84d6e chore(webui): update uk (#2639)
Reviewed-on: OpenWF/SpaceNinjaServer#2639
Co-authored-by: LoseFace <loseface@noreply.localhost>
Co-committed-by: LoseFace <loseface@noreply.localhost>
2025-08-16 05:41:12 -07:00
62881aaa36 feat: articula customizations (#2636)
Reviewed-on: OpenWF/SpaceNinjaServer#2636
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-08-16 05:40:16 -07:00
df316e3a7a feat: conclave challenges rotation (#2635)
Re #1192

Reviewed-on: OpenWF/SpaceNinjaServer#2635
Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com>
Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
2025-08-16 05:39:23 -07:00
264e9cfc98 fix: use flat rush cost at <50% progress (#2634)
otherwise the cost would be increased instead of decreased

Reviewed-on: OpenWF/SpaceNinjaServer#2634
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-08-16 05:39:00 -07:00
5d5554a80e feat: h-09 apex turret sumdali reward (#2633)
Closes #2630

Reviewed-on: OpenWF/SpaceNinjaServer#2633
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-08-16 05:38:48 -07:00
da14a4081b chore: put reward year into goal _id (#2626)
Closes #2623

Reviewed-on: OpenWF/SpaceNinjaServer#2626
Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com>
Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
2025-08-15 21:02:15 -07:00
b0b68f474a feat: getShip import (#2627)
Re #2592
Unsure about import note, is it okay that we leave the API path?

Reviewed-on: OpenWF/SpaceNinjaServer#2627
Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com>
Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
2025-08-15 15:13:34 -07:00
ab214df1a8 chore(webui): update ru & uk (#2632)
Updated and improved some translations

Reviewed-on: OpenWF/SpaceNinjaServer#2632
Co-authored-by: LoseFace <loseface@noreply.localhost>
Co-committed-by: LoseFace <loseface@noreply.localhost>
2025-08-15 14:57:04 -07:00
9f8105d7f1 fix: extractor drone reward amounts (#2629)
Fixes #2628

Reviewed-on: OpenWF/SpaceNinjaServer#2629
Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com>
Co-authored-by: VampireKitten <dynamightkobold@gmail.com>
Co-committed-by: VampireKitten <dynamightkobold@gmail.com>
2025-08-15 14:56:39 -07:00
c47a29ec96 chore: note 2025-08-15 18:15:10 +02:00
6d727c50f4 chore: handle addItem of GhoulFragmentRewards (#2625)
Closes #2624

Reviewed-on: OpenWF/SpaceNinjaServer#2625
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-08-15 08:15:51 -07:00
bf04755c36 feat: belly of the beast / eight claw (#2621)
Re #1103

Reviewed-on: OpenWF/SpaceNinjaServer#2621
Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com>
Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
2025-08-15 08:14:36 -07:00
48 changed files with 2257 additions and 724 deletions

View File

@ -59,7 +59,8 @@
"nightwaveStandingMultiplier": 1,
"unfaithfulBugFixes": {
"ignore1999LastRegionPlayed": false,
"fixXtraCheeseTimer": false
"fixXtraCheeseTimer": false,
"useAnniversaryTagForOldGoals": true
},
"worldState": {
"creditBoost": false,
@ -67,8 +68,10 @@
"resourceBoost": false,
"tennoLiveRelay": false,
"wolfHunt": false,
"orphixVenom": false,
"longShadow": false,
"hallowedFlame": false,
"anniversary": null,
"hallowedNightmares": false,
"hallowedNightmaresRewardsOverride": 0,
"proxyRebellion": false,
@ -79,6 +82,10 @@
"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.81",
"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.81",
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.81.tgz",
"integrity": "sha512-kh3e21XThVDSwdC3TJsMsXZnlZ4B/21HdeJkKcjuTygpCd842EPEKS3lRZl3mpXFOmdha744vAW1XEyHfiLofg=="
},
"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.81",
"warframe-riven-info": "^0.1.2",
"winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0",

View File

@ -102,7 +102,10 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
const secondsElapsed = Math.trunc(Date.now() / 1000) - start;
const progress = secondsElapsed / recipe.buildTime;
logger.debug(`rushing recipe at ${Math.trunc(progress * 100)}% completion`);
const cost = Math.round(recipe.skipBuildTimePrice * (1 - (progress - 0.5)));
const cost =
progress > 0.5
? Math.round(recipe.skipBuildTimePrice * (1 - (progress - 0.5)))
: recipe.skipBuildTimePrice;
InventoryChanges = {
...InventoryChanges,
...updateCurrency(inventory, cost, true)

View File

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

View File

@ -0,0 +1,26 @@
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) {
res.json({
Tier: guild.Tier,
GoalProgress: {
Count: goal.Count,
Tag: goal.Tag,
_id: { $oid: goal.goalId }
}
});
return;
}
}
res.json({});
};

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);
addBooster(boosterType, 3 * 3600, inventory); // unfaithful, but current HUB server does not handle broadcasting, so this way users can bless themselves.
await inventory.save();
let token = "";

View File

@ -88,8 +88,7 @@ export const loginController: RequestHandler = async (request, response) => {
account.LastLogin = new Date();
await account.save();
// Tell WebUI its nonce has been invalidated
sendWsBroadcastTo(account._id.toString(), { logged_out: true });
sendWsBroadcastTo(account._id.toString(), { nonce_updated: true });
response.json(createLoginResponse(myAddress, myUrlBase, account.toJSON(), buildLabel));
};

View File

@ -21,8 +21,7 @@ export const logoutController: RequestHandler = async (req, res) => {
}
);
if (stat.modifiedCount) {
// Tell WebUI its nonce has been invalidated
sendWsBroadcastTo(req.query.accountId as string, { logged_out: true });
sendWsBroadcastTo(req.query.accountId as string, { nonce_updated: true });
}
res.writeHead(200, {

View File

@ -1,23 +1,19 @@
import { getAccountIdForRequest } from "@/src/services/loginService";
import { IPictureFrameInfo, ISetPlacedDecoInfoRequest } from "@/src/types/personalRoomsTypes";
import { ISetPlacedDecoInfoRequest } from "@/src/types/personalRoomsTypes";
import { RequestHandler } from "express";
import { handleSetPlacedDecoInfo } from "@/src/services/shipCustomizationsService";
export const setPlacedDecoInfoController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const payload = JSON.parse(req.body as string) as ISetPlacedDecoInfoRequest;
//console.log(JSON.stringify(payload, null, 2));
await handleSetPlacedDecoInfo(accountId, payload);
res.json({
DecoId: payload.DecoId,
IsPicture: true,
PictureFrameInfo: payload.PictureFrameInfo,
BootLocation: payload.BootLocation
...payload,
IsPicture: !!payload.PictureFrameInfo
} satisfies ISetPlacedDecoInfoResponse);
};
interface ISetPlacedDecoInfoResponse {
DecoId: string;
interface ISetPlacedDecoInfoResponse extends ISetPlacedDecoInfoRequest {
IsPicture: boolean;
PictureFrameInfo?: IPictureFrameInfo;
BootLocation?: string;
}

View File

@ -1,8 +1,10 @@
import { importInventory, importLoadOutPresets } from "@/src/services/importService";
import { importInventory, importLoadOutPresets, importPersonalRooms } 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) => {
@ -13,15 +15,21 @@ export const importController: RequestHandler = async (req, res) => {
importInventory(inventory, request.inventory);
await inventory.save();
if (request.inventory.LoadOutPresets) {
if ("LoadOutPresets" in request.inventory && 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>;
inventory: Partial<IInventoryClient> | Partial<IGetShipResponse>;
}

View File

@ -19,6 +19,8 @@ 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,
@ -174,6 +176,28 @@ 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 },
@ -206,7 +230,8 @@ 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 }
ClassChanges: { type: [guildLogEntryNumberSchema], default: undefined },
GoalProgress: { type: [goalProgressSchema], default: undefined }
},
{ id: false }
);

View File

@ -85,8 +85,8 @@ import {
IAccolades,
IHubNpcCustomization,
IEndlessXpReward,
IPersonalGoalProgressDatabase,
IPersonalGoalProgressClient,
IGoalProgressDatabase,
IGoalProgressClient,
IKubrowPetPrintClient,
IKubrowPetPrintDatabase
} from "@/src/types/inventoryTypes/inventoryTypes";
@ -445,7 +445,7 @@ const discoveredMarkerSchema = new Schema<IDiscoveredMarker>(
{ _id: false }
);
const personalGoalProgressSchema = new Schema<IPersonalGoalProgressDatabase>(
const personalGoalProgressSchema = new Schema<IGoalProgressDatabase>(
{
Best: Number,
Count: Number,
@ -458,8 +458,8 @@ const personalGoalProgressSchema = new Schema<IPersonalGoalProgressDatabase>(
personalGoalProgressSchema.set("toJSON", {
virtuals: true,
transform(_doc, obj: Record<string, any>) {
const db = obj as IPersonalGoalProgressDatabase;
const client = obj as IPersonalGoalProgressClient;
const db = obj as IGoalProgressDatabase;
const client = obj as IGoalProgressClient;
client._id = toOid(db.goalId);

View File

@ -25,7 +25,7 @@ export const EquipmentSelectionSchema = new Schema<IEquipmentSelection>(
}
);
const loadoutConfigSchema = new Schema<ILoadoutConfigDatabase>(
export const loadoutConfigSchema = new Schema<ILoadoutConfigDatabase>(
{
FocusSchool: String,
PresetIcon: String,

View File

@ -8,7 +8,7 @@ const leaderboardEntrySchema = new Schema<ILeaderboardEntryDatabase>(
displayName: { type: String, required: true },
score: { type: Number, required: true },
guildId: Schema.Types.ObjectId,
expiry: { type: Date, required: true },
expiry: Date,
guildTier: Number
},
{ id: false }

View File

@ -1,6 +1,7 @@
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
import {
IApartmentDatabase,
ICustomizationInfoDatabase,
IFavouriteLoadoutDatabase,
IGardeningDatabase,
IOrbiterClient,
@ -11,12 +12,13 @@ import {
IPlantClient,
IPlantDatabase,
IPlanterDatabase,
IRoom,
IRoomDatabase,
ITailorShopDatabase,
PersonalRoomsModelType
} from "@/src/types/personalRoomsTypes";
import { Schema, Types, model } from "mongoose";
import { colorSchema, shipCustomizationSchema } from "@/src/models/commonModel";
import { loadoutConfigSchema } from "@/src/models/inventoryModels/loadoutModel";
export const pictureFrameInfoSchema = new Schema<IPictureFrameInfo>(
{
@ -34,7 +36,20 @@ export const pictureFrameInfoSchema = new Schema<IPictureFrameInfo>(
TextColorB: Number,
TextOrientation: Number
},
{ id: false, _id: false }
{ _id: false }
);
export const customizationInfoSchema = new Schema<ICustomizationInfoDatabase>(
{
Anim: String,
AnimPose: Number,
LoadOutPreset: loadoutConfigSchema,
VehiclePreset: loadoutConfigSchema,
EquippedWeapon: String,
AvatarType: String,
LoadOutType: String
},
{ _id: false }
);
const placedDecosSchema = new Schema<IPlacedDecosDatabase>(
@ -44,7 +59,9 @@ const placedDecosSchema = new Schema<IPlacedDecosDatabase>(
Rot: [Number],
Scale: Number,
Sockets: Number,
PictureFrameInfo: { type: pictureFrameInfoSchema, default: undefined }
PictureFrameInfo: { type: pictureFrameInfoSchema, default: undefined },
CustomizationInfo: { type: customizationInfoSchema, default: undefined },
AnimPoseItem: String
},
{ id: false }
);
@ -60,7 +77,7 @@ placedDecosSchema.set("toJSON", {
}
});
const roomSchema = new Schema<IRoom>(
const roomSchema = new Schema<IRoomDatabase>(
{
Name: String,
MaxCapacity: Number,

View File

@ -97,7 +97,19 @@ const statsSchema = new Schema<IStatsDatabase>({
SentinelGameScore: Number,
CaliberChicksScore: Number,
OlliesCrashCourseScore: Number,
DojoObstacleScore: Number
DojoObstacleScore: Number,
Halloween16: Number,
AmalgamEventScoreMax: Number,
Halloween19ScoreMax: Number,
FlotillaEventScore: Number,
FlotillaSpaceBadgesTier1: Number,
FlotillaSpaceBadgesTier2: Number,
FlotillaSpaceBadgesTier3: Number,
FlotillaGroundBadgesTier1: Number,
FlotillaGroundBadgesTier2: Number,
FlotillaGroundBadgesTier3: Number,
MechSurvivalScoreMax: Number
});
statsSchema.set("toJSON", {

View File

@ -62,6 +62,7 @@ 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/getGuildEventScoreController";
import { getGuildLogController } from "@/src/controllers/api/getGuildLogController";
import { getIgnoredUsersController } from "@/src/controllers/api/getIgnoredUsersController";
import { getNewRewardSeedController } from "@/src/controllers/api/getNewRewardSeedController";
@ -192,6 +193,7 @@ 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

View File

@ -8,5 +8,6 @@ const statsRouter = express.Router();
statsRouter.get("/view.php", viewController);
statsRouter.post("/upload.php", uploadController);
statsRouter.post("/leaderboardWeekly.php", leaderboardController);
statsRouter.post("/leaderboardArchived.php", leaderboardController);
export { statsRouter };

View File

@ -71,6 +71,7 @@ export interface IConfig {
unfaithfulBugFixes?: {
ignore1999LastRegionPlayed?: boolean;
fixXtraCheeseTimer?: boolean;
useAnniversaryTagForOldGoals?: boolean;
};
worldState?: {
creditBoost?: boolean;
@ -79,8 +80,10 @@ export interface IConfig {
tennoLiveRelay?: boolean;
baroTennoConRelay?: boolean;
wolfHunt?: boolean;
orphixVenom?: boolean;
longShadow?: boolean;
hallowedFlame?: boolean;
anniversary?: number;
hallowedNightmares?: boolean;
hallowedNightmaresRewardsOverride?: number;
proxyRebellion?: boolean;
@ -91,6 +94,10 @@ export interface IConfig {
starDaysOverride?: boolean;
dogDaysOverride?: boolean;
dogDaysRewardsOverride?: number;
bellyOfTheBeast?: boolean;
bellyOfTheBeastProgressOverride?: number;
eightClaw?: boolean;
eightClawProgressOverride?: number;
eidolonOverride?: string;
vallisOverride?: string;
duviriOverride?: string;

View File

@ -115,7 +115,14 @@ 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
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
};
};
@ -809,3 +816,100 @@ 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"
]
},
MechSurvival: {
guildGoals: [
[1390, 5860, 13920, 18850],
[3510, 22275, 69120, 137250],
[11700, 75250, 230400, 457500],
[35100, 222750, 691200, 1372500],
[117000, 742500, 2304000, 4575000]
],
rewards: [
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/MechEventTrophyTerracottaRecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/MechEventTrophyBronzeRecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/MechEventTrophySilverRecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/MechEventTrophyGoldRecipe"
]
}
};

View File

@ -44,6 +44,28 @@ import {
IKubrowPetDetailsClient,
IKubrowPetDetailsDatabase
} from "@/src/types/equipmentTypes";
import {
IApartmentClient,
IApartmentDatabase,
ICustomizationInfoClient,
ICustomizationInfoDatabase,
IFavouriteLoadout,
IFavouriteLoadoutDatabase,
IGetShipResponse,
IOrbiterClient,
IOrbiterDatabase,
IPersonalRoomsDatabase,
IPlacedDecosClient,
IPlacedDecosDatabase,
IPlantClient,
IPlantDatabase,
IPlanterClient,
IPlanterDatabase,
IRoomClient,
IRoomDatabase,
ITailorShop,
ITailorShopDatabase
} from "@/src/types/personalRoomsTypes";
const convertDate = (value: IMongoDate): Date => {
return new Date(parseInt(value.$date.$numberLong));
@ -429,3 +451,84 @@ export const importLoadOutPresets = (db: ILoadoutDatabase, client: ILoadOutPrese
db.OPERATOR_ADULT = client.OPERATOR_ADULT.map(convertLoadOutConfig);
db.DRIFTER = client.DRIFTER.map(convertLoadOutConfig);
};
export const convertCustomizationInfo = (client: ICustomizationInfoClient): ICustomizationInfoDatabase => {
return {
...client,
LoadOutPreset: client.LoadOutPreset ? convertLoadOutConfig(client.LoadOutPreset) : undefined,
VehiclePreset: client.VehiclePreset ? convertLoadOutConfig(client.VehiclePreset) : undefined
};
};
const convertDeco = (client: IPlacedDecosClient): IPlacedDecosDatabase => {
const { id, ...rest } = client;
return {
...rest,
CustomizationInfo: client.CustomizationInfo ? convertCustomizationInfo(client.CustomizationInfo) : undefined,
_id: new Types.ObjectId(id.$oid)
};
};
const convertRoom = (client: IRoomClient): IRoomDatabase => {
return {
...client,
PlacedDecos: client.PlacedDecos ? client.PlacedDecos.map(convertDeco) : []
};
};
const convertShip = (client: IOrbiterClient): IOrbiterDatabase => {
return {
...client,
ShipInterior: {
...client.ShipInterior,
Colors: Array.isArray(client.ShipInterior.Colors) ? {} : client.ShipInterior.Colors
},
Rooms: client.Rooms.map(convertRoom),
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,
Rooms: client.Rooms.map(convertRoom),
Gardening: { Planters: client.Gardening.Planters.map(convertPlanter) },
FavouriteLoadouts: client.FavouriteLoadouts ? client.FavouriteLoadouts.map(convertFavouriteLoadout) : []
};
};
const convertTailorShop = (client: ITailorShop): ITailorShopDatabase => {
return {
...client,
Rooms: client.Rooms.map(convertRoom),
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

@ -847,6 +847,32 @@ 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;
}

View File

@ -1,38 +1,66 @@
import { Guild } from "@/src/models/guildModel";
import { Leaderboard, TLeaderboardEntryDocument } from "@/src/models/leaderboardModel";
import { ILeaderboardEntryClient } from "@/src/types/leaderboardTypes";
import { handleGuildGoalProgress } from "@/src/services/guildService";
import { getWorldState } from "@/src/services/worldStateService";
import { Types } from "mongoose";
export const submitLeaderboardScore = async (
schedule: "weekly" | "daily",
schedule: "weekly" | "daily" | "events",
leaderboard: string,
ownerId: string,
displayName: string,
score: number,
guildId: string | undefined
): Promise<void> => {
let expiry: Date;
let expiry: Date | undefined;
if (schedule == "daily") {
expiry = new Date(Math.trunc(Date.now() / 86400000) * 86400000 + 86400000);
} else {
} else if (schedule == "weekly") {
const EPOCH = 1734307200 * 1000; // Monday
const week = Math.trunc((Date.now() - EPOCH) / 604800000);
const weekStart = EPOCH + week * 604800000;
const weekEnd = weekStart + 604800000;
expiry = new Date(weekEnd);
}
if (guildId) {
const guild = (await Guild.findById(guildId, "Name Tier GoalProgress VaultDecoRecipes"))!;
if (schedule == "events") {
const prevAccount = await Leaderboard.findOne(
{ leaderboard: `${schedule}.accounts.${leaderboard}`, ownerId },
"score"
);
const delta = score - (prevAccount?.score ?? 0);
if (delta > 0) {
await Leaderboard.findOneAndUpdate(
{ leaderboard: `${schedule}.guilds.${leaderboard}`, ownerId: guildId },
{ $inc: { score: delta }, $set: { displayName: guild.Name, guildTier: guild.Tier } },
{ upsert: true }
);
const goal = getWorldState().Goals.find(x => x.ScoreMaxTag == leaderboard);
if (goal) {
await handleGuildGoalProgress(guild, {
Count: delta,
Tag: goal.Tag,
goalId: new Types.ObjectId(goal._id.$oid)
});
}
}
} else {
await Leaderboard.findOneAndUpdate(
{ leaderboard: `${schedule}.guilds.${leaderboard}`, ownerId: guildId },
{ $max: { score }, $set: { displayName: guild.Name, guildTier: guild.Tier, expiry } },
{ upsert: true, new: true }
);
}
}
await Leaderboard.findOneAndUpdate(
{ leaderboard: `${schedule}.accounts.${leaderboard}`, ownerId },
{ $max: { score }, $set: { displayName, guildId, expiry } },
{ upsert: true }
);
if (guildId) {
const guild = (await Guild.findById(guildId, "Name Tier"))!;
await Leaderboard.findOneAndUpdate(
{ leaderboard: `${schedule}.guilds.${leaderboard}`, ownerId: guildId },
{ $max: { score }, $set: { displayName: guild.Name, guildTier: guild.Tier, expiry } },
{ upsert: true }
);
}
};
export const getLeaderboard = async (
@ -43,6 +71,7 @@ export const getLeaderboard = async (
guildId: string | undefined,
guildTier: number | undefined
): Promise<ILeaderboardEntryClient[]> => {
leaderboard = leaderboard.replace("archived", guildTier || guildId ? "events.guilds" : "events.accounts");
const filter: { leaderboard: string; guildId?: string; guildTier?: number } = { leaderboard };
if (guildId) {
filter.guildId = guildId;

View File

@ -81,6 +81,8 @@ 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)
@ -650,7 +652,12 @@ export const addMissionInventoryUpdates = async (
}
}
if (currentMissionKey && currentMissionKey in goalMessagesByKey) {
const totalCount = (goalProgress?.Count ?? 0) + uploadProgress.Count;
let countBeforeUpload = goalProgress?.Count ?? 0;
let totalCount = countBeforeUpload + uploadProgress.Count;
if (goal.Best) {
countBeforeUpload = goalProgress?.Best ?? 0;
totalCount = uploadProgress.Best;
}
let reward;
if (goal.InterimGoals && goal.InterimRewards) {
@ -658,7 +665,7 @@ export const addMissionInventoryUpdates = async (
if (
goal.InterimGoals[i] &&
goal.InterimGoals[i] <= totalCount &&
(!goalProgress || goalProgress.Count < goal.InterimGoals[i]) &&
(!goalProgress || countBeforeUpload < goal.InterimGoals[i]) &&
goal.InterimRewards[i]
) {
reward = goal.InterimRewards[i];
@ -670,7 +677,7 @@ export const addMissionInventoryUpdates = async (
!reward &&
goal.Goal &&
goal.Goal <= totalCount &&
(!goalProgress || goalProgress.Count < goal.Goal) &&
(!goalProgress || countBeforeUpload < goal.Goal) &&
goal.Reward
) {
reward = goal.Reward;
@ -679,7 +686,7 @@ export const addMissionInventoryUpdates = async (
!reward &&
goal.BonusGoal &&
goal.BonusGoal <= totalCount &&
(!goalProgress || goalProgress.Count < goal.BonusGoal) &&
(!goalProgress || countBeforeUpload < goal.BonusGoal) &&
goal.BonusReward
) {
reward = goal.BonusReward;
@ -705,6 +712,20 @@ export const addMissionInventoryUpdates = async (
if (reward.credits) {
message.RegularCredits = reward.credits;
}
if (info.arg) {
const args: Record<string, string | number> = {
PLAYER_NAME: account.DisplayName,
CREDIT_REWARD: reward.credits ?? 0
};
info.arg.forEach(key => {
const value = args[key];
if (value) {
message.arg ??= [];
message.arg.push({ Key: key, Tag: value });
}
});
}
await createMessage(inventory.accountOwnerId, [message]);
}
@ -712,10 +733,20 @@ export const addMissionInventoryUpdates = async (
}
if (goalProgress) {
goalProgress.Best = Math.max(goalProgress.Best, uploadProgress.Best);
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;
}
@ -1079,6 +1110,12 @@ export const addMissionRewards = async (
}
}
}
if (rewardInfo.GoalProgressAmount && goal.Tag.startsWith("MechSurvival")) {
MissionRewards.push({
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/MechSurvivalEventCreds",
ItemCount: Math.trunc(rewardInfo.GoalProgressAmount / 10)
});
}
}
}
@ -1297,6 +1334,27 @@ export const addMissionRewards = async (
logger.error(`unknown droptable ${si.DropTable} for DROP_BLUEPRINT`);
}
}
// e.g. H-09 Apex Turret Sumdali
if (si.DROP_MISC_ITEM) {
const resourceDroptable = droptables.find(x => x.type == "resource");
if (resourceDroptable) {
for (let i = 0; i != si.DROP_MISC_ITEM.length; ++i) {
const reward = getRandomReward(resourceDroptable.items)!;
logger.debug(`stripped droptable (resources pool) rolled`, reward);
if (Object.keys(await addItem(inventory, reward.type)).length == 0) {
logger.debug(`item already owned, skipping`);
} else {
MissionRewards.push({
StoreItem: toStoreItem(reward.type),
ItemCount: 1,
FromEnemyCache: true // to show "identified"
});
}
}
} else {
logger.error(`unknown droptable ${si.DropTable} for DROP_BLUEPRINT`);
}
}
}
}
@ -2227,7 +2285,7 @@ const getHexBounties = (seed: number): { nodes: string[]; buddies: string[] } =>
return { nodes, buddies };
};*/
const goalMessagesByKey: Record<string, { sndr: string; msg: string; sub: string; icon: string }> = {
const goalMessagesByKey: Record<string, { sndr: string; msg: string; sub: string; icon: string; arg?: string[] }> = {
"/Lotus/Types/Keys/GalleonRobberyAlert": {
sndr: "/Lotus/Language/Bosses/BossCouncilorVayHek",
msg: "/Lotus/Language/Messages/GalleonRobbery2025RewardMsgA",
@ -2340,19 +2398,22 @@ const goalMessagesByKey: Record<string, { sndr: string; msg: string; sub: string
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/G1Quests/RazorbackArmadaRewardBody",
sub: "/Lotus/Language/G1Quests/GenericTacAlertSmallRewardMsgTitle",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["CREDIT_REWARD"]
},
"/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"
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["CREDIT_REWARD"]
},
"/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"
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["CREDIT_REWARD"]
},
"/Lotus/Types/Keys/TacAlertKeyProxyRebellionFour": {
sndr: "/Lotus/Language/Bosses/Lotus",
@ -2364,7 +2425,8 @@ const goalMessagesByKey: Record<string, { sndr: string; msg: string; sub: string
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/G1Quests/ProjectNightwatchRewardMsgA",
sub: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionOneTitle",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["CREDIT_REWARD"]
},
"/Lotus/Types/Keys/TacAlertKeyProjectNightwatch": {
sndr: "/Lotus/Language/Bosses/Lotus",
@ -2383,5 +2445,175 @@ const goalMessagesByKey: Record<string, { sndr: string; msg: string; sub: string
msg: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionRewardBody",
sub: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionFourTitle",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
},
"/Lotus/Types/Keys/MechSurvivalCorpusShip": {
sndr: "/Lotus/Language/Bosses/DeimosFather",
msg: "/Lotus/Language/Inbox/MechEvent2020Tier1CompleteDesc",
sub: "/Lotus/Language/Inbox/MechEvent2020Tier1CompleteTitle",
icon: "/Lotus/Interface/Icons/Npcs/Entrati/Father.png"
},
"/Lotus/Types/Keys/MechSurvivalGrineerGalleon": {
sndr: "/Lotus/Language/Bosses/DeimosFather",
msg: "/Lotus/Language/Inbox/MechEvent2020Tier2CompleteDesc",
sub: "/Lotus/Language/Inbox/MechEvent2020Tier2CompleteTitle",
icon: "/Lotus/Interface/Icons/Npcs/Entrati/Father.png"
},
"/Lotus/Types/Keys/MechSurvivalGasCity": {
sndr: "/Lotus/Language/Bosses/DeimosFather",
msg: "/Lotus/Language/Inbox/MechEvent2020Tier3CompleteDesc",
sub: "/Lotus/Language/Inbox/MechEvent2020Tier3CompleteTitle",
icon: "/Lotus/Interface/Icons/Npcs/Entrati/Father.png"
},
"/Lotus/Types/Keys/MechSurvivalCorpusShipEndurance": {
sndr: "/Lotus/Language/Bosses/DeimosFather",
msg: "/Lotus/Language/Inbox/MechEvent2020Tier3CompleteDesc",
sub: "/Lotus/Language/Inbox/MechEvent2020Tier3CompleteTitle",
icon: "/Lotus/Interface/Icons/Npcs/Entrati/Father.png"
},
"/Lotus/Types/Keys/MechSurvivalGrineerGalleonEndurance": {
sndr: "/Lotus/Language/Bosses/DeimosFather",
msg: "/Lotus/Language/Inbox/MechEvent2020Tier3CompleteDesc",
sub: "/Lotus/Language/Inbox/MechEvent2020Tier3CompleteTitle",
icon: "/Lotus/Interface/Icons/Npcs/Entrati/Father.png"
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2019E": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgB",
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleB",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2020F": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgC",
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleB",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2024ChallengeModeA": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgD",
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleD",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2017C": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2019RewardMsgC",
sub: "/Lotus/Language/Messages/Anniversary2019MissionTitleC",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2020H": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2020RewardMsgH",
sub: "/Lotus/Language/Messages/Anniversary2020MissionTitleH",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2022J": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2022RewardMsgJ",
sub: "/Lotus/Language/Messages/Anniversary2022MissionTitleJ",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025D": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgB",
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleB",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025ChallengeModeA": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgC",
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleC",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2020G": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2020RewardMsgG",
sub: "/Lotus/Language/Messages/Anniversary2020MissionTitleG",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2017B": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2019RewardMsgB",
sub: "/Lotus/Language/Messages/Anniversary2019MissionTitleB",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2017A": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2019RewardMsgA",
sub: "/Lotus/Language/Messages/Anniversary2019MissionTitleA",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2023K": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgG",
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleG",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025ChallengeModeB": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgD",
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleD",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025A": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgA",
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleA",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2018D": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgG",
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleG",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025C": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgF",
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleF",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2024L": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgA",
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleA",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2024ChallengeModeB": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgE",
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleE",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2021I": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgH",
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleH",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025B": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgE",
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleE",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
arg: ["PLAYER_NAME"]
}
};

View File

@ -36,6 +36,9 @@ 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/");
@ -137,6 +140,22 @@ 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(

View File

@ -19,6 +19,7 @@ import { Guild } from "@/src/models/guildModel";
import { hasGuildPermission } from "@/src/services/guildService";
import { GuildPermission } from "@/src/types/guildTypes";
import { ExportResources } from "warframe-public-export-plus";
import { convertCustomizationInfo } from "@/src/services/importService";
export const setShipCustomizations = async (
accountId: string,
@ -269,6 +270,8 @@ export const handleSetPlacedDecoInfo = async (accountId: string, req: ISetPlaced
}
placedDeco.PictureFrameInfo = req.PictureFrameInfo;
placedDeco.CustomizationInfo = req.CustomizationInfo ? convertCustomizationInfo(req.CustomizationInfo) : undefined;
placedDeco.AnimPoseItem = req.AnimPoseItem;
await personalRooms.save();
};

View File

@ -382,6 +382,29 @@ export const updateStats = async (accountOwnerId: string, payload: IStatsUpdate)
);
break;
case "Halloween16":
case "AmalgamEventScoreMax":
case "Halloween19ScoreMax":
case "FlotillaEventScore":
case "FlotillaSpaceBadgesTier1":
case "FlotillaSpaceBadgesTier2":
case "FlotillaSpaceBadgesTier3":
case "FlotillaGroundBadgesTier1":
case "FlotillaGroundBadgesTier2":
case "FlotillaGroundBadgesTier3":
case "MechSurvivalScoreMax":
playerStats[category] ??= 0;
if (data > playerStats[category]) playerStats[category] = data as number;
await submitLeaderboardScore(
"events",
category,
accountOwnerId,
payload.displayName,
data as number,
payload.guildId
);
break;
default:
if (!ignoredCategories.includes(category)) {
unknownCategories[action] ??= [];

View File

@ -8,6 +8,7 @@ import syndicateMissions from "@/static/fixed_responses/worldState/syndicateMiss
import darvoDeals from "@/static/fixed_responses/worldState/darvoDeals.json";
import invasionNodes from "@/static/fixed_responses/worldState/invasionNodes.json";
import invasionRewards from "@/static/fixed_responses/worldState/invasionRewards.json";
import pvpChallenges from "@/static/fixed_responses/worldState/pvpChallenges.json";
import { buildConfig } from "@/src/services/buildConfigService";
import { unixTimesInMs } from "@/src/constants/timeConstants";
import { config } from "@/src/services/configService";
@ -17,10 +18,12 @@ import {
ICalendarDay,
ICalendarEvent,
ICalendarSeason,
IGoal,
IInvasion,
ILiteSortie,
IPrimeVaultTrader,
IPrimeVaultTraderOffer,
IPVPChallengeInstance,
ISeasonChallenge,
ISortie,
ISortieMission,
@ -1401,6 +1404,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
DailyDeals: [],
EndlessXpChoices: [],
KnownCalendarSeasons: [],
PVPChallengeInstances: [],
...staticWorldState,
SyndicateMissions: [...staticWorldState.SyndicateMissions],
InGameMarket: {
@ -1535,7 +1539,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
Personal: true,
Bounty: true,
ClampNodeScores: true,
Node: "EventNode28", // Incompatible with Wolf Hunt (2025)
Node: "EventNode28", // Incompatible with Wolf Hunt (2025), Orphix Venom, Warframe Anniversary
MissionKeyName: "/Lotus/Types/Keys/GalleonRobberyAlertB",
Desc: "/Lotus/Language/Events/GalleonRobberyEventMissionTitle",
Icon: "/Lotus/Interface/Icons/Player/GalleonRobberiesEvent.png",
@ -1801,7 +1805,10 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
worldState.Goals.push({
_id: {
$oid: ((dogDaysStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "c57487c3768936df"
$oid:
((dogDaysStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") +
"c57487c3768936d" +
year.toString(16)
},
Activation: { $date: { $numberLong: activationTimeStamp } },
Expiry: { $date: { $numberLong: expiryTimeStamp } },
@ -1813,14 +1820,14 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
Personal: true,
Bounty: true,
ClampNodeScores: true,
Node: "EventNode25", // Incompatible with Hallowed Flame, Hallowed Nightmares
Node: "EventNode25", // Incompatible with Hallowed Flame, Hallowed Nightmares, Warframe Anniversary
ConcurrentMissionKeyNames: [
"/Lotus/Types/Keys/TacAlertKeyWaterFightB",
"/Lotus/Types/Keys/TacAlertKeyWaterFightC",
"/Lotus/Types/Keys/TacAlertKeyWaterFightD"
],
ConcurrentNodeReqs: [25, 50, 100],
ConcurrentNodes: ["EventNode24", "EventNode34", "EventNode35"], // Incompatible with Hallowed Flame, Hallowed Nightmares
ConcurrentNodes: ["EventNode24", "EventNode34", "EventNode35"], // Incompatible with Hallowed Flame, Hallowed Nightmares, Warframe Anniversary
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyWaterFightA",
Faction: "FC_CORPUS",
Desc: "/Lotus/Language/Alerts/TacAlertWaterFight",
@ -1928,6 +1935,226 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
}
}
if (config.worldState?.anniversary != undefined) {
// Incompatible with: Use Tag from Warframe Anniversary for old Events, Wolf Hunt (2025), Galleon Of Ghouls, Hallowed Flame, Hallowed Nightmares, Dog Days, Proxy Rebellion, Long Shadow
const goalsByWeek: Partial<IGoal>[][] = [
[
{
Node: "EventNode28",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2019E",
Tag: "Anniversary2019TacAlert",
Reward: {
items: ["/Lotus/StoreItems/Upgrades/Skins/Excalibur/ExcaliburDexSkin"]
}
},
{
Node: "EventNode26",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2020F",
Tag: "Anniversary2020TacAlert",
Reward: {
items: ["/Lotus/StoreItems/Types/Items/ShipDecos/ExcaliburDexBobbleHead"]
}
},
{
Node: "EventNode19",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2024ChallengeModeA",
Tag: "Anniversary2024TacAlertCMA",
Reward: {
items: ["/Lotus/StoreItems/Types/Items/MiscItems/WeaponUtilityUnlocker"]
}
}
],
[
{
Node: "EventNode24",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2017C",
Tag: "Anniversary2018TacAlert",
Reward: {
items: ["/Lotus/StoreItems/Weapons/Tenno/LongGuns/DexTheThird/DexTheThird"]
}
},
{
Node: "EventNode18",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2020H",
Tag: "Anniversary2020TacAlert",
Reward: {
items: ["/Lotus/StoreItems/Types/StoreItems/AvatarImages/ImageDexAnniversary"]
}
}
],
[
{
Node: "EventNode18",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2022J",
Tag: "Anniversary2022TacAlert",
Reward: {
items: ["/Lotus/StoreItems/Upgrades/Skins/Rhino/RhinoDexSkin"]
}
},
{
Node: "EventNode38",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2025D",
Tag: "Anniversary2020TacAlert",
Reward: {
items: ["/Lotus/StoreItems/Types/Items/ShipDecos/RhinoDexBobbleHead"]
}
},
{
Node: "EventNode27",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2025ChallengeModeA",
Tag: "Anniversary2024TacAlertCMA",
Reward: {
items: ["/Lotus/StoreItems/Types/Items/MiscItems/OrokinCatalyst"]
}
}
],
[
{
Node: "EventNode2",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2020G",
Tag: "Anniversary2020TacAlert",
Reward: {
items: ["/Lotus/StoreItems/Upgrades/Skins/Liset/DexLisetSkin"]
}
},
{
Node: "EventNode17",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2017B",
Tag: "Anniversary2018TacAlert",
Reward: {
items: ["/Lotus/StoreItems/Weapons/Tenno/Melee/Swords/DexTheSecond/DexTheSecond"]
}
}
],
[
{
Node: "EventNode18",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2017A",
Tag: "Anniversary2018TacAlert",
Reward: {
items: ["/Lotus/StoreItems/Weapons/Tenno/Pistols/DexFuris/DexFuris"]
}
},
{
Node: "EventNode26",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2023K",
Tag: "Anniversary2025TacAlert",
Reward: {
items: ["/Lotus/StoreItems/Types/StoreItems/AvatarImages/AvatarImageCommunityClemComic"]
}
},
{
Node: "EventNode12",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2025ChallengeModeB",
Tag: "Anniversary2025TacAlertCMB",
Reward: {
items: ["/Lotus/StoreItems/Types/Items/MiscItems/WeaponPrimaryArcaneUnlocker"]
}
}
],
[
{
Node: "EventNode17",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2025A",
Tag: "Anniversary2025TacAlert",
Reward: {
items: [
"/Lotus/StoreItems/Weapons/Tenno/Melee/Swords/KatanaAndWakizashi/Dex2023Nikana/Dex2023Nikana"
]
}
},
{
Node: "EventNode27",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2018D",
Tag: "Anniversary2018TacAlert",
Reward: {
items: ["/Lotus/StoreItems/Upgrades/Skins/Scarves/DexScarf"]
}
}
],
[
{
Node: "EventNode38",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2025C",
Tag: "Anniversary2018TacAlert",
Reward: {
items: ["/Lotus/StoreItems/Upgrades/Skins/Wisp/DexWispSkin"]
}
},
{
Node: "EventNode12",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2024L",
Tag: "Anniversary2024TacAlert",
Reward: {
items: ["/Lotus/Types/StoreItems/Packages/OperatorDrifterDexBundle"]
}
},
{
Node: "EventNode26",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2024ChallengeModeB",
Tag: "Anniversary2024TacAlertCMB",
Reward: {
items: ["/Lotus/StoreItems/Types/Recipes/Components/UmbraFormaBlueprint"]
}
}
],
[
{
Node: "EventNode37",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2021I",
Tag: "Anniversary2021TacAlert",
Reward: {
items: [
"/Lotus/StoreItems/Upgrades/Skins/Armor/Dex2020Armor/Dex2020ArmorAArmor",
"/Lotus/StoreItems/Upgrades/Skins/Armor/Dex2020Armor/Dex2020ArmorCArmor",
"/Lotus/StoreItems/Upgrades/Skins/Armor/Dex2020Armor/Dex2020ArmorLArmor",
"/Lotus/StoreItems/Types/Game/CatbrowPet/CatbrowGeneticSignature"
],
countedItems: [
{
ItemType: "/Lotus/Types/Game/CatbrowPet/CatbrowGeneticSignature",
ItemCount: 10
}
]
}
},
{
Node: "EventNode9",
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyAnniversary2025B",
Tag: "Anniversary2025TacAlert",
Reward: {
items: ["/Lotus/StoreItems/Types/StoreItems/SuitCustomizations/ColourPickerAnniversaryEleven"]
}
}
]
];
goalsByWeek[config.worldState.anniversary].forEach((goal, i) => {
worldState.Goals.push({
_id: {
$oid:
"67c6d8e725b23feb" +
config.worldState?.anniversary!.toString(16).padStart(4, "0") +
i.toString(16).padStart(4, "0")
},
Activation: { $date: { $numberLong: "1745593200000" } },
Expiry: { $date: { $numberLong: "2000000000000" } },
Count: 0,
Goal: 1,
Success: 0,
Personal: true,
ClampNodeScores: true,
Node: goal.Node,
MissionKeyName: goal.MissionKeyName,
Desc: goal.Tag!.endsWith("CMB")
? "/Lotus/Language/Events/Anniversary2024ChallengeMode"
: "/Lotus/Language/G1Quests/Anniversary2017MissionTitle",
Icon: "/Lotus/Interface/Icons/Player/GlyphLotus12Anniversary.png",
Tag: goal.Tag!,
Reward: goal.Reward
});
});
}
if (config.worldState?.wolfHunt) {
worldState.Goals.push({
_id: {
@ -1958,7 +2185,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
"/Lotus/Types/Keys/WolfTacAlertReduxD"
],
ConcurrentNodeReqs: [1, 2, 3],
ConcurrentNodes: ["EventNode28", "EventNode39", "EventNode40"], // Incompatible with Galleon Of Ghouls
ConcurrentNodes: ["EventNode28", "EventNode39", "EventNode40"], // Incompatible with Galleon Of Ghouls, Orphix Venom, Warframe Anniversary
MissionKeyName: "/Lotus/Types/Keys/WolfTacAlertReduxA",
Faction: "FC_GRINEER",
Desc: "/Lotus/Language/Alerts/WolfAlert",
@ -1989,6 +2216,18 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
});
}
const tagsForOlderGoals: string[] = [
"Anniversary2018TacAlert",
"Anniversary2019TacAlert",
"Anniversary2020TacAlert",
"Anniversary2021TacAlert",
"Anniversary2022TacAlert",
"Anniversary2024TacAlert",
"Anniversary2024TacAlertCMA",
"Anniversary2025TacAlert",
"Anniversary2025TacAlertCMB"
];
if (config.worldState?.hallowedFlame) {
worldState.Goals.push(
{
@ -2013,7 +2252,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
Faction: "FC_INFESTATION",
Desc: "/Lotus/Language/Events/TacAlertHalloweenLantern",
Icon: "/Lotus/Interface/Icons/JackOLanternColour.png",
Tag: "Halloween19",
Tag: config.unfaithfulBugFixes?.useAnniversaryTagForOldGoals ? tagsForOlderGoals[0] : "Halloween19",
InterimRewards: [
{ items: ["/Lotus/StoreItems/Types/Items/MiscItems/OrokinCatalyst"] },
{ items: ["/Lotus/StoreItems/Types/Items/MiscItems/Forma"] }
@ -2039,7 +2278,9 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
Desc: "/Lotus/Language/Events/TacAlertHalloweenLanternEndless",
Icon: "/Lotus/Interface/Icons/JackOLanternColour.png",
Tag: "Halloween19Endless",
PrereqGoalTags: ["Halloween19"],
PrereqGoalTags: [
config.unfaithfulBugFixes?.useAnniversaryTagForOldGoals ? tagsForOlderGoals[0] : "Halloween19"
],
Reward: {
items: [
"/Lotus/StoreItems/Upgrades/Skins/Effects/BatsEphemera",
@ -2094,7 +2335,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
const year = config.worldState.hallowedNightmaresRewardsOverride ?? 0;
worldState.Goals.push({
_id: { $oid: "5bc9e8f7972d7d184c8398c9" },
_id: { $oid: "5bc98f00000000000000000" + year.toString(16) },
Activation: { $date: { $numberLong: "1539972000000" } },
Expiry: { $date: { $numberLong: "2000000000000" } },
Count: 0,
@ -2103,23 +2344,23 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
Success: 0,
Personal: true,
Bounty: true,
Tag: "Halloween",
Tag: config.unfaithfulBugFixes?.useAnniversaryTagForOldGoals ? tagsForOlderGoals[0] : "Halloween",
Faction: "FC_INFESTATION",
Desc: "/Lotus/Language/G1Quests/TacAlertHalloweenTitle",
ToolTip: "/Lotus/Language/G1Quests/TacAlertHalloweenToolTip",
Icon: "/Lotus/Interface/Icons/JackOLanternColour.png",
ClampNodeScores: true,
Node: "EventNode2",
Node: "EventNode2", // Incompatible with Warframe Anniversary
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyHalloween",
ConcurrentMissionKeyNames: ["/Lotus/Types/Keys/TacAlertKeyHalloweenBonus"],
ConcurrentNodeReqs: [1],
ConcurrentNodes: ["EventNode24"], // Incompatible with Hallowed Flame, Dog Days
ConcurrentNodes: ["EventNode24"], // Incompatible with Hallowed Flame, Dog Days, Warframe Anniversary
InterimRewards: [rewards[year][0]],
Reward: rewards[year][1]
});
if (year != 2) {
worldState.Goals.push({
_id: { $oid: "5bca18b1e12d9e14a0b6ad27" },
_id: { $oid: "5bc98f01000000000000000" + year.toString(16) },
Activation: { $date: { $numberLong: "1539972000000" } },
Expiry: { $date: { $numberLong: "2000000000000" } },
Count: 0,
@ -2129,7 +2370,9 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
Bounty: true,
Best: true,
Tag: "Halloween",
PrereqGoalTags: ["Halloween"],
PrereqGoalTags: [
config.unfaithfulBugFixes?.useAnniversaryTagForOldGoals ? tagsForOlderGoals[0] : "Halloween"
],
Faction: "FC_INFESTATION",
Desc: "Hallowed Nightmares - Time Attack",
ToolTip: "/Lotus/Language/G1Quests/TacAlertHalloweenToolTip",
@ -2192,7 +2435,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
const year = config.worldState.proxyRebellionRewardsOverride ?? 0;
worldState.Goals.push({
_id: { $oid: "5b5743ac972d7d3ed0517b0d" },
_id: { $oid: "5b5b5da0000000000000000" + year.toString(16) },
Activation: { $date: { $numberLong: "1532714400000" } },
Expiry: { $date: { $numberLong: "2000000000000" } },
Count: 0,
@ -2203,19 +2446,19 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
Personal: true,
Bounty: true,
ClampNodeScores: true,
Node: "EventNode18",
Node: "EventNode18", // Incompatible with Warframe Anniversary
ConcurrentMissionKeyNames: [
"/Lotus/Types/Keys/TacAlertKeyProxyRebellionTwo",
"/Lotus/Types/Keys/TacAlertKeyProxyRebellionThree",
"/Lotus/Types/Keys/TacAlertKeyProxyRebellionFour"
],
ConcurrentNodeReqs: [1, 2, 3],
ConcurrentNodes: ["EventNode7", "EventNode4", "EventNode17"],
ConcurrentNodes: ["EventNode7", "EventNode4", "EventNode17"], // Incompatible with Orphix venom, Warframe Anniversary
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyProxyRebellionOne",
Faction: "FC_CORPUS",
Desc: "/Lotus/Language/Alerts/TacAlertProxyRebellion",
Icon: "/Lotus/Materials/Emblems/BountyBadge_e.png",
Tag: "ProxyRebellion",
Tag: config.unfaithfulBugFixes?.useAnniversaryTagForOldGoals ? tagsForOlderGoals[1] : "ProxyRebellion",
InterimRewards: rewards[year].slice(0, 2),
Reward: rewards[year][2],
BonusReward: rewards[year][3]
@ -2234,12 +2477,12 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
Success: 0,
Personal: true,
Bounty: true,
Tag: "NightwatchTacAlert",
Tag: config.unfaithfulBugFixes?.useAnniversaryTagForOldGoals ? tagsForOlderGoals[2] : "NightwatchTacAlert",
Faction: "FC_GRINEER",
Desc: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertTitle",
Icon: "/Lotus/Materials/Emblems/BountyBadge_e.png",
ClampNodeScores: true,
Node: "EventNode9",
Node: "EventNode9", // Incompatible with Warframe Anniversary
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyProjectNightwatchEasy",
ConcurrentMissionKeyNames: [
"/Lotus/Types/Keys/TacAlertKeyProjectNightwatch",
@ -2265,6 +2508,126 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
BonusReward: { items: ["/Lotus/StoreItems/Upgrades/Skins/Clan/BountyHunterBadgeItem"] }
});
}
if (config.worldState?.bellyOfTheBeast) {
worldState.Goals.push({
_id: { $oid: "67a5035c2a198564d62e165e" },
Activation: { $date: { $numberLong: "1738868400000" } },
Expiry: { $date: { $numberLong: "2000000000000" } },
Count: config.worldState.bellyOfTheBeastProgressOverride ?? 0,
HealthPct: (config.worldState.bellyOfTheBeastProgressOverride ?? 0) / 100,
Goal: 0,
Personal: true,
Community: true,
ClanGoal: [72, 216, 648, 1944, 5832],
Tag: "JadeShadowsEvent",
Faction: "FC_MITW",
Desc: "/Lotus/Language/JadeShadows/JadeShadowsEventName",
ToolTip: "/Lotus/Language/JadeShadows/JadeShadowsShortEventDesc",
Icon: "/Lotus/Interface/Icons/WorldStatePanel/JadeShadowsEventBadge.png",
ScoreLocTag: "/Lotus/Language/JadeShadows/JadeShadowsEventScore",
Node: "SolNode723",
MissionKeyName: "/Lotus/Types/Keys/JadeShadowsEventMission",
ItemType: "/Lotus/Types/Gameplay/JadeShadows/Resources/AscensionEventResourceItem"
});
}
if (config.worldState?.eightClaw) {
worldState.Goals.push({
_id: { $oid: "685c15f80000000000000000" },
Activation: { $date: { $numberLong: "1750865400000" } },
Expiry: { $date: { $numberLong: "2000000000000" } },
Count: config.worldState.eightClawProgressOverride ?? 0,
HealthPct: (config.worldState.eightClawProgressOverride ?? 0) / 100,
Goal: 0,
Personal: true,
Community: true,
ClanGoal: [72, 216, 648, 1944, 5832],
Tag: "DuviriMurmurEvent",
Faction: "FC_MITW",
Desc: "/Lotus/Language/Isleweaver/DuviriMurmurEventTitle",
ToolTip: "/Lotus/Language/Isleweaver/DuviriMurmurEventDescription",
Icon: "/Lotus/Interface/Icons/WorldStatePanel/EightClawEventBadge.png",
ScoreLocTag: "/Lotus/Language/Isleweaver/DuviriMurmurEventScore",
Node: "SolNode236",
MissionKeyName: "/Lotus/Types/Keys/DuviriMITW/DuviriMITWEventKey"
});
}
if (config.worldState?.orphixVenom) {
worldState.Goals.push(
{
_id: { $oid: "5fdcccb875d5ad500dc477d0" },
Activation: { $date: { $numberLong: "1608320400000" } },
Expiry: { $date: { $numberLong: "2000000000000" } },
Count: 0,
Goal: 500,
Success: 0,
Personal: true,
Best: true,
Node: "EventNode17", // Incompatible with Proxy Rebellion
MissionKeyName: "/Lotus/Types/Keys/MechSurvivalCorpusShip",
Faction: "FC_SENTIENT",
Desc: "/Lotus/Language/Events/MechEventMissionTier1",
Icon: "/Lotus/Interface/Icons/Categories/IconMech256.png",
Tag: "MechSurvivalA",
ScoreVar: "MechSurvivalScore",
Reward: {
items: ["/Lotus/StoreItems/Upgrades/Skins/Clan/MechEventEmblemItem"]
}
},
{
_id: { $oid: "5fdcccb875d5ad500dc477d1" },
Activation: { $date: { $numberLong: "1608320400000" } },
Expiry: { $date: { $numberLong: "2000000000000" } },
Count: 0,
Goal: 1000,
Success: 0,
Personal: true,
Best: true,
Node: "EventNode28", // Incompatible with Galleon Of Ghouls, Wolf Hunt (2025)
MissionKeyName: "/Lotus/Types/Keys/MechSurvivalGrineerGalleon",
Faction: "FC_SENTIENT",
Desc: "/Lotus/Language/Events/MechEventMissionTier2",
Icon: "/Lotus/Interface/Icons/Categories/IconMech256.png",
Tag: "MechSurvivalB",
PrereqGoalTags: ["MechSurvivalA"],
ScoreVar: "MechSurvivalScore",
Reward: {
items: ["/Lotus/StoreItems/Types/Items/FusionTreasures/OroFusexJ"]
}
},
{
_id: { $oid: "5fdcccb875d5ad500dc477d2" },
Activation: { $date: { $numberLong: "1608320400000" } },
Expiry: { $date: { $numberLong: "2000000000000" } },
Count: 0,
Goal: 2000,
Success: 0,
Personal: true,
Best: true,
Node: "EventNode32",
MissionKeyName: "/Lotus/Types/Keys/MechSurvivalGasCity",
MissionKeyRotation: [
"/Lotus/Types/Keys/MechSurvivalGasCity",
"/Lotus/Types/Keys/MechSurvivalCorpusShipEndurance",
"/Lotus/Types/Keys/MechSurvivalGrineerGalleonEndurance"
],
MissionKeyRotationInterval: 3600, // 1 hour
Faction: "FC_SENTIENT",
Desc: "/Lotus/Language/Events/MechEventMissionTier3",
Icon: "/Lotus/Interface/Icons/Categories/IconMech256.png",
Tag: "MechSurvival",
PrereqGoalTags: ["MechSurvivalA", "MechSurvivalB"],
ScoreVar: "MechSurvivalScore",
ScoreMaxTag: "MechSurvivalScoreMax",
Reward: {
items: [
"/Lotus/StoreItems/Types/Items/MiscItems/FormaAura",
"/Lotus/StoreItems/Upgrades/Skins/Necramech/MechWeapon/MechEventMausolonSkin"
]
}
}
);
}
// Nightwave Challenges
const nightwaveSyndicateTag = getNightwaveSyndicateTag(buildLabel);
@ -2586,6 +2949,23 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
pushSyndicateMissions(worldState, sdy, rng.randomInt(0, 100_000), "ba6f84724fa48061", "SteelMeridianSyndicate");
}
{
const conclaveDayStart = EPOCH + day * unixTimesInMs.day + 5 * unixTimesInMs.hour + 30 * unixTimesInMs.minute;
const conclaveDayEnd = conclaveDayStart + unixTimesInMs.day;
const conclaveWeekStart = weekStart + 40 * unixTimesInMs.minute - 2 * unixTimesInMs.day;
const conclaveWeekEnd = conclaveWeekStart + unixTimesInMs.week;
pushConclaveWeakly(worldState.PVPChallengeInstances, week);
pushConclaveDailys(worldState.PVPChallengeInstances, day);
if (isBeforeNextExpectedWorldStateRefresh(timeMs, conclaveDayEnd)) {
pushConclaveDailys(worldState.PVPChallengeInstances, day + 1);
}
if (isBeforeNextExpectedWorldStateRefresh(timeMs, conclaveWeekEnd)) {
pushConclaveWeakly(worldState.PVPChallengeInstances, week + 1);
}
}
// Archon Hunt cycling every week
worldState.LiteSorties.push(getLiteSortie(week));
if (isBeforeNextExpectedWorldStateRefresh(timeMs, weekEnd)) {
@ -2971,3 +3351,136 @@ const updateDailyDeal = async (): Promise<void> => {
export const updateWorldStateCollections = async (): Promise<void> => {
await Promise.all([updateFissures(), updateDailyDeal()]);
};
const pushConclaveDaily = (
activeChallenges: IPVPChallengeInstance[],
PVPMode: string,
pool: {
key: string;
ScriptParamValue: number;
PVPModeAllowed: string[];
SyndicateXP: number;
DuringSingleMatch?: boolean;
}[],
day: number,
id: number
): void => {
const conclaveDayStart = EPOCH + day * unixTimesInMs.day + 5 * unixTimesInMs.hour + 30 * unixTimesInMs.minute;
const conclaveDayEnd = conclaveDayStart + unixTimesInMs.day;
const challengeId = day * 8 + id;
const rng = new SRng(new SRng(challengeId).randomInt(0, 100_000));
let challenge: {
key: string;
ScriptParamValue: number;
PVPModeAllowed?: string[];
SyndicateXP?: number;
DuringSingleMatch?: boolean;
};
do {
challenge = rng.randomElement(pool)!;
} while (
activeChallenges.some(x => x.challengeTypeRefID == challenge.key) &&
activeChallenges.some(x => x.PVPMode == PVPMode)
);
activeChallenges.push({
_id: {
$oid: "689ec5d985b55902" + challengeId.toString().padStart(8, "0")
},
challengeTypeRefID: challenge.key,
startDate: { $date: { $numberLong: conclaveDayStart.toString() } },
endDate: { $date: { $numberLong: conclaveDayEnd.toString() } },
params: [{ n: "ScriptParamValue", v: challenge.ScriptParamValue }],
isGenerated: true,
PVPMode,
subChallenges: [],
Category: "PVPChallengeTypeCategory_DAILY"
});
};
const pushConclaveDailys = (activeChallenges: IPVPChallengeInstance[], day: number): void => {
const modes = [
"PVPMODE_SPEEDBALL",
"PVPMODE_CAPTURETHEFLAG",
"PVPMODE_DEATHMATCH",
"PVPMODE_TEAMDEATHMATCH"
] as const;
const challengesMap: Record<
string,
{
key: string;
ScriptParamValue: number;
PVPModeAllowed: string[];
SyndicateXP: number;
DuringSingleMatch?: boolean;
}[]
> = {};
for (const mode of modes) {
challengesMap[mode] = Object.entries(pvpChallenges)
.filter(([_, challenge]) => challenge.PVPModeAllowed.includes(mode))
.map(([key, challenge]) => ({ key, ...challenge }));
}
modes.forEach((mode, index) => {
pushConclaveDaily(activeChallenges, mode, challengesMap[mode], day, index * 2);
pushConclaveDaily(activeChallenges, mode, challengesMap[mode], day, index * 2 + 1);
});
};
const pushConclaveWeakly = (activeChallenges: IPVPChallengeInstance[], week: number): void => {
const weekStart = EPOCH + week * unixTimesInMs.week;
const conclaveWeekStart = weekStart + 40 * unixTimesInMs.minute - 2 * unixTimesInMs.day;
const conclaveWeekEnd = conclaveWeekStart + unixTimesInMs.week;
const conclaveIdStart = ((conclaveWeekStart / 1000) & 0xffffffff).toString(16).padStart(8, "0").padEnd(23, "0");
activeChallenges.push(
{
_id: { $oid: conclaveIdStart + "1" },
challengeTypeRefID: "/Lotus/PVPChallengeTypes/PVPTimedChallengeGameModeWins",
startDate: { $date: { $numberLong: conclaveWeekStart.toString() } },
endDate: { $date: { $numberLong: conclaveWeekEnd.toString() } },
params: [{ n: "ScriptParamValue", v: 6 }],
isGenerated: true,
PVPMode: "PVPMODE_ALL",
subChallenges: [],
Category: "PVPChallengeTypeCategory_WEEKLY"
},
{
_id: { $oid: conclaveIdStart + "2" },
challengeTypeRefID: "/Lotus/PVPChallengeTypes/PVPTimedChallengeGameModeComplete",
startDate: { $date: { $numberLong: conclaveWeekStart.toString() } },
endDate: { $date: { $numberLong: conclaveWeekEnd.toString() } },
params: [{ n: "ScriptParamValue", v: 20 }],
isGenerated: true,
PVPMode: "PVPMODE_ALL",
subChallenges: [],
Category: "PVPChallengeTypeCategory_WEEKLY"
},
{
_id: { $oid: conclaveIdStart + "3" },
challengeTypeRefID: "/Lotus/PVPChallengeTypes/PVPTimedChallengeOtherChallengeCompleteANY",
startDate: { $date: { $numberLong: conclaveWeekStart.toString() } },
endDate: { $date: { $numberLong: conclaveWeekEnd.toString() } },
params: [{ n: "ScriptParamValue", v: 10 }],
isGenerated: true,
PVPMode: "PVPMODE_ALL",
subChallenges: [],
Category: "PVPChallengeTypeCategory_WEEKLY"
},
{
_id: { $oid: conclaveIdStart + "4" },
challengeTypeRefID: "/Lotus/PVPChallengeTypes/PVPTimedChallengeWeeklyStandardSet",
startDate: { $date: { $numberLong: conclaveWeekStart.toString() } },
endDate: { $date: { $numberLong: conclaveWeekEnd.toString() } },
params: [{ n: "ScriptParamValue", v: 0 }],
isGenerated: true,
PVPMode: "PVPMODE_NONE",
subChallenges: [
{ $oid: conclaveIdStart + "1" },
{ $oid: conclaveIdStart + "2" },
{ $oid: conclaveIdStart + "3" }
],
Category: "PVPChallengeTypeCategory_WEEKLY_ROOT"
}
);
};

View File

@ -73,8 +73,9 @@ interface IWsMsgToClient {
auth_fail?: {
isRegister: boolean;
};
logged_out?: boolean;
nonce_updated?: boolean;
update_inventory?: boolean;
logged_out?: boolean;
}
const wsOnConnect = (ws: ws, req: http.IncomingMessage): void => {

View File

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

View File

@ -109,7 +109,7 @@ export interface IInventoryDatabase
QualifyingInvasions: IInvasionProgressDatabase[];
LastInventorySync?: Types.ObjectId;
EndlessXP?: IEndlessXpProgressDatabase[];
PersonalGoalProgress?: IPersonalGoalProgressDatabase[];
PersonalGoalProgress?: IGoalProgressDatabase[];
}
export interface IQuestKeyDatabase {
@ -318,7 +318,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
HWIDProtectEnabled?: boolean;
KubrowPetPrints: IKubrowPetPrintClient[];
AlignmentReplay?: IAlignment;
PersonalGoalProgress?: IPersonalGoalProgressClient[];
PersonalGoalProgress?: IGoalProgressClient[];
ThemeStyle: string;
ThemeBackground: string;
ThemeSounds: string;
@ -730,7 +730,7 @@ export enum UpgradeType {
export interface ILoreFragmentScan {
Progress: number;
Region?: string;
Region: string;
ItemType: string;
}
@ -895,8 +895,8 @@ export interface IPeriodicMissionCompletionResponse extends Omit<IPeriodicMissio
date: IMongoDate;
}
export interface IPersonalGoalProgressClient {
Best: number;
export interface IGoalProgressClient {
Best?: number;
Count: number;
Tag: string;
_id: IOid;
@ -904,7 +904,7 @@ export interface IPersonalGoalProgressClient {
//ReceivedClanReward1?: boolean;
}
export interface IPersonalGoalProgressDatabase extends Omit<IPersonalGoalProgressClient, "_id"> {
export interface IGoalProgressDatabase extends Omit<IGoalProgressClient, "_id"> {
goalId: Types.ObjectId;
}

View File

@ -6,7 +6,7 @@ export interface ILeaderboardEntryDatabase {
displayName: string;
score: number;
guildId?: Types.ObjectId;
expiry: Date;
expiry?: Date;
guildTier?: number;
}

View File

@ -1,6 +1,6 @@
import { IColor, IShipAttachments, IShipCustomization } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { Document, Model, Types } from "mongoose";
import { ILoadoutClient } from "@/src/types/saveLoadoutTypes";
import { ILoadoutClient, ILoadoutConfigClient, ILoadoutConfigDatabase } from "@/src/types/saveLoadoutTypes";
import { IMongoDate, IOid } from "@/src/types/commonTypes";
export interface IGetShipResponse {
@ -17,7 +17,7 @@ export interface IOrbiterClient {
Features: string[];
ShipId: IOid;
ShipInterior: IShipCustomization;
Rooms: IRoom[];
Rooms: IRoomClient[];
VignetteFish?: string[];
FavouriteLoadoutId?: IOid;
Wallpaper?: string;
@ -28,7 +28,7 @@ export interface IOrbiterClient {
export interface IOrbiterDatabase {
Features: string[];
Rooms: IRoom[];
Rooms: IRoomDatabase[];
ShipInterior?: IShipCustomization;
VignetteFish?: string[];
FavouriteLoadoutId?: Types.ObjectId;
@ -53,12 +53,18 @@ export interface IPersonalRoomsDatabase {
TailorShop: ITailorShopDatabase;
}
export interface IRoom {
export interface IRoomDatabase {
Name: string;
MaxCapacity: number;
PlacedDecos?: IPlacedDecosDatabase[];
}
export interface IRoomClient {
Name: string;
MaxCapacity: number;
PlacedDecos?: IPlacedDecosClient[];
}
export interface IPlantClient {
PlantType: string;
EndTime: IMongoDate;
@ -89,15 +95,15 @@ export interface IGardeningDatabase {
export interface IApartmentClient {
Gardening: IGardeningClient;
Rooms: IRoom[];
FavouriteLoadouts: IFavouriteLoadout[];
Rooms: IRoomClient[];
FavouriteLoadouts?: IFavouriteLoadout[];
VideoWallBackdrop?: string;
Soundscape?: string;
}
export interface IApartmentDatabase {
Gardening: IGardeningDatabase;
Rooms: IRoom[];
Rooms: IRoomDatabase[];
FavouriteLoadouts: IFavouriteLoadoutDatabase[];
VideoWallBackdrop?: string;
Soundscape?: string;
@ -110,11 +116,14 @@ export interface IPlacedDecosDatabase {
Scale?: number;
Sockets?: number;
PictureFrameInfo?: IPictureFrameInfo;
CustomizationInfo?: ICustomizationInfoDatabase;
AnimPoseItem?: string;
_id: Types.ObjectId;
}
export interface IPlacedDecosClient extends Omit<IPlacedDecosDatabase, "_id"> {
export interface IPlacedDecosClient extends Omit<IPlacedDecosDatabase, "_id" | "CustomizationInfo"> {
id: IOid;
CustomizationInfo?: ICustomizationInfoClient;
}
export interface ISetShipCustomizationsRequest {
@ -166,11 +175,13 @@ export interface IResetShipDecorationsResponse {
}
export interface ISetPlacedDecoInfoRequest {
DecoType: string;
DecoType?: string;
DecoId: string;
Room: string;
PictureFrameInfo: IPictureFrameInfo;
PictureFrameInfo: IPictureFrameInfo; // IsPicture
CustomizationInfo?: ICustomizationInfoClient; // !IsPicture
BootLocation?: TBootLocation;
AnimPoseItem?: string; // !IsPicture
ComponentId?: string;
GuildId?: string;
}
@ -191,6 +202,21 @@ export interface IPictureFrameInfo {
TextOrientation: number;
}
export interface ICustomizationInfoClient {
Anim?: string;
AnimPose?: number;
LoadOutPreset?: ILoadoutConfigClient;
VehiclePreset?: ILoadoutConfigClient;
EquippedWeapon?: "SUIT_SLOT" | "LONG_GUN_SLOT" | "PISTOL_SLOT";
AvatarType?: string;
LoadOutType?: string; // "LOT_NORMAL"
}
export interface ICustomizationInfoDatabase extends Omit<ICustomizationInfoClient, "LoadOutPreset" | "VehiclePreset"> {
LoadOutPreset?: ILoadoutConfigDatabase;
VehiclePreset?: ILoadoutConfigDatabase;
}
export interface IFavouriteLoadout {
Tag: string;
LoadoutId: IOid;
@ -206,11 +232,12 @@ export interface ITailorShopDatabase {
Colors?: IColor;
CustomJson?: string;
LevelDecosVisible?: boolean;
Rooms: IRoom[];
Rooms: IRoomDatabase[];
}
export interface ITailorShop extends Omit<ITailorShopDatabase, "FavouriteLoadouts"> {
FavouriteLoadouts: IFavouriteLoadout[];
export interface ITailorShop extends Omit<ITailorShopDatabase, "Rooms" | "FavouriteLoadouts"> {
Rooms: IRoomClient[];
FavouriteLoadouts?: IFavouriteLoadout[];
}
export type RoomsType = { Name: string; MaxCapacity: number; PlacedDecos: Types.DocumentArray<IPlacedDecosDatabase> };

View File

@ -117,6 +117,7 @@ export type IMissionInventoryUpdateRequest = {
DropTable: string;
DROP_MOD?: number[];
DROP_BLUEPRINT?: number[];
DROP_MISC_ITEM?: number[];
}[];
DeathMarks?: string[];
Nemesis?: number;
@ -205,6 +206,7 @@ export interface IRewardInfo {
Q?: boolean; // likely indicates that the bonus objective for this stage was completed
CheckpointCounter?: number; // starts at 1, is incremented with each job stage upload, and does not reset when starting a new job
challengeMissionId?: string;
GoalProgressAmount?: number;
}
export type IMissionStatus = "GS_SUCCESS" | "GS_FAILURE" | "GS_DUMPED" | "GS_QUIT" | "GS_INTERRUPTED";

View File

@ -32,6 +32,19 @@ export interface IStatsClient {
OlliesCrashCourseScore?: number;
DojoObstacleScore?: number;
// event scores
Halloween16?: number;
AmalgamEventScoreMax?: number;
Halloween19ScoreMax?: number;
FlotillaEventScore?: number;
FlotillaSpaceBadgesTier1?: number;
FlotillaSpaceBadgesTier2?: number;
FlotillaSpaceBadgesTier3?: number;
FlotillaGroundBadgesTier1?: number;
FlotillaGroundBadgesTier2?: number;
FlotillaGroundBadgesTier3?: number;
MechSurvivalScoreMax?: number;
// not in schema
PVP?: {
suitDeaths?: number;

View File

@ -39,32 +39,44 @@ export interface IGoal {
_id: IOid;
Activation: IMongoDate;
Expiry: IMongoDate;
Count?: number;
HealthPct?: number;
Icon: string;
Desc: string;
ToolTip?: string;
Faction?: string;
Goal?: number;
InterimGoals?: number[];
BonusGoal?: number;
HealthPct?: number;
ClanGoal?: number[];
Success?: number;
Personal?: boolean;
Best?: boolean;
Community?: boolean;
Best?: boolean; // Use Best instead of Count to check for reward
Bounty?: boolean; // Tactical Alert
Faction?: string;
ClampNodeScores?: boolean;
Desc: string;
ToolTip?: string;
Transmission?: string;
InstructionalItem?: string;
Icon: string;
ItemType?: string;
Tag: string;
PrereqGoalTags?: string[];
Node?: string;
VictimNode?: string;
ConcurrentMissionKeyNames?: string[];
ConcurrentNodeReqs?: number[];
ConcurrentNodes?: string[];
RegionIdx?: number;
Regions?: number[];
MissionKeyName?: string;
Reward?: IMissionReward;
InterimRewards?: IMissionReward[];
BonusReward?: IMissionReward;
@ -76,7 +88,12 @@ export interface IGoal {
JobPreviousVersion?: IOid;
ScoreVar?: string;
ScoreMaxTag?: string;
ScoreMaxTag?: string; // Field in leaderboard
ScoreLocTag?: string;
MissionKeyRotation?: string[];
MissionKeyRotationInterval?: number;
NightLevel?: string;
}

View File

@ -0,0 +1,290 @@
{
"/Lotus/PVPChallengeTypes/PVPTimedChallengeFlagCaptureEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_CAPTURETHEFLAG"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeFlagCaptureMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_CAPTURETHEFLAG"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeFlagReturnEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_CAPTURETHEFLAG"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsComboEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsComboMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsHeadShotsEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsHeadShotsMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsMeleeEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsMeleeMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsMeleeHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 3000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsMultiMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPaybackEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPayback_MEDIUM": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPowerEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPowerMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPowerHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 3000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPrimaryEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPrimaryMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPrimaryHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 3000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsSecondaryEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsSecondaryMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsSecondaryHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 3000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsStreak_MEDIUM": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsStreakDominationEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsStreakDomination_MEDIUM": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsStreakDominationHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 3000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsStreakStoppedEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsStreakStopped_MEDIUM": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsStreakHARD": {
"ScriptParamValue": 2,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 3000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsTargetInAirEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsTargetInAirMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsTargetInAirHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 3000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsWhileSlidingEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsWhileSlidingMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsWhileSlidingHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 3000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeMatchCompleteEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_CAPTURETHEFLAG", "PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeMatchCompleteMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_CAPTURETHEFLAG", "PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballCatchesEASY": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 1000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballCatchesMEDIUM": {
"ScriptParamValue": 10,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 3000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballCatchesHARD": {
"ScriptParamValue": 6,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 6000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballChecksEASY": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 1000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballChecksMEDIUM": {
"ScriptParamValue": 10,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 3000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballChecksHARD": {
"ScriptParamValue": 6,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 6000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballGoalsEASY": {
"ScriptParamValue": 2,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 1000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballGoalsMEDIUM": {
"ScriptParamValue": 6,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 3000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballGoalsHARD": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 6000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballInterceptionsEASY": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 1000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballInterceptionsMEDIUM": {
"ScriptParamValue": 6,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 3000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballInterceptionsHARD": {
"ScriptParamValue": 6,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 6000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballPassesEASY": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 1000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballPassesMEDIUM": {
"ScriptParamValue": 6,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 3000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballPassesHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 6000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballStealsEASY": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 1000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballStealsMEDIUM": {
"ScriptParamValue": 6,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 3000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballStealsHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 6000
}
}

View File

@ -311,140 +311,6 @@
"PrimeVaultAvailabilities": [false, false, false, false, false],
"PrimeTokenAvailability": true,
"LibraryInfo": { "LastCompletedTargetType": "/Lotus/Types/Game/Library/Targets/Research7Target" },
"PVPChallengeInstances": [
{
"_id": { "$oid": "6635562d036ce37f7f98e264" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeGameModeComplete",
"startDate": { "$date": { "$numberLong": "1714771501460" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 20 }],
"isGenerated": true,
"PVPMode": "PVPMODE_ALL",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_WEEKLY"
},
{
"_id": { "$oid": "6635562d036ce37f7f98e263" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeGameModeWins",
"startDate": { "$date": { "$numberLong": "1714771501460" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 6 }],
"isGenerated": true,
"PVPMode": "PVPMODE_ALL",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_WEEKLY"
},
{
"_id": { "$oid": "6635562d036ce37f7f98e265" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeOtherChallengeCompleteANY",
"startDate": { "$date": { "$numberLong": "1714771501460" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 10 }],
"isGenerated": true,
"PVPMode": "PVPMODE_ALL",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_WEEKLY"
},
{
"_id": { "$oid": "6635562d036ce37f7f98e266" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeWeeklyStandardSet",
"startDate": { "$date": { "$numberLong": "1714771501460" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 0 }],
"isGenerated": true,
"PVPMode": "PVPMODE_NONE",
"subChallenges": [{ "$oid": "6635562d036ce37f7f98e263" }, { "$oid": "6635562d036ce37f7f98e264" }, { "$oid": "6635562d036ce37f7f98e265" }],
"Category": "PVPChallengeTypeCategory_WEEKLY_ROOT"
},
{
"_id": { "$oid": "6639ca6967c1192987d75fee" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeFlagReturnEASY",
"startDate": { "$date": { "$numberLong": "1715063401824" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 1 }],
"isGenerated": true,
"PVPMode": "PVPMODE_CAPTURETHEFLAG",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_DAILY"
},
{
"_id": { "$oid": "6639ca6967c1192987d75fed" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeMatchCompleteMEDIUM",
"startDate": { "$date": { "$numberLong": "1715063401824" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 4 }],
"isGenerated": true,
"PVPMode": "PVPMODE_CAPTURETHEFLAG",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_DAILY"
},
{
"_id": { "$oid": "6639ca6967c1192987d75ff2" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeMatchCompleteEASY",
"startDate": { "$date": { "$numberLong": "1715063401824" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 1 }],
"isGenerated": true,
"PVPMode": "PVPMODE_DEATHMATCH",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_DAILY"
},
{
"_id": { "$oid": "6639ca6967c1192987d75ff1" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPayback_MEDIUM",
"startDate": { "$date": { "$numberLong": "1715063401824" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 3 }],
"isGenerated": true,
"PVPMode": "PVPMODE_DEATHMATCH",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_DAILY"
},
{
"_id": { "$oid": "6639ca6967c1192987d75fef" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsStreakDominationEASY",
"startDate": { "$date": { "$numberLong": "1715063401824" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 1 }],
"isGenerated": true,
"PVPMode": "PVPMODE_TEAMDEATHMATCH",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_DAILY"
},
{
"_id": { "$oid": "6639ca6967c1192987d75ff0" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsWhileInAirHARD",
"startDate": { "$date": { "$numberLong": "1715063401824" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 3 }],
"isGenerated": true,
"PVPMode": "PVPMODE_TEAMDEATHMATCH",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_DAILY"
},
{
"_id": { "$oid": "6639ca6967c1192987d75ff3" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballCatchesMEDIUM",
"startDate": { "$date": { "$numberLong": "1715063401824" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 10 }],
"isGenerated": true,
"PVPMode": "PVPMODE_SPEEDBALL",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_DAILY"
},
{
"_id": { "$oid": "6639ca6967c1192987d75ff4" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballInterceptionsEASY",
"startDate": { "$date": { "$numberLong": "1715063401824" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 3 }],
"isGenerated": true,
"PVPMode": "PVPMODE_SPEEDBALL",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_DAILY"
}
],
"PersistentEnemies": [],
"PVPAlternativeModes": [],
"PVPActiveTournaments": [],

View File

@ -937,24 +937,35 @@
<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="unfaithfulBugFixes.useAnniversaryTagForOldGoals" />
<label class="form-check-label" for="unfaithfulBugFixes.useAnniversaryTagForOldGoals" data-loc="worldState_useAnniversaryTagForOldGoals"></label>
<abbr data-loc-inc="worldState_anniversary"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="worldState.wolfHunt" />
<label class="form-check-label" for="worldState.wolfHunt" data-loc="worldState_wolfHunt"></label>
<abbr data-loc-inc="worldState_galleonOfGhouls"><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>
<abbr data-loc-inc="worldState_galleonOfGhouls|worldState_orphixVenom|worldState_anniversary"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="worldState.orphixVenom" />
<label class="form-check-label" for="worldState.orphixVenom" data-loc="worldState_orphixVenom"></label>
<abbr data-loc-inc="worldState_galleonOfGhouls|worldState_wolfHunt|worldState_proxyRebellion|worldState_anniversary"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="worldState.longShadow" />
<label class="form-check-label" for="worldState.longShadow" data-loc="worldState_longShadow"></label>
<abbr data-loc-inc="worldState_anniversary"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="worldState.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>
<abbr data-loc-inc="worldState_hallowedNightmares|worldState_dogDays|worldState_anniversary"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
</div>
<div class="form-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>
<abbr data-loc-inc="worldState_hallowedFlame|worldState_dogDays|worldState_anniversary"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
<select class="form-control" id="worldState.hallowedNightmares" data-default="false">
<option value="true" data-loc="enabled"></option>
<option value="false" data-loc="disabled"></option>
@ -963,15 +974,16 @@
<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>
<option value="0" data-loc="worldState_from_year" data-loc-replace="2018"></option>
<option value="1" data-loc="worldState_from_year" data-loc-replace="2016"></option>
<option value="2" data-loc="worldState_from_year" data-loc-replace="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>
<abbr data-loc-inc="worldState_anniversary|worldState_orphixVenom"><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.proxyRebellion" data-default="false">
<option value="true" data-loc="enabled"></option>
<option value="false" data-loc="disabled"></option>
@ -980,14 +992,14 @@
<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>
<option value="0" data-loc="worldState_from_year" data-loc-replace="2019"></option>
<option value="1" data-loc="worldState_from_year" data-loc-replace="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>
<abbr data-loc-inc="worldState_wolfHunt|worldState_anniversary|worldState_orphixVenom"><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,6 +1007,21 @@
<option value="3" data-loc="worldState_we3"></option>
</select>
</div>
<div class="form-group mt-2">
<label class="form-label" for="worldState.anniversary" data-loc="worldState_anniversary"></label>
<abbr data-loc-inc="worldState_useAnniversaryTagForOldGoals|worldState_wolfHunt|worldState_galleonOfGhouls|worldState_hallowedNightmares|worldState_hallowedFlame|worldState_dogDays|worldState_proxyRebellion|worldState_longShadow|worldState_orphixVenom"><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.anniversary" data-default="null">
<option value="null" data-loc="disabled"></option>
<option value="0" data-loc="worldState_week" data-loc-replace="1"></option>
<option value="1" data-loc="worldState_week" data-loc-replace="2"></option>
<option value="2" data-loc="worldState_week" data-loc-replace="3"></option>
<option value="3" data-loc="worldState_week" data-loc-replace="4"></option>
<option value="4" data-loc="worldState_week" data-loc-replace="5"></option>
<option value="5" data-loc="worldState_week" data-loc-replace="6"></option>
<option value="6" data-loc="worldState_week" data-loc-replace="7"></option>
<option value="7" data-loc="worldState_week" data-loc-replace="8"></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">
@ -1022,7 +1049,7 @@
<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>
<abbr data-loc-inc="worldState_hallowedFlame|worldState_hallowedNightmares|worldState_anniversary"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
<select class="form-control" id="worldState.dogDaysOverride" data-default="null">
<option value="null" data-loc="normal"></option>
<option value="true" data-loc="enabled"></option>
@ -1033,13 +1060,49 @@
<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>
<option value="3" data-loc="worldState_from_year" data-loc-replace="2025"></option>
<option value="2" data-loc="worldState_from_year" data-loc-replace="2024"></option>
<option value="1" data-loc="worldState_from_year" data-loc-replace="2023"></option>
<option value="0" data-loc="worldState_pre_year" data-loc-replace="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">
<form class="form-group" onsubmit="doSaveConfigInt('worldState.bellyOfTheBeastProgressOverride'); return false;">
<label class="form-label" for="worldState.bellyOfTheBeastProgressOverride" data-loc="worldState_bellyOfTheBeastProgressOverride"></label>
<div class="input-group">
<input id="worldState.bellyOfTheBeastProgressOverride" class="form-control" type="number" min="0" max="100" data-default="0" />
<button class="btn btn-secondary" type="submit" data-loc="cheats_save"></button>
</div>
</form>
</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">
<form class="form-group" onsubmit="doSaveConfigInt('worldState.eightClawProgressOverride'); return false;">
<label class="form-label" for="worldState.eightClawProgressOverride" data-loc="worldState_eightClawProgressOverride"></label>
<div class="input-group">
<input id="worldState.eightClawProgressOverride" class="form-control" type="number" min="0" max="100" data-default="0" />
<button class="btn btn-secondary" type="submit" data-loc="cheats_save"></button>
</div>
</form>
</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="">
@ -1121,7 +1184,10 @@
</div>
</div>
<div data-route="/webui/import" data-title="Import | OpenWF WebUI">
<p data-loc="import_importNote"></p>
<p>
<span data-loc="import_importNote"></span>
<span data-loc="import_importNote2"></span>
</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

@ -81,12 +81,15 @@ function openWebSocket() {
single.loadRoute("/webui/");
}
}
if ("logged_out" in msg) {
if ("nonce_updated" in msg) {
sendAuth();
}
if ("update_inventory" in msg) {
updateInventory();
}
if ("logged_out" in msg) {
logout();
}
};
window.ws.onclose = function () {
ws_is_open = false;
@ -145,13 +148,20 @@ function doLogout() {
}
}
function renameAccount() {
const newname = window.prompt(loc("code_changeNameConfirm"));
function renameAccount(taken_name) {
const newname = window.prompt(
(taken_name ? loc("code_changeNameRetry").split("|NAME|").join(taken_name) + " " : "") +
loc("code_changeNameConfirm")
);
if (newname) {
revalidateAuthz().then(() => {
fetch("/custom/renameAccount?" + window.authz + "&newname=" + newname).then(() => {
$(".displayname").text(newname);
updateLocElements();
fetch("/custom/renameAccount?" + window.authz + "&newname=" + newname).then(res => {
if (res.status == 409) {
renameAccount(newname);
} else {
$(".displayname").text(newname);
updateLocElements();
}
});
});
}
@ -206,12 +216,12 @@ function updateLocElements() {
const incWith = elm
.getAttribute("data-loc-inc")
.split("|")
.map(key => loc(key))
.map(key => loc(key).replace(/<[^>]+>/g, ""))
.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"));
document.querySelectorAll("[data-loc-replace]").forEach(elm => {
elm.innerHTML = elm.innerHTML.replace("|VAL|", elm.getAttribute("data-loc-replace"));
});
}
@ -662,166 +672,174 @@ function updateInventory() {
"KubrowPets"
].forEach(category => {
document.getElementById(category + "-list").innerHTML = "";
data[category].forEach(item => {
const tr = document.createElement("tr");
tr.setAttribute("data-item-type", item.ItemType);
{
const td = document.createElement("td");
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
if (item.ItemName) {
const pipeIndex = item.ItemName.indexOf("|");
if (pipeIndex != -1) {
td.textContent = item.ItemName.substr(1 + pipeIndex) + " " + td.textContent;
} else {
td.textContent = item.ItemName + " (" + td.textContent + ")";
data[category]
.sort((a, b) => (b.Favorite ? 1 : 0) - (a.Favorite ? 1 : 0))
.forEach(item => {
const tr = document.createElement("tr");
tr.setAttribute("data-item-type", item.ItemType);
{
const td = document.createElement("td");
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
if (item.ItemName) {
const pipeIndex = item.ItemName.indexOf("|");
if (pipeIndex != -1) {
td.textContent = item.ItemName.substr(1 + pipeIndex) + " " + td.textContent;
} else {
td.textContent = item.ItemName + " (" + td.textContent + ")";
}
}
if (item.Details?.Name) {
td.textContent = item.Details.Name + " (" + td.textContent + ")";
}
if (item.ModularParts && item.ModularParts.length) {
td.textContent += " [";
item.ModularParts.forEach(part => {
td.textContent += " " + (itemMap[part]?.name ?? part) + ",";
});
td.textContent = td.textContent.slice(0, -1) + " ]";
}
tr.appendChild(td);
}
if (item.Details?.Name) {
td.textContent = item.Details.Name + " (" + td.textContent + ")";
}
if (item.ModularParts && item.ModularParts.length) {
td.textContent += " [";
item.ModularParts.forEach(part => {
td.textContent += " " + (itemMap[part]?.name ?? part) + ",";
});
td.textContent = td.textContent.slice(0, -1) + " ]";
}
tr.appendChild(td);
}
{
const td = document.createElement("td");
td.classList = "text-end text-nowrap";
{
const td = document.createElement("td");
td.classList = "text-end text-nowrap";
let maxXP = Math.pow(uniqueLevelCaps[item.ItemType] ?? 30, 2) * 1000;
if (
category != "Suits" &&
category != "SpaceSuits" &&
category != "Sentinels" &&
category != "Hoverboards" &&
category != "MechSuits" &&
category != "MoaPets" &&
category != "KubrowPets"
) {
maxXP /= 2;
}
let anyExaltedMissingXP = false;
if (item.XP >= maxXP && item.ItemType in itemMap && "exalted" in itemMap[item.ItemType]) {
for (const exaltedType of itemMap[item.ItemType].exalted) {
const exaltedItem = data.SpecialItems.find(x => x.ItemType == exaltedType);
if (exaltedItem) {
const exaltedCap = itemMap[exaltedType]?.type == "weapons" ? 800_000 : 1_600_000;
if (exaltedItem.XP < exaltedCap) {
anyExaltedMissingXP = true;
break;
let maxXP = Math.pow(uniqueLevelCaps[item.ItemType] ?? 30, 2) * 1000;
if (
category != "Suits" &&
category != "SpaceSuits" &&
category != "Sentinels" &&
category != "Hoverboards" &&
category != "MechSuits" &&
category != "MoaPets" &&
category != "KubrowPets"
) {
maxXP /= 2;
}
let anyExaltedMissingXP = false;
if (item.XP >= maxXP && item.ItemType in itemMap && "exalted" in itemMap[item.ItemType]) {
for (const exaltedType of itemMap[item.ItemType].exalted) {
const exaltedItem = data.SpecialItems.find(x => x.ItemType == exaltedType);
if (exaltedItem) {
const exaltedCap =
itemMap[exaltedType]?.type == "weapons" ? 800_000 : 1_600_000;
if (exaltedItem.XP < exaltedCap) {
anyExaltedMissingXP = true;
break;
}
}
}
}
}
if (item.XP < maxXP || anyExaltedMissingXP) {
const a = document.createElement("a");
a.href = "#";
a.onclick = function (event) {
event.preventDefault();
revalidateAuthz().then(() => {
const promises = [];
if (item.XP < maxXP) {
promises.push(addGearExp(category, item.ItemId.$oid, maxXP - item.XP));
}
if ("exalted" in itemMap[item.ItemType]) {
for (const exaltedType of itemMap[item.ItemType].exalted) {
const exaltedItem = data.SpecialItems.find(x => x.ItemType == exaltedType);
if (exaltedItem) {
const exaltedCap =
itemMap[exaltedType]?.type == "weapons" ? 800_000 : 1_600_000;
if (exaltedItem.XP < exaltedCap) {
promises.push(
addGearExp(
"SpecialItems",
exaltedItem.ItemId.$oid,
exaltedCap - exaltedItem.XP
)
);
if (item.XP < maxXP || anyExaltedMissingXP) {
const a = document.createElement("a");
a.href = "#";
a.onclick = function (event) {
event.preventDefault();
revalidateAuthz().then(() => {
const promises = [];
if (item.XP < maxXP) {
promises.push(addGearExp(category, item.ItemId.$oid, maxXP - item.XP));
}
if ("exalted" in itemMap[item.ItemType]) {
for (const exaltedType of itemMap[item.ItemType].exalted) {
const exaltedItem = data.SpecialItems.find(
x => x.ItemType == exaltedType
);
if (exaltedItem) {
const exaltedCap =
itemMap[exaltedType]?.type == "weapons" ? 800_000 : 1_600_000;
if (exaltedItem.XP < exaltedCap) {
promises.push(
addGearExp(
"SpecialItems",
exaltedItem.ItemId.$oid,
exaltedCap - exaltedItem.XP
)
);
}
}
}
}
}
Promise.all(promises).then(() => {
updateInventory();
Promise.all(promises).then(() => {
updateInventory();
});
});
});
};
a.title = loc("code_maxRank");
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M214.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-160 160c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 141.2V448c0 17.7 14.3 32 32 32s32-14.3 32-32V141.2L329.4 246.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z"/></svg>`;
td.appendChild(a);
}
if (
["Suits", "LongGuns", "Pistols", "Melee", "SpaceGuns", "SpaceMelee"].includes(category) ||
modularWeapons.includes(item.ItemType)
) {
const a = document.createElement("a");
a.href = "/webui/detailedView?productCategory=" + category + "&itemId=" + item.ItemId.$oid;
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M278.5 215.6L23 471c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l57-57h68c49.7 0 97.9-14.4 139-41c11.1-7.2 5.5-23-7.8-23c-5.1 0-9.2-4.1-9.2-9.2c0-4.1 2.7-7.6 6.5-8.8l81-24.3c2.5-.8 4.8-2.1 6.7-4l22.4-22.4c10.1-10.1 2.9-27.3-11.3-27.3l-32.2 0c-5.1 0-9.2-4.1-9.2-9.2c0-4.1 2.7-7.6 6.5-8.8l112-33.6c4-1.2 7.4-3.9 9.3-7.7C506.4 207.6 512 184.1 512 160c0-41-16.3-80.3-45.3-109.3l-5.5-5.5C432.3 16.3 393 0 352 0s-80.3 16.3-109.3 45.3L139 149C91 197 64 262.1 64 330v55.3L253.6 195.8c6.2-6.2 16.4-6.2 22.6 0c5.4 5.4 6.1 13.6 2.2 19.8z"/></svg>`;
td.appendChild(a);
}
if (!(item.Features & 8) && modularWeapons.includes(item.ItemType)) {
const a = document.createElement("a");
a.href = "#";
a.onclick = function (event) {
event.preventDefault();
gildEquipment(category, item.ItemId.$oid);
};
a.title = loc("code_gild");
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M316.9 18C311.6 7 300.4 0 288.1 0s-23.4 7-28.8 18L195 150.3 51.4 171.5c-12 1.8-22 10.2-25.7 21.7s-.7 24.2 7.9 32.7L137.8 329 113.2 474.7c-2 12 3 24.2 12.9 31.3s23 8 33.8 2.3l128.3-68.5 128.3 68.5c10.8 5.7 23.9 4.9 33.8-2.3s14.9-19.3 12.9-31.3L438.5 329 542.7 225.9c8.6-8.5 11.7-21.2 7.9-32.7s-13.7-19.9-25.7-21.7L381.2 150.3 316.9 18z"/></svg>`;
td.appendChild(a);
}
if (category == "KubrowPets") {
const a = document.createElement("a");
a.href = "#";
a.onclick = function (event) {
event.preventDefault();
maturePet(item.ItemId.$oid, !item.Details.IsPuppy);
};
if (item.Details.IsPuppy) {
a.title = loc("code_mature");
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M112 48a48 48 0 1 1 96 0 48 48 0 1 1 -96 0zm40 304l0 128c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-223.1L59.4 304.5c-9.1 15.1-28.8 20-43.9 10.9s-20-28.8-10.9-43.9l58.3-97c17.4-28.9 48.6-46.6 82.3-46.6l29.7 0c33.7 0 64.9 17.7 82.3 46.6l58.3 97c9.1 15.1 4.2 34.8-10.9 43.9s-34.8 4.2-43.9-10.9L232 256.9 232 480c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-128-16 0z"/></svg>`;
} else {
a.title = loc("code_unmature");
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M256 64A64 64 0 1 0 128 64a64 64 0 1 0 128 0zM152.9 169.3c-23.7-8.4-44.5-24.3-58.8-45.8L74.6 94.2C64.8 79.5 45 75.6 30.2 85.4s-18.7 29.7-8.9 44.4L40.9 159c18.1 27.1 42.8 48.4 71.1 62.4L112 480c0 17.7 14.3 32 32 32s32-14.3 32-32l0-96 32 0 0 96c0 17.7 14.3 32 32 32s32-14.3 32-32l0-258.4c29.1-14.2 54.4-36.2 72.7-64.2l18.2-27.9c9.6-14.8 5.4-34.6-9.4-44.3s-34.6-5.5-44.3 9.4L291 122.4c-21.8 33.4-58.9 53.6-98.8 53.6c-12.6 0-24.9-2-36.6-5.8c-.9-.3-1.8-.7-2.7-.9z"/></svg>`;
};
a.title = loc("code_maxRank");
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M214.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-160 160c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 141.2V448c0 17.7 14.3 32 32 32s32-14.3 32-32V141.2L329.4 246.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z"/></svg>`;
td.appendChild(a);
}
td.appendChild(a);
}
{
const a = document.createElement("a");
a.href = "#";
a.onclick = function (event) {
event.preventDefault();
const name = prompt(loc("code_renamePrompt"));
if (name !== null) {
renameGear(category, item.ItemId.$oid, name);
if (
["Suits", "LongGuns", "Pistols", "Melee", "SpaceGuns", "SpaceMelee"].includes(
category
) ||
modularWeapons.includes(item.ItemType)
) {
const a = document.createElement("a");
a.href =
"/webui/detailedView?productCategory=" + category + "&itemId=" + item.ItemId.$oid;
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M278.5 215.6L23 471c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l57-57h68c49.7 0 97.9-14.4 139-41c11.1-7.2 5.5-23-7.8-23c-5.1 0-9.2-4.1-9.2-9.2c0-4.1 2.7-7.6 6.5-8.8l81-24.3c2.5-.8 4.8-2.1 6.7-4l22.4-22.4c10.1-10.1 2.9-27.3-11.3-27.3l-32.2 0c-5.1 0-9.2-4.1-9.2-9.2c0-4.1 2.7-7.6 6.5-8.8l112-33.6c4-1.2 7.4-3.9 9.3-7.7C506.4 207.6 512 184.1 512 160c0-41-16.3-80.3-45.3-109.3l-5.5-5.5C432.3 16.3 393 0 352 0s-80.3 16.3-109.3 45.3L139 149C91 197 64 262.1 64 330v55.3L253.6 195.8c6.2-6.2 16.4-6.2 22.6 0c5.4 5.4 6.1 13.6 2.2 19.8z"/></svg>`;
td.appendChild(a);
}
if (!(item.Features & 8) && modularWeapons.includes(item.ItemType)) {
const a = document.createElement("a");
a.href = "#";
a.onclick = function (event) {
event.preventDefault();
gildEquipment(category, item.ItemId.$oid);
};
a.title = loc("code_gild");
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M316.9 18C311.6 7 300.4 0 288.1 0s-23.4 7-28.8 18L195 150.3 51.4 171.5c-12 1.8-22 10.2-25.7 21.7s-.7 24.2 7.9 32.7L137.8 329 113.2 474.7c-2 12 3 24.2 12.9 31.3s23 8 33.8 2.3l128.3-68.5 128.3 68.5c10.8 5.7 23.9 4.9 33.8-2.3s14.9-19.3 12.9-31.3L438.5 329 542.7 225.9c8.6-8.5 11.7-21.2 7.9-32.7s-13.7-19.9-25.7-21.7L381.2 150.3 316.9 18z"/></svg>`;
td.appendChild(a);
}
if (category == "KubrowPets") {
const a = document.createElement("a");
a.href = "#";
a.onclick = function (event) {
event.preventDefault();
maturePet(item.ItemId.$oid, !item.Details.IsPuppy);
};
if (item.Details.IsPuppy) {
a.title = loc("code_mature");
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M112 48a48 48 0 1 1 96 0 48 48 0 1 1 -96 0zm40 304l0 128c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-223.1L59.4 304.5c-9.1 15.1-28.8 20-43.9 10.9s-20-28.8-10.9-43.9l58.3-97c17.4-28.9 48.6-46.6 82.3-46.6l29.7 0c33.7 0 64.9 17.7 82.3 46.6l58.3 97c9.1 15.1 4.2 34.8-10.9 43.9s-34.8 4.2-43.9-10.9L232 256.9 232 480c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-128-16 0z"/></svg>`;
} else {
a.title = loc("code_unmature");
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M256 64A64 64 0 1 0 128 64a64 64 0 1 0 128 0zM152.9 169.3c-23.7-8.4-44.5-24.3-58.8-45.8L74.6 94.2C64.8 79.5 45 75.6 30.2 85.4s-18.7 29.7-8.9 44.4L40.9 159c18.1 27.1 42.8 48.4 71.1 62.4L112 480c0 17.7 14.3 32 32 32s32-14.3 32-32l0-96 32 0 0 96c0 17.7 14.3 32 32 32s32-14.3 32-32l0-258.4c29.1-14.2 54.4-36.2 72.7-64.2l18.2-27.9c9.6-14.8 5.4-34.6-9.4-44.3s-34.6-5.5-44.3 9.4L291 122.4c-21.8 33.4-58.9 53.6-98.8 53.6c-12.6 0-24.9-2-36.6-5.8c-.9-.3-1.8-.7-2.7-.9z"/></svg>`;
}
};
a.title = loc("code_rename");
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M0 80V229.5c0 17 6.7 33.3 18.7 45.3l176 176c25 25 65.5 25 90.5 0L418.7 317.3c25-25 25-65.5 0-90.5l-176-176c-12-12-28.3-18.7-45.3-18.7H48C21.5 32 0 53.5 0 80zm112 32a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/></svg>`;
td.appendChild(a);
td.appendChild(a);
}
{
const a = document.createElement("a");
a.href = "#";
a.onclick = function (event) {
event.preventDefault();
const name = prompt(loc("code_renamePrompt"));
if (name !== null) {
renameGear(category, item.ItemId.$oid, name);
}
};
a.title = loc("code_rename");
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M0 80V229.5c0 17 6.7 33.3 18.7 45.3l176 176c25 25 65.5 25 90.5 0L418.7 317.3c25-25 25-65.5 0-90.5l-176-176c-12-12-28.3-18.7-45.3-18.7H48C21.5 32 0 53.5 0 80zm112 32a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/></svg>`;
td.appendChild(a);
}
{
const a = document.createElement("a");
a.href = "#";
a.onclick = function (event) {
event.preventDefault();
document.getElementById(category + "-list").removeChild(tr);
disposeOfGear(category, item.ItemId.$oid);
};
a.title = loc("code_remove");
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M135.2 17.7L128 32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H320l-7.2-14.3C307.4 6.8 296.3 0 284.2 0H163.8c-12.1 0-23.2 6.8-28.6 17.7zM416 128H32L53.2 467c1.6 25.3 22.6 45 47.9 45H346.9c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>`;
td.appendChild(a);
}
tr.appendChild(td);
}
{
const a = document.createElement("a");
a.href = "#";
a.onclick = function (event) {
event.preventDefault();
document.getElementById(category + "-list").removeChild(tr);
disposeOfGear(category, item.ItemId.$oid);
};
a.title = loc("code_remove");
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M135.2 17.7L128 32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H320l-7.2-14.3C307.4 6.8 296.3 0 284.2 0H163.8c-12.1 0-23.2 6.8-28.6 17.7zM416 128H32L53.2 467c1.6 25.3 22.6 45 47.9 45H346.9c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>`;
td.appendChild(a);
}
tr.appendChild(td);
}
document.getElementById(category + "-list").appendChild(tr);
});
document.getElementById(category + "-list").appendChild(tr);
});
});
document.getElementById("EvolutionProgress-list").innerHTML = "";

View File

@ -10,6 +10,7 @@ dict = {
code_loginFail: `Anmeldung fehlgeschlagen. Bitte überprüfe deine Angaben.`,
code_regFail: `Registrierung fehlgeschlagen. Account existiert bereits?`,
code_changeNameConfirm: `In welchen Namen möchtest du deinen Account umbenennen?`,
code_changeNameRetry: `[UNTRANSLATED] |NAME| is already taken.`,
code_deleteAccountConfirm: `Bist du sicher, dass du deinen Account |DISPLAYNAME| (|EMAIL|) löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden.`,
code_archgun: `Arch-Gewehr`,
code_melee: `Nahkampf`,
@ -246,19 +247,27 @@ dict = {
worldState_baroTennoConRelay: `Baros TennoCon Relais`,
worldState_starDays: `Sternen-Tage`,
worldState_galleonOfGhouls: `Galeone der Ghule`,
worldState_anniversary: `[UNTRANSLATED] Warframe Anniversary`,
worldState_useAnniversaryTagForOldGoals: `[UNTRANSLATED] Use <code>Tag</code> from Warframe Anniversary for old Events`,
worldState_ghoulEmergence: `Ghul Ausrottung`,
worldState_plagueStar: `Plagenstern`,
worldState_dogDays: `Hitzefrei`,
worldState_dogDaysRewards: `[UNTRANSLATED] Dog Days Rewards`,
worldState_wolfHunt: `Wolfsjagd (2025)`,
worldState_orphixVenom: `Orphix Gift`,
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_from_year: `[UNTRANSLATED] from |YEAR|`,
worldState_pre_year: `[UNTRANSLATED] pre |YEAR|`,
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 |VAL|`,
worldState_pre_year: `[UNTRANSLATED] pre |VAL|`,
worldState_week: `[UNTRANSLATED] Week |VAL|`,
worldState_incompatibleWith: `[UNTRANSLATED] Incompatible with:`,
enabled: `Aktiviert`,
disabled: `Deaktiviert`,
@ -303,7 +312,8 @@ dict = {
worldState_varziaFullyStocked: `Varzia hat volles Inventar`,
worldState_varziaOverride: `Varzia-Angebotsüberschreibung`,
import_importNote: `Du kannst hier eine vollständige oder teilweise Inventarantwort (Client-Darstellung) einfügen. Alle Felder, die vom Importer unterstützt werden, <b>werden in deinem Account überschrieben</b>.`,
import_importNote: `[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_submit: `Absenden`,
import_samples: `Beispiele:`,
import_samples_maxFocus: `Alle Fokus-Schulen maximiert`,

View File

@ -9,6 +9,7 @@ dict = {
code_loginFail: `Login failed. Double-check the email and password.`,
code_regFail: `Registration failed. Account already exists?`,
code_changeNameConfirm: `What would you like to change your account name to?`,
code_changeNameRetry: `|NAME| is already taken.`,
code_deleteAccountConfirm: `Are you sure you want to delete your account |DISPLAYNAME| (|EMAIL|)? This action cannot be undone.`,
code_archgun: `Archgun`,
code_melee: `Melee`,
@ -245,19 +246,27 @@ dict = {
worldState_baroTennoConRelay: `Baro's TennoCon Relay`,
worldState_starDays: `Star Days`,
worldState_galleonOfGhouls: `Galleon of Ghouls`,
worldState_anniversary: `Warframe Anniversary`,
worldState_useAnniversaryTagForOldGoals: `Use <code>Tag</code> from Warframe Anniversary for old Events`,
worldState_ghoulEmergence: `Ghoul Purge`,
worldState_plagueStar: `Plague Star`,
worldState_dogDays: `Dog Days`,
worldState_dogDaysRewards: `Dog Days Rewards`,
worldState_wolfHunt: `Wolf Hunt (2025)`,
worldState_orphixVenom: `Orphix Venom`,
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_from_year: `from |YEAR|`,
worldState_pre_year: `pre |YEAR|`,
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 |VAL|`,
worldState_pre_year: `pre |VAL|`,
worldState_week: `Week |VAL|`,
worldState_incompatibleWith: `Incompatible with:`,
enabled: `Enabled`,
disabled: `Disabled`,
@ -302,7 +311,8 @@ dict = {
worldState_varziaFullyStocked: `Varzia Fully Stocked`,
worldState_varziaOverride: `Varzia Rotation Override`,
import_importNote: `You can provide a full or partial inventory response (client respresentation) here. All fields that are supported by the importer <b>will be overwritten</b> in your account.`,
import_importNote: `You can provide a full or partial <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_submit: `Submit`,
import_samples: `Samples:`,
import_samples_maxFocus: `All Focus Schools Maxed Out`,

View File

@ -10,6 +10,7 @@ dict = {
code_loginFail: `Error al iniciar sesión. Verifica el correo electrónico y la contraseña.`,
code_regFail: `Error al registrar la cuenta. ¿Ya existe una cuenta con este correo?`,
code_changeNameConfirm: `¿Qué nombre te gustaría ponerle a tu cuenta?`,
code_changeNameRetry: `[UNTRANSLATED] |NAME| is already taken.`,
code_deleteAccountConfirm: `¿Estás seguro de que deseas eliminar tu cuenta |DISPLAYNAME| (|EMAIL|)? Esta acción es permanente.`,
code_archgun: `Archcañón`,
code_melee: `Cuerpo a cuerpo`,
@ -246,19 +247,27 @@ dict = {
worldState_baroTennoConRelay: `Repetidor de Baro de la TennoCon`,
worldState_starDays: `Días estelares`,
worldState_galleonOfGhouls: `Galeón de Gules`,
worldState_anniversary: `[UNTRANSLATED] Warframe Anniversary`,
worldState_useAnniversaryTagForOldGoals: `[UNTRANSLATED] Use <code>Tag</code> from Warframe Anniversary for old Events`,
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_orphixVenom: `Veneno de Orphix`,
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_from_year: `de |YEAR|`,
worldState_pre_year: `antes de |YEAR|`,
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 |VAL|`,
worldState_pre_year: `antes de |VAL|`,
worldState_week: `[UNTRANSLATED] Week |VAL|`,
worldState_incompatibleWith: `No compatible con:`,
enabled: `Activado`,
disabled: `Desactivado`,
@ -303,7 +312,8 @@ dict = {
worldState_varziaFullyStocked: `Varzia con stock completo`,
worldState_varziaOverride: `Cambio en rotación de Varzia`,
import_importNote: `Puedes proporcionar una respuesta de inventario completa o parcial (representación del cliente) aquí. Todos los campos compatibles con el importador <b>serán sobrescritos</b> en tu cuenta.`,
import_importNote: `[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_submit: `Enviar`,
import_samples: `Muestras:`,
import_samples_maxFocus: `Todas las escuelas de enfoque al máximo`,

View File

@ -10,6 +10,7 @@ dict = {
code_loginFail: `Connexion échouée. Vérifiez le mot de passe.`,
code_regFail: `Enregistrement impossible. Compte existant?`,
code_changeNameConfirm: `Nouveau nom du compte :`,
code_changeNameRetry: `[UNTRANSLATED] |NAME| is already taken.`,
code_deleteAccountConfirm: `Supprimer |DISPLAYNAME| (|EMAIL|) ? Cette action est irreversible.`,
code_archgun: `Archgun`,
code_melee: `Melee`,
@ -246,19 +247,27 @@ dict = {
worldState_baroTennoConRelay: `Relais Baro TennoCon`,
worldState_starDays: `Jours Stellaires`,
worldState_galleonOfGhouls: `Galion des Goules`,
worldState_anniversary: `[UNTRANSLATED] Warframe Anniversary`,
worldState_useAnniversaryTagForOldGoals: `[UNTRANSLATED] Use <code>Tag</code> from Warframe Anniversary for old Events`,
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_orphixVenom: `Venin Orphix`,
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_from_year: `[UNTRANSLATED] from |YEAR|`,
worldState_pre_year: `[UNTRANSLATED] pre |YEAR|`,
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 |VAL|`,
worldState_pre_year: `[UNTRANSLATED] pre |VAL|`,
worldState_week: `[UNTRANSLATED] Week |VAL|`,
worldState_incompatibleWith: `[UNTRANSLATED] Incompatible with:`,
enabled: `Activé`,
disabled: `Désactivé`,
@ -303,7 +312,8 @@ dict = {
worldState_varziaFullyStocked: `Stock de Varzia au max`,
worldState_varziaOverride: `Rotation de Varzia`,
import_importNote: `Import manuel. Toutes les modifcations supportées par l'inventaire <b>écraseront celles présentes dans la base de données</b>.`,
import_importNote: `[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_submit: `Soumettre`,
import_samples: `Échantillons :`,
import_samples_maxFocus: `Toutes les écoles de focus au rang max`,

View File

@ -10,6 +10,7 @@ dict = {
code_loginFail: `Не удалось войти. Проверьте адрес электронной почты и пароль.`,
code_regFail: `Не удалось зарегистрироваться. Учетная запись уже существует?`,
code_changeNameConfirm: `Какое имя вы хотите установить для своей учетной записи?`,
code_changeNameRetry: `[UNTRANSLATED] |NAME| is already taken.`,
code_deleteAccountConfirm: `Вы уверены, что хотите удалить аккаунт |DISPLAYNAME| (|EMAIL|)? Это действие нельзя отменить.`,
code_archgun: `Арч-Пушка`,
code_melee: `Ближний бой`,
@ -25,12 +26,12 @@ 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: `Успешно удалено.`,
@ -39,11 +40,11 @@ dict = {
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: `Готово. Обратите внимание, что вам нужно будет перезайти, чтобы увидеть изменения в игре.`,
@ -83,7 +84,7 @@ dict = {
inventory_pistols: `Вторичное оружие`,
inventory_melee: `Оружие ближнего боя`,
inventory_spaceSuits: `Арчвинги`,
inventory_spaceGuns: `Оружие арчвинга`,
inventory_spaceGuns: `Оружие Арчвинга`,
inventory_spaceMelee: `Оружие ближнего боя арчвинга`,
inventory_mechSuits: `Некрамехи`,
inventory_sentinels: `Стражи`,
@ -94,21 +95,21 @@ dict = {
inventory_kubrowPets: `Звери`,
inventory_evolutionProgress: `Прогресс эволюции Инкарнонов`,
inventory_Boosters: `Бустеры`,
inventory_bulkAddSuits: `Добавить отсутствующие варфреймы`,
inventory_bulkAddSuits: `Добавить отсутствующие Варфреймы`,
inventory_bulkAddWeapons: `Добавить отсутствующее оружие`,
inventory_bulkAddSpaceSuits: `Добавить отсутствующие арчвинги`,
inventory_bulkAddSpaceWeapons: `Добавить отсутствующее оружие арчвингов`,
inventory_bulkAddSentinels: `Добавить отсутствующих стражей`,
inventory_bulkAddSentinelWeapons: `Добавить отсутствующее оружие стражей`,
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_bulkRankUpSuits: `Макс. ранг всех Варфреймов`,
inventory_bulkRankUpWeapons: `Макс. ранг всего оружия`,
inventory_bulkRankUpSpaceSuits: `Макс. ранг всех Арчвингов`,
inventory_bulkRankUpSpaceWeapons: `Макс. ранг всего оружия Арчвингов`,
inventory_bulkRankUpSentinels: `Макс. ранг всех Стражей`,
inventory_bulkRankUpSentinelWeapons: `Макс. ранг всего оружия Стражей`,
inventory_bulkRankUpEvolutionProgress: `Макс. ранг всех эволюций Инкарнонов`,
inventory_maxPlexus: `Макс. ранг Плексуса`,
quests_list: `Квесты`,
quests_completeAll: `Завершить все квесты`,
@ -121,53 +122,53 @@ dict = {
currency_PrimeTokens: `Королевские Айя`,
currency_owned: `У тебя |COUNT|.`,
detailedView_archonShardsLabel: `Ячейки осколков архонта`,
detailedView_archonShardsLabel: `Ячейки осколков Архонта`,
detailedView_archonShardsDescription: `Вы можете использовать эти неограниченные ячейки для установки множества улучшений.`,
detailedView_archonShardsDescription2: `Обратите внимание: каждый осколок архонта применяется с задержкой при загрузке.`,
detailedView_archonShardsDescription2: `Обратите внимание: каждый осколок Архонта применяется с задержкой при загрузке.`,
detailedView_valenceBonusLabel: `Бонус Валентности`,
detailedView_valenceBonusDescription: `Вы можете установить или убрать бонус валентности с вашего оружия.`,
detailedView_modularPartsLabel: `Изменить Модульные Части`,
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_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_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_offensiveLabel: `Атакующее улучшение`,
invigorations_defensiveLabel: `Вспомогательное улучшение`,
invigorations_expiryLabel: `Срок действия Воодушевления (необязательно)`,
abilityOverride_label: `Переопределение способности`,
abilityOverride_onSlot: `в ячейке`,
mods_addRiven: `Добавить Мод Разлома`,
mods_addRiven: `Добавить мод Разлома`,
mods_fingerprint: `Отпечаток`,
mods_fingerprintHelp: `Нужна помощь с отпечатком?`,
mods_rivens: `Моды Разлома`,
mods_mods: `Моды`,
mods_addMax: `Добавить максимально улучшенный`,
mods_addMax: `Добавить макс. улучшенный`,
mods_addMissingUnrankedMods: `Добавить недостающие моды без ранга`,
mods_removeUnranked: `Удалить моды без ранга`,
mods_addMissingMaxRankMods: `Добавить недостающие моды максимального ранга`,
mods_addMissingMaxRankMods: `Добавить недостающие моды макс. ранга`,
cheats_administratorRequirement: `Вы должны быть администратором для использования этой функции. Чтобы стать администратором, добавьте <code>\"|DISPLAYNAME|\"</code> в <code>administratorNames</code> в config.json.`,
cheats_server: `Сервер`,
cheats_skipTutorial: `Пропустить обучение`,
@ -175,14 +176,14 @@ dict = {
cheats_unlockAllScans: `Разблокировать все сканирования`,
cheats_unlockAllMissions: `Разблокировать все миссии`,
cheats_unlockAllMissions_ok: `Успех. Пожалуйста, обратите внимание, что вам нужно будет войти в Додзё/Реле или перезайти, чтобы клиент обновил звездную карту.`,
cheats_infiniteCredits: `Бесконечные кредиты`,
cheats_infinitePlatinum: `Бесконечная платина`,
cheats_infiniteEndo: `Бесконечное эндо`,
cheats_infiniteCredits: `Бесконечные Кредиты`,
cheats_infinitePlatinum: `Бесконечная Платина`,
cheats_infiniteEndo: `Бесконечное Эндо`,
cheats_infiniteRegalAya: `Бесконечная Королевская Айя`,
cheats_infiniteHelminthMaterials: `Бесконечные Секреции Гельминта`,
cheats_infiniteHelminthMaterials: `Бесконечные секреции Гельминта`,
cheats_claimingBlueprintRefundsIngredients: `Возврат ингредиентов чертежей`,
cheats_dontSubtractPurchaseCreditCost: `Не вычитать стоимость кредитов при покупке`,
cheats_dontSubtractPurchasePlatinumCost: `Не вычитать стоимость платины при покупке`,
cheats_dontSubtractPurchaseCreditCost: `Не вычитать стоимость Кредитов при покупке`,
cheats_dontSubtractPurchasePlatinumCost: `Не вычитать стоимость Платины при покупке`,
cheats_dontSubtractPurchaseItemCost: `Не вычитать стоимость предметов при покупке`,
cheats_dontSubtractPurchaseStandingCost: `Не вычитать стоимость репутации при покупке`,
cheats_dontSubtractVoidTraces: `Не вычитать количество Отголосков Бездны`,
@ -196,10 +197,10 @@ dict = {
cheats_universalPolarityEverywhere: `Универсальная полярность везде`,
cheats_unlockDoubleCapacityPotatoesEverywhere: `Реакторы/Катализаторы орокин везде`,
cheats_unlockExilusEverywhere: `Адаптеры Эксилус везде`,
cheats_unlockArcanesEverywhere: `Адаптеры для мистификаторов везде`,
cheats_unlockArcanesEverywhere: `Адаптеры для Мистификаторов везде`,
cheats_noDailyStandingLimits: `Без ежедневных лимитов репутации`,
cheats_noDailyFocusLimit: `Без ежедневных лимитов фокуса`,
cheats_noArgonCrystalDecay: `Без распада аргоновых кристаллов`,
cheats_noDailyFocusLimit: `Без ежедневных лимитов Фокуса`,
cheats_noArgonCrystalDecay: `Без распада Аргоновых кристаллов`,
cheats_noMasteryRankUpCooldown: `Повышение ранга мастерства без кулдауна`,
cheats_noVendorPurchaseLimits: `Отсутствие лимитов на покупки у торговцев`,
cheats_noDeathMarks: `Без меток смерти`,
@ -209,28 +210,28 @@ dict = {
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_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_disableDailyTribute: `Отключить ежедневные награды`,
cheats_spoofMasteryRank: `Поддельный ранг мастерства (-1 для отключения)`,
cheats_relicRewardItemCountMultiplier: `Мультипликатор количества предметов награды реликвии`,
cheats_nightwaveStandingMultiplier: `Мультипликатор репутации Ночной волны`,
cheats_save: `Сохранить`,
cheats_account: `Аккаунт`,
cheats_unlockAllFocusSchools: `Разблокировать все школы фокуса`,
cheats_unlockAllFocusSchools: `Разблокировать все школы Фокуса`,
cheats_helminthUnlockAll: `Полностью улучшить Гельминта`,
cheats_addMissingSubsumedAbilities: `Добавить отсутствующие поглощённые способности`,
cheats_intrinsicsUnlockAll: `Полностью улучшить Модуляры`,
@ -239,26 +240,34 @@ dict = {
cheats_markAllAsRead: `Пометить все входящие как прочитанные`,
worldState: `Состояние мира`,
worldState_creditBoost: `Глобальный бустер кредитов`,
worldState_affinityBoost: `Глобальный бустер синтеза`,
worldState_resourceBoost: `Глобальный бустер ресурсов`,
worldState_creditBoost: `Глобальный бустер Кредитов`,
worldState_affinityBoost: `Глобальный бустер Синтеза`,
worldState_resourceBoost: `Глобальный бустер Ресурсов`,
worldState_tennoLiveRelay: `Реле TennoLive`,
worldState_baroTennoConRelay: `Реле Баро TennoCon`,
worldState_starDays: `Звёздные дни`,
worldState_galleonOfGhouls: `Галеон Гулей`,
worldState_anniversary: `Годовщина Warframe`,
worldState_useAnniversaryTagForOldGoals: `Использовать <code>Tag</code> из Годовщины Warframe для старых событий`,
worldState_ghoulEmergence: `Избавление от гулей`,
worldState_plagueStar: `Чумная звезда`,
worldState_dogDays: `Знойные дни`,
worldState_dogDaysRewards: `Награды Знойных дней`,
worldState_wolfHunt: `Волчья Охота (2025)`,
worldState_orphixVenom: `Яд Орфикса`,
worldState_longShadow: `Длинная Тень`,
worldState_hallowedFlame: `Священное пламя`,
worldState_hallowedNightmares: `Священные Кошмары`,
worldState_hallowedNightmaresRewards: `Награды Священных Кошмаров`,
worldState_proxyRebellion: `Восстание Роботов`,
worldState_proxyRebellionRewards: `Награды Восстания Роботов`,
worldState_from_year: `из |YEAR|`,
worldState_pre_year: `до |YEAR|`,
worldState_hallowedNightmares: `Священные кошмары`,
worldState_hallowedNightmaresRewards: `Награды Священных кошмаров`,
worldState_proxyRebellion: `Восстание роботов`,
worldState_proxyRebellionRewards: `Награды Восстания роботов`,
worldState_bellyOfTheBeast: `Чрево зверя`,
worldState_bellyOfTheBeastProgressOverride: `Прогресс Чрева зверя`,
worldState_eightClaw: `Восемь когтей`,
worldState_eightClawProgressOverride: `Прогресс Восьми когтей`,
worldState_from_year: `из |VAL|`,
worldState_pre_year: `до |VAL|`,
worldState_week: `Неделя |VAL|`,
worldState_incompatibleWith: `Несовместимо с:`,
enabled: `Включено`,
disabled: `Отключено`,
@ -299,73 +308,74 @@ dict = {
worldState_allAtOnceNormal: `Все сразу, в обычном режиме`,
worldState_allAtOnceSteelPath: `Все сразу, в режиме Стального Пути`,
worldState_theCircuitOverride: `Типы миссий в подземелье Дувири`,
worldState_darvoStockMultiplier: `Множитель Запасов Дарво`,
worldState_varziaFullyStocked: `Полный Ассортимент Варзии`,
worldState_varziaOverride: `Изменение Ротации Варзии`,
worldState_darvoStockMultiplier: `Множитель запасов Дарво`,
worldState_varziaFullyStocked: `Полный ассортимент Варзии`,
worldState_varziaOverride: `Изменение ротации Варзии`,
import_importNote: `Вы можете загрузить полный или частичный ответ инвентаря (клиентское представление) здесь. Все поддерживаемые поля <b>будут перезаписаны</b> в вашем аккаунте.`,
import_importNote: `Вы можете загрузить полный или частичный ответ <code>inventory.php</code> или <code>getShip.php</code> (клиентское представление) здесь. `,
import_importNote2: `Все поддерживаемые поля <b>будут перезаписаны</b> в вашем аккаунте.`,
import_submit: `Отправить`,
import_samples: `Пример:`,
import_samples_maxFocus: `Все школы Фокуса максимального уровня`,
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: `+5m обнаружение врагов`,
upgrade_AvatarLootRadar: `+7m обнаружение добычи`,
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: `Подбор сфер здоровья даёт +|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: `Радиация`,
damageType_Electricity: `Электрический`,
damageType_Fire: `Огненный`,
damageType_Freeze: `Холодовой`,
damageType_Impact: `Ударный`,
damageType_Magnetic: `Магнитный`,
damageType_Poison: `Токсичный`,
damageType_Radiation: `Радиационный`,
theme_dark: `Темная тема`,
theme_light: `Светлая тема`,

View File

@ -1,6 +1,6 @@
// Ukrainian translation by LoseFace
dict = {
general_inventoryUpdateNote: `Пам'ятка: Щоб побачити зміни в грі, вам потрібно повторно синхронізувати свій інвентар, наприклад, використовуючи команду /sync завантажувача, відвідавши Доджьо/Реле або перезавантаживши гру.`,
general_inventoryUpdateNote: `Пам'ятка: Щоб побачити зміни в грі, вам потрібно повторно синхронізувати своє спорядження, наприклад, використовуючи команду /sync завантажувача, відвідавши Доджьо/Реле або перезавантаживши гру.`,
general_addButton: `Добавити`,
general_setButton: `Встановити`,
general_none: `Відсутній`,
@ -10,9 +10,10 @@ dict = {
code_loginFail: `Не вдалося увійти. Перевірте адресу електронної пошти та пароль.`,
code_regFail: `Не вдалося зареєструватися. Обліковий запис вже існує?`,
code_changeNameConfirm: `Яке ім'я ви хочете встановити для свого облікового запису?`,
code_changeNameRetry: `[UNTRANSLATED] |NAME| is already taken.`,
code_deleteAccountConfirm: `Ви впевнені, що хочете видалити обліковий запис |DISPLAYNAME| (|EMAIL|)? Цю дію не можна скасувати.`,
code_archgun: `Арч-Пушка`,
code_melee: `Ближній бій`,
code_archgun: `Арк-гармата`,
code_melee: `Холодна зброя`,
code_pistol: `Пістолет`,
code_rifle: `Гвинтівка`,
code_shotgun: `Рушниця`,
@ -22,11 +23,11 @@ dict = {
code_amp: `Підсилювач`,
code_kDrive: `К-Драйв`,
code_legendaryCore: `Легендарне ядро`,
code_traumaticPeculiar: `Травмуюча Странність`,
code_traumaticPeculiar: `Особливе травмування`,
code_starter: `|MOD| (Пошкоджений)`,
code_badItem: `(Самозванець)`,
code_maxRank: `Максимальний рівень`,
code_rename: `Переіменувати`,
code_maxRank: `Макс. рівень`,
code_rename: `Перейменувати`,
code_renamePrompt: `Введіть нове ім'я:`,
code_remove: `Видалити`,
code_addItemsConfirm: `Ви впевнені, що хочете додати |COUNT| предметів на ваш обліковий запис?`,
@ -42,15 +43,15 @@ dict = {
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_gild: `Покращити`,
code_moa: `МОА`,
code_zanuka: `Гончарка`,
code_zanuka: `Гончак`,
code_stage: `Етап`,
code_complete: `Завершити`,
code_nextStage: `Наступний етап`,
@ -59,56 +60,56 @@ dict = {
code_setInactive: `Зробити пригоду неактивною`,
code_completed: `Завершено`,
code_active: `Активний`,
code_pigment: `Пігмент`,
code_mature: `Підготувати до бою`,
code_pigment: `Барвник`,
code_mature: `Виростити для бою`,
code_unmature: `Обернути старіння`,
code_succChange: `Успішно змінено.`,
code_requiredInvigorationUpgrade: `Ви повинні вибрати як атакуюче, так і допоміжне покращення.`,
login_description: `Увійдіть, використовуючи облікові дані OpenWF (ті ж, що й у грі при підключенні до цього сервера).`,
code_requiredInvigorationUpgrade: `Ви повинні вибрати як атакуюче, так і допоміжне вдосконалення.`,
login_description: `Увійдіть, використовуючи облікові дані OpenWF (ті ж, що й у грі при підключенні до цього серверу).`,
login_emailLabel: `Адреса електронної пошти`,
login_passwordLabel: `Пароль`,
login_loginButton: `Увійти`,
login_registerButton: `Зареєструватися`,
navbar_logout: `Вийти`,
navbar_renameAccount: `Переіменувати обліковий запис`,
navbar_renameAccount: `Перейменувати обліковий запис`,
navbar_deleteAccount: `Видалити обліковий запис`,
navbar_inventory: `Спорядження`,
navbar_mods: `Моди`,
navbar_mods: `Модифікатори`,
navbar_quests: `Пригоди`,
navbar_cheats: `Чити`,
navbar_import: `Імпорт`,
inventory_addItems: `Додати предмети`,
inventory_suits: `Ворфрейми`,
inventory_longGuns: `Основне озброєння`,
inventory_pistols: `Допоміжне озброєння`,
inventory_melee: `Холодне озброєння`,
inventory_longGuns: `Основна зброя`,
inventory_pistols: `Допоміжна зброя`,
inventory_melee: `Холодна зброя`,
inventory_spaceSuits: `Арквінґи`,
inventory_spaceGuns: `Озброєння арквінґів`,
inventory_spaceMelee: `Холодне озброєння арквінґів`,
inventory_spaceGuns: `Зброя Арквінґів`,
inventory_spaceMelee: `Холодна зброя Арквінґів`,
inventory_mechSuits: `Некрамехи`,
inventory_sentinels: `Вартові`,
inventory_sentinelWeapons: `Озброєння вартових`,
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: `Максимальний рівень Плексу`,
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: `Закінчити всі пригоди`,
@ -121,71 +122,71 @@ dict = {
currency_PrimeTokens: `Королівські Ая`,
currency_owned: `У тебе |COUNT|.`,
detailedView_archonShardsLabel: `Клітинки осколків архонта`,
detailedView_archonShardsDescription: `Ви можете використовувати ці необмежені клітинки для встановлення безлічі вдосконалень.`,
detailedView_archonShardsDescription2: `Зверніть увагу: кожен уламок архонта застосовується з затримкою при завантаженні.`,
detailedView_archonShardsLabel: `Комірки уламків Архонта`,
detailedView_archonShardsDescription: `Ви можете використовувати ці необмежені комірки для встановлення безлічі вдосконалень.`,
detailedView_archonShardsDescription2: `Зверніть увагу: кожен уламок Архонта застосовується з затримкою при завантаженні.`,
detailedView_valenceBonusLabel: `Ознака Валентності`,
detailedView_valenceBonusDescription: `Ви можете встановити або прибрати ознака валентності з вашої зброї.`,
detailedView_modularPartsLabel: `Змінити Модульні Частини`,
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_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_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_offensiveLabel: `Атакуюче вдосконалення`,
invigorations_defensiveLabel: `Допоміжне вдосконалення`,
invigorations_expiryLabel: `Термін дії Зміцнення (необов'язково)`,
abilityOverride_label: `Перевизначення здібностей`,
abilityOverride_onSlot: `у клітинці`,
abilityOverride_onSlot: `у комірці`,
mods_addRiven: `Добавити Модифікатор Розколу`,
mods_addRiven: `Добавити модифікатор Розколу`,
mods_fingerprint: `Відбиток`,
mods_fingerprintHelp: `Потрібна допомога з відбитком?`,
mods_rivens: `Модифікатори Розколу`,
mods_mods: `Модифікатори`,
mods_addMax: `Добавити максимально вдосконалений`,
mods_addMax: `Добавити макс. вдосконалений`,
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: `Успіх. Будь ласка, зверніть увагу, що вам потрібно буде увійти в Доджьо/Реле або перезайти, щоб клієнт оновив Зоряну мапу.`,
cheats_infiniteCredits: `Бескінечні Кредити`,
cheats_infinitePlatinum: `Бескінечна Платина`,
cheats_infiniteEndo: `Бескінечне Ендо`,
cheats_infiniteRegalAya: `Бескінечна Королівська Ая`,
cheats_infiniteHelminthMaterials: `Бескінечні Секреції Гельмінта`,
cheats_infiniteHelminthMaterials: `Бескінечні секреції Гельмінта`,
cheats_claimingBlueprintRefundsIngredients: `Повернення інгредієнтів креслеників`,
cheats_dontSubtractPurchaseCreditCost: `Не вираховувати вартість кредитів при купівлі`,
cheats_dontSubtractPurchasePlatinumCost: `Не вираховувати вартість платини при купівлі`,
cheats_dontSubtractPurchaseCreditCost: `Не вираховувати вартість Кредитів при купівлі`,
cheats_dontSubtractPurchasePlatinumCost: `Не вираховувати вартість Платини при купівлі`,
cheats_dontSubtractPurchaseItemCost: `Не вираховувати вартість предметів при купівлі`,
cheats_dontSubtractPurchaseStandingCost: `Не вираховувати вартість репутації при купівлі`,
cheats_dontSubtractVoidTraces: `Не вираховувати кількість Відголосків Безодні`,
cheats_dontSubtractVoidTraces: `Не вираховувати кількість Відлуння`,
cheats_dontSubtractConsumables: `Не вираховувати кількість витратних матеріалів`,
cheats_unlockAllShipFeatures: `Розблокувати всі функції судна`,
cheats_unlockAllShipDecorations: `Розблокувати всі прикраси судна`,
@ -196,10 +197,10 @@ dict = {
cheats_universalPolarityEverywhere: `Будь-яка полярність скрізь`,
cheats_unlockDoubleCapacityPotatoesEverywhere: `Орокінські Реактори/Каталізатори скрізь`,
cheats_unlockExilusEverywhere: `Ексилотримач скрізь`,
cheats_unlockArcanesEverywhere: `Тримач містифікаторів скрізь`,
cheats_unlockArcanesEverywhere: `Тримач Містифікаторів скрізь`,
cheats_noDailyStandingLimits: `Без щоденних лімітів репутації`,
cheats_noDailyFocusLimit: `Без щоденних лімітів фокуса`,
cheats_noArgonCrystalDecay: `Без розпаду аргонових кристалів`,
cheats_noDailyFocusLimit: `Без щоденних лімітів Фокусу`,
cheats_noArgonCrystalDecay: `Без розпаду Аргонових кристалів`,
cheats_noMasteryRankUpCooldown: `Підвищення ранга майстерності без очікування`,
cheats_noVendorPurchaseLimits: `Відсутність лімітів на купівлю у продавців`,
cheats_noDeathMarks: `Без позначок смерті`,
@ -209,16 +210,16 @@ dict = {
cheats_baroFullyStocked: `Баро повністю укомплектований`,
cheats_syndicateMissionsRepeatable: `Повторювати місії синдиката`,
cheats_unlockAllProfitTakerStages: `Розблокувати всі етапи Привласнювачки`,
cheats_instantFinishRivenChallenge: `Миттєве завершення випробування Модифікатора Розколу`,
cheats_instantResourceExtractorDrones: `Миттєво добуваючі дрони-видобувачі`,
cheats_noResourceExtractorDronesDamage: `Без шкоди по дронам-видобувачам`,
cheats_instantFinishRivenChallenge: `Миттєве завершення випробування модифікатора Розколу`,
cheats_instantResourceExtractorDrones: `Миттєво добуваючі Дрони-видобувачі`,
cheats_noResourceExtractorDronesDamage: `Без шкоди по Дронам-видобувачам`,
cheats_skipClanKeyCrafting: `Пропустити створення кланового ключа`,
cheats_noDojoRoomBuildStage: `Миттєве будівництво Кімнат Доджьо`,
cheats_noDojoDecoBuildStage: `Миттєве будівництво Декорацій Доджьо`,
cheats_fastDojoRoomDestruction: `Миттєве знищення Кімнат Доджьо`,
cheats_noDojoResearchCosts: `Безкоштовні Дослідження Доджьо`,
cheats_noDojoResearchTime: `Миттєві Дослідження Доджьо`,
cheats_fastClanAscension: `Миттєве Піднесення Клану`,
cheats_noDojoRoomBuildStage: `Миттєве будівництво кімнат Доджьо`,
cheats_noDojoDecoBuildStage: `Миттєве будівництво декорацій Доджьо`,
cheats_fastDojoRoomDestruction: `Миттєве знищення кімнат Доджьо`,
cheats_noDojoResearchCosts: `Безкоштовні дослідження Доджьо`,
cheats_noDojoResearchTime: `Миттєві дослідження Доджьо`,
cheats_fastClanAscension: `Миттєве піднесення клану`,
cheats_missionsCanGiveAllRelics: `Місії можуть давати всі реліквії`,
cheats_exceptionalRelicsAlwaysGiveBronzeReward: `Вийняткові реліквії завжди дають бронзову нагороду`,
cheats_flawlessRelicsAlwaysGiveSilverReward: `Бездоганні реліквії завжди дають срібну нагороду`,
@ -230,7 +231,7 @@ dict = {
cheats_nightwaveStandingMultiplier: `Множник репутації Нічної хвилі`,
cheats_save: `Зберегти`,
cheats_account: `Обліковий запис`,
cheats_unlockAllFocusSchools: `Розблокувати всі школи фокуса`,
cheats_unlockAllFocusSchools: `Розблокувати всі школи Фокусу`,
cheats_helminthUnlockAll: `Повністю покращити Гельмінта`,
cheats_addMissingSubsumedAbilities: `Додати відсутні поглинуті здібності`,
cheats_intrinsicsUnlockAll: `Повністю покращити Кваліфікації`,
@ -239,26 +240,34 @@ dict = {
cheats_markAllAsRead: `Помітити всі вхідні як прочитані`,
worldState: `Стан світу`,
worldState_creditBoost: `Глобальний бустер кредитів`,
worldState_affinityBoost: `Глобальний бустер синтезу`,
worldState_resourceBoost: `Глобальний бустер ресурсів`,
worldState_creditBoost: `Глобальне посилення Кредитів`,
worldState_affinityBoost: `Глобальне посилення Синтезу`,
worldState_resourceBoost: `Глобальне посилення Ресурсів`,
worldState_tennoLiveRelay: `Реле TennoLive`,
worldState_baroTennoConRelay: `Реле Баро TennoCon`,
worldState_starDays: `Зоряні дні`,
worldState_galleonOfGhouls: `Гульський Галеон`,
worldState_galleonOfGhouls: `Гульський галеон`,
worldState_anniversary: `[UNTRANSLATED] Warframe Anniversary`,
worldState_useAnniversaryTagForOldGoals: `[UNTRANSLATED] Use <code>Tag</code> from Warframe Anniversary for old Events`,
worldState_ghoulEmergence: `Зачищення від гулів`,
worldState_plagueStar: `Морова зірка`,
worldState_dogDays: `Спекотні дні`,
worldState_dogDaysRewards: `Нагороди Спекотних днів`,
worldState_wolfHunt: `Полювання на Вовка (2025)`,
worldState_orphixVenom: `Орфіксова отрута`,
worldState_longShadow: `Довга тінь`,
worldState_hallowedFlame: `Священне полум'я`,
worldState_hallowedNightmares: `Священні жахіття`,
worldState_hallowedNightmaresRewards: `Нагороди Священних Жахіть`,
worldState_hallowedNightmaresRewards: `Нагороди Священних жахіть`,
worldState_proxyRebellion: `Повстання роботів`,
worldState_proxyRebellionRewards: `Нагороди Повстання роботів`,
worldState_from_year: `з |YEAR|`,
worldState_pre_year: `до |YEAR|`,
worldState_bellyOfTheBeast: `У лігві звіра`,
worldState_bellyOfTheBeastProgressOverride: `Прогрес У лігві звіра`,
worldState_eightClaw: `Вісім кігтів`,
worldState_eightClawProgressOverride: `Прогрес Восьми кігтів`,
worldState_from_year: `з |VAL|`,
worldState_pre_year: `до |VAL|`,
worldState_week: `[UNTRANSLATED] Week |VAL|`,
worldState_incompatibleWith: `Несумісне з:`,
enabled: `Увімкнено`,
disabled: `Вимкнено`,
@ -273,9 +282,9 @@ dict = {
worldState_cold: `Холод`,
worldState_duviriOverride: `Цикл Дувірі`,
worldState_joy: `Радість`,
worldState_anger: `Гнів`,
worldState_anger: `Злість`,
worldState_envy: `Заздрість`,
worldState_sorrow: `Скорбота`,
worldState_sorrow: `Журба`,
worldState_fear: `Страх`,
worldState_nightwaveOverride: `Сезон Нічної хвилі`,
worldState_RadioLegionIntermission13Syndicate: `Вибірка Нори 9`,
@ -299,68 +308,69 @@ dict = {
worldState_allAtOnceNormal: `Всі одразу, в звичайному режимі`,
worldState_allAtOnceSteelPath: `Всі одразу, в режимі Шляху Сталі`,
worldState_theCircuitOverride: `Типи місій у підземеллі Дувірі`,
worldState_darvoStockMultiplier: `Множник Запасів Дарво`,
worldState_varziaFullyStocked: `Повний Асортимент Варзії`,
worldState_varziaOverride: `Зміна Ротації Варзії`,
worldState_darvoStockMultiplier: `Множник запасів Дарво`,
worldState_varziaFullyStocked: `Повний асортимент Варзії`,
worldState_varziaOverride: `Зміна ротації Варзії`,
import_importNote: `Ви можете завантажити повну або часткову відповідь спорядження (клієнтське представлення) тут. Всі підтримувані поля <b>будуть перезаписані</b> у вашому акаунті.`,
import_importNote: `Ви можете завантажити повну або часткову відповідь <code>inventory.php</code> або <code>getShip.php</code> (клієнтське представлення) тут.`,
import_importNote2: `Всі підтримувані поля <b>будуть перезаписані</b> у вашому акаунті.`,
import_submit: `Відправити`,
import_samples: `Приклад:`,
import_samples_maxFocus: `Всі школи Фокуса максимального рівня`,
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| Щит при вбивстві з Вибуховим Уронoм`,
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: `+5m Виявлення ворогів`,
upgrade_AvatarLootRadar: `+7m Виявлення здобичі`,
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: `Згустки здоров'я дають +|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_Fire: `Термічний`,
damageType_Freeze: `Крижаний`,
damageType_Impact: `Ударний`,
damageType_Magnetic: `Магнетичний`,

View File

@ -10,6 +10,7 @@ dict = {
code_loginFail: `登录失败。请检查邮箱和密码。`,
code_regFail: `注册失败。账号是否已存在?`,
code_changeNameConfirm: `您想将账户名称更改为?`,
code_changeNameRetry: `[UNTRANSLATED] |NAME| is already taken.`,
code_deleteAccountConfirm: `确定要删除您的账户 |DISPLAYNAME|(|EMAIL|) 吗?此操作不可撤销。`,
code_archgun: `空战`,
code_melee: `近战`,
@ -246,19 +247,27 @@ dict = {
worldState_baroTennoConRelay: `Baro的TennoCon中继站`,
worldState_starDays: `活动:星日`,
worldState_galleonOfGhouls: `战术警报:尸鬼的帆船战舰`,
worldState_anniversary: `[UNTRANSLATED] Warframe Anniversary`,
worldState_useAnniversaryTagForOldGoals: `[UNTRANSLATED] Use <code>Tag</code> from Warframe Anniversary for old Events`,
worldState_ghoulEmergence: `尸鬼净化`,
worldState_plagueStar: `瘟疫之星`,
worldState_dogDays: `三伏天`,
worldState_dogDaysRewards: `[UNTRANSLATED] Dog Days Rewards`,
worldState_wolfHunt: `恶狼狩猎 (2025)`,
worldState_orphixVenom: `奥影之毒`,
worldState_longShadow: `暗夜长影`,
worldState_hallowedFlame: `万圣之焰`,
worldState_hallowedNightmares: `万圣噩梦`,
worldState_hallowedNightmaresRewards: `[UNTRANSLATED] Hallowed Nightmares Rewards`,
worldState_proxyRebellion: `机械叛乱`,
worldState_proxyRebellionRewards: `[UNTRANSLATED] Proxy Rebellion Rewards`,
worldState_from_year: `[UNTRANSLATED] from |YEAR|`,
worldState_pre_year: `[UNTRANSLATED] pre |YEAR|`,
worldState_bellyOfTheBeast: `兽之腹`,
worldState_bellyOfTheBeastProgressOverride: `[UNTRANSLATED] Belly of the Beast Progress`,
worldState_eightClaw: `八爪`,
worldState_eightClawProgressOverride: `[UNTRANSLATED] Eight Claw Progress`,
worldState_from_year: `[UNTRANSLATED] from |VAL|`,
worldState_pre_year: `[UNTRANSLATED] pre |VAL|`,
worldState_week: `[UNTRANSLATED] Week |VAL|`,
worldState_incompatibleWith: `[UNTRANSLATED] Incompatible with:`,
enabled: `启用`,
disabled: `关闭/取消配置`,
@ -303,7 +312,8 @@ dict = {
worldState_varziaFullyStocked: `瓦奇娅开启全部库存商品`,
worldState_varziaOverride: `瓦奇娅(Prime重生)轮换状态`,
import_importNote: `您可以在此处提供完整或部分库存响应(客户端表示)。支持的所有字段<b>将被覆盖</b>到您的账户中。`,
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: `所有专精学派完全精通`,