forked from OpenWF/SpaceNinjaServer
Compare commits
53 Commits
32c95b6715
...
02f0935710
| Author | SHA1 | Date | |
|---|---|---|---|
| 02f0935710 | |||
| af4c3a93ce | |||
| 4141970530 | |||
| ca589cb7cf | |||
| d6ed22d1ff | |||
| 610a432e46 | |||
| 2ca895a5f8 | |||
| fd2286c253 | |||
| 5a582daa1a | |||
| 6a571e5e78 | |||
| 0349c4a32c | |||
| e1563bf298 | |||
| af6f422fec | |||
| f5c1b83598 | |||
| 30f380f37e | |||
| 0f7a85db59 | |||
| 43bc12713a | |||
| 6022bf97b5 | |||
| 159e151dc0 | |||
| 56954260c8 | |||
| c535044af8 | |||
| f5146be129 | |||
| d38ec06ed6 | |||
| 060f65900f | |||
| 66d3057d40 | |||
| b14a5925df | |||
| 9da47c406a | |||
| 09065bdb4e | |||
| 8f04fc5fdf | |||
| 230ee5f638 | |||
| 21db6ce265 | |||
| 1ecf53c96b | |||
| e67ef63b77 | |||
| 5772ebe746 | |||
| 0136e4d152 | |||
| 8b3ee4b4f5 | |||
| 6e8800f048 | |||
| d65a667acd | |||
| c6a3e86d2b | |||
| a8e41c95e7 | |||
| 9426359370 | |||
| e5247700df | |||
| 1c3f1e2276 | |||
| 7710e7c13f | |||
| a64c5ea3c1 | |||
| 17e1eb86dd | |||
| de9dfb3d71 | |||
| fc38f818dd | |||
| e76f08db89 | |||
| 7bcb5f21ce | |||
| 3641d63f6f | |||
| 71c4835a69 | |||
| 86a63ace41 |
@ -35,5 +35,5 @@ SpaceNinjaServer requires a `config.json`. To set it up, you can copy the [confi
|
|||||||
- `RadioLegion2Syndicate` for The Emissary
|
- `RadioLegion2Syndicate` for The Emissary
|
||||||
- `RadioLegionIntermissionSyndicate` for Intermission I
|
- `RadioLegionIntermissionSyndicate` for Intermission I
|
||||||
- `RadioLegionSyndicate` for The Wolf of Saturn Six
|
- `RadioLegionSyndicate` for The Wolf of Saturn Six
|
||||||
- `allTheFissures` can be set to `normal` or `hard` to enable all fissures either in normal or steel path, respectively.
|
- `worldState.allTheFissures` can be set to `normal` or `hard` to enable all fissures either in normal or steel path, respectively.
|
||||||
- `worldState.circuitGameModes` can be set to an array of game modes which will override the otherwise-random pattern in The Circuit. Valid element values are `Survival`, `VoidFlood`, `Excavation`, `Defense`, `Exterminate`, `Assassination`, and `Alchemy`.
|
- `worldState.circuitGameModes` can be set to an array of game modes which will override the otherwise-random pattern in The Circuit. Valid element values are `Survival`, `VoidFlood`, `Excavation`, `Defense`, `Exterminate`, `Assassination`, and `Alchemy`.
|
||||||
|
|||||||
@ -38,8 +38,14 @@
|
|||||||
"anniversary": null,
|
"anniversary": null,
|
||||||
"hallowedNightmares": false,
|
"hallowedNightmares": false,
|
||||||
"hallowedNightmaresRewardsOverride": 0,
|
"hallowedNightmaresRewardsOverride": 0,
|
||||||
|
"naberusNightsOverride": null,
|
||||||
"proxyRebellion": false,
|
"proxyRebellion": false,
|
||||||
"proxyRebellionRewardsOverride": 0,
|
"proxyRebellionRewardsOverride": 0,
|
||||||
|
"voidCorruption2025Week1": false,
|
||||||
|
"voidCorruption2025Week2": false,
|
||||||
|
"voidCorruption2025Week3": false,
|
||||||
|
"voidCorruption2025Week4": false,
|
||||||
|
"qtccAlerts": false,
|
||||||
"galleonOfGhouls": 0,
|
"galleonOfGhouls": 0,
|
||||||
"ghoulEmergenceOverride": null,
|
"ghoulEmergenceOverride": null,
|
||||||
"plagueStarOverride": null,
|
"plagueStarOverride": null,
|
||||||
|
|||||||
10
package-lock.json
generated
10
package-lock.json
generated
@ -9,6 +9,7 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"license": "GNU",
|
"license": "GNU",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"body-parser": "^2.2.0",
|
||||||
"chokidar": "^4.0.3",
|
"chokidar": "^4.0.3",
|
||||||
"crc-32": "^1.2.2",
|
"crc-32": "^1.2.2",
|
||||||
"express": "^5",
|
"express": "^5",
|
||||||
@ -17,7 +18,7 @@
|
|||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
"ncp": "^2.0.0",
|
"ncp": "^2.0.0",
|
||||||
"undici": "^7.10.0",
|
"undici": "^7.10.0",
|
||||||
"warframe-public-export-plus": "^0.5.89",
|
"warframe-public-export-plus": "^0.5.90",
|
||||||
"warframe-riven-info": "^0.1.2",
|
"warframe-riven-info": "^0.1.2",
|
||||||
"winston": "^3.17.0",
|
"winston": "^3.17.0",
|
||||||
"winston-daily-rotate-file": "^5.0.0",
|
"winston-daily-rotate-file": "^5.0.0",
|
||||||
@ -37,6 +38,7 @@
|
|||||||
"node": ">=20.18.1"
|
"node": ">=20.18.1"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
|
"@types/body-parser": "^1.19.6",
|
||||||
"@types/express": "^5",
|
"@types/express": "^5",
|
||||||
"@types/morgan": "^1.9.9",
|
"@types/morgan": "^1.9.9",
|
||||||
"@types/websocket": "^1.0.10",
|
"@types/websocket": "^1.0.10",
|
||||||
@ -5532,9 +5534,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/warframe-public-export-plus": {
|
"node_modules/warframe-public-export-plus": {
|
||||||
"version": "0.5.89",
|
"version": "0.5.90",
|
||||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.89.tgz",
|
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.90.tgz",
|
||||||
"integrity": "sha512-a6dM1MirzofSsuv3LlRQHFLSSIGKPVSN93dcXSDmA3njsWqOGjJJdWyXqcyxxYw8rEB8CNowSHst/MUmKvKlRg=="
|
"integrity": "sha512-PzYFJ+qOZawPOVx9+hGlOosGdqSJMSRL6c1z3CCXMiY5SEHUs7p9JIMjkqnvg1g7vflVWnyG6E5/2gYkQs0d7w=="
|
||||||
},
|
},
|
||||||
"node_modules/warframe-riven-info": {
|
"node_modules/warframe-riven-info": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
"license": "GNU",
|
"license": "GNU",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"body-parser": "^2.2.0",
|
||||||
"chokidar": "^4.0.3",
|
"chokidar": "^4.0.3",
|
||||||
"crc-32": "^1.2.2",
|
"crc-32": "^1.2.2",
|
||||||
"express": "^5",
|
"express": "^5",
|
||||||
@ -35,13 +36,14 @@
|
|||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
"ncp": "^2.0.0",
|
"ncp": "^2.0.0",
|
||||||
"undici": "^7.10.0",
|
"undici": "^7.10.0",
|
||||||
"warframe-public-export-plus": "^0.5.89",
|
"warframe-public-export-plus": "^0.5.90",
|
||||||
"warframe-riven-info": "^0.1.2",
|
"warframe-riven-info": "^0.1.2",
|
||||||
"winston": "^3.17.0",
|
"winston": "^3.17.0",
|
||||||
"winston-daily-rotate-file": "^5.0.0",
|
"winston-daily-rotate-file": "^5.0.0",
|
||||||
"ws": "^8.18.2"
|
"ws": "^8.18.2"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
|
"@types/body-parser": "^1.19.6",
|
||||||
"@types/express": "^5",
|
"@types/express": "^5",
|
||||||
"@types/morgan": "^1.9.9",
|
"@types/morgan": "^1.9.9",
|
||||||
"@types/websocket": "^1.0.10",
|
"@types/websocket": "^1.0.10",
|
||||||
|
|||||||
@ -31,12 +31,13 @@ export const abortDojoComponentController: RequestHandler = async (req, res) =>
|
|||||||
|
|
||||||
if (request.DecoId) {
|
if (request.DecoId) {
|
||||||
removeDojoDeco(guild, request.ComponentId, request.DecoId);
|
removeDojoDeco(guild, request.ComponentId, request.DecoId);
|
||||||
|
await guild.save();
|
||||||
|
res.json(await getDojoClient(guild, 0, request.ComponentId));
|
||||||
} else {
|
} else {
|
||||||
await removeDojoRoom(guild, request.ComponentId);
|
await removeDojoRoom(guild, request.ComponentId);
|
||||||
|
await guild.save();
|
||||||
|
res.json(await getDojoClient(guild, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
await guild.save();
|
|
||||||
res.json(await getDojoClient(guild, 0, request.ComponentId));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IAbortDojoComponentRequest {
|
interface IAbortDojoComponentRequest {
|
||||||
|
|||||||
@ -5,11 +5,23 @@ import { Guild, GuildMember } from "../../models/guildModel.ts";
|
|||||||
import { createUniqueClanName, getGuildClient, giveClanKey } from "../../services/guildService.ts";
|
import { createUniqueClanName, getGuildClient, giveClanKey } from "../../services/guildService.ts";
|
||||||
import { getInventory } from "../../services/inventoryService.ts";
|
import { getInventory } from "../../services/inventoryService.ts";
|
||||||
import type { IInventoryChanges } from "../../types/purchaseTypes.ts";
|
import type { IInventoryChanges } from "../../types/purchaseTypes.ts";
|
||||||
|
import { sendWsBroadcastTo } from "../../services/wsService.ts";
|
||||||
|
|
||||||
export const createGuildController: RequestHandler = async (req, res) => {
|
export const createGuildController: RequestHandler = async (req, res) => {
|
||||||
const account = await getAccountForRequest(req);
|
const account = await getAccountForRequest(req);
|
||||||
const payload = getJSONfromString<ICreateGuildRequest>(String(req.body));
|
const payload = getJSONfromString<ICreateGuildRequest>(String(req.body));
|
||||||
|
|
||||||
|
const inventory = await getInventory(account._id.toString(), "GuildId LevelKeys Recipes");
|
||||||
|
if (inventory.GuildId) {
|
||||||
|
const guild = await Guild.findById(inventory.GuildId);
|
||||||
|
if (guild) {
|
||||||
|
res.json({
|
||||||
|
...(await getGuildClient(guild, account))
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remove pending applications for this account
|
// Remove pending applications for this account
|
||||||
await GuildMember.deleteMany({ accountId: account._id, status: 1 });
|
await GuildMember.deleteMany({ accountId: account._id, status: 1 });
|
||||||
|
|
||||||
@ -27,7 +39,6 @@ export const createGuildController: RequestHandler = async (req, res) => {
|
|||||||
rank: 0
|
rank: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
const inventory = await getInventory(account._id.toString(), "GuildId LevelKeys Recipes");
|
|
||||||
inventory.GuildId = guild._id;
|
inventory.GuildId = guild._id;
|
||||||
const inventoryChanges: IInventoryChanges = {};
|
const inventoryChanges: IInventoryChanges = {};
|
||||||
giveClanKey(inventory, inventoryChanges);
|
giveClanKey(inventory, inventoryChanges);
|
||||||
@ -37,6 +48,7 @@ export const createGuildController: RequestHandler = async (req, res) => {
|
|||||||
...(await getGuildClient(guild, account)),
|
...(await getGuildClient(guild, account)),
|
||||||
InventoryChanges: inventoryChanges
|
InventoryChanges: inventoryChanges
|
||||||
});
|
});
|
||||||
|
sendWsBroadcastTo(account._id.toString(), { update_inventory: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
interface ICreateGuildRequest {
|
interface ICreateGuildRequest {
|
||||||
|
|||||||
27
src/controllers/api/forceRemoveItemController.ts
Normal file
27
src/controllers/api/forceRemoveItemController.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import type { RequestHandler } from "express";
|
||||||
|
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
||||||
|
import { getJSONfromString } from "../../helpers/stringHelpers.ts";
|
||||||
|
import { getInventory } from "../../services/inventoryService.ts";
|
||||||
|
import type { IInventoryChanges } from "../../types/purchaseTypes.ts";
|
||||||
|
|
||||||
|
export const forceRemoveItemController: RequestHandler = async (req, res) => {
|
||||||
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
const inventory = await getInventory(accountId, "MiscItems");
|
||||||
|
const body = getJSONfromString<IForceRemoveItemRequest>(String(req.body));
|
||||||
|
const inventoryChanges: IInventoryChanges = {};
|
||||||
|
for (const item of body.items) {
|
||||||
|
const index = inventory.MiscItems.findIndex(x => x.ItemType == item);
|
||||||
|
if (index != -1) {
|
||||||
|
inventoryChanges.MiscItems ??= [];
|
||||||
|
inventoryChanges.MiscItems.push({ ItemType: item, ItemCount: inventory.MiscItems[index].ItemCount * -1 });
|
||||||
|
|
||||||
|
inventory.MiscItems.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await inventory.save();
|
||||||
|
res.json({ InventoryChanges: inventoryChanges });
|
||||||
|
};
|
||||||
|
|
||||||
|
interface IForceRemoveItemRequest {
|
||||||
|
items: string[];
|
||||||
|
}
|
||||||
@ -19,7 +19,7 @@ export const getGuildDojoController: RequestHandler = async (req, res) => {
|
|||||||
_id: new Types.ObjectId(),
|
_id: new Types.ObjectId(),
|
||||||
pf: "/Lotus/Levels/ClanDojo/DojoHall.level",
|
pf: "/Lotus/Levels/ClanDojo/DojoHall.level",
|
||||||
ppf: "",
|
ppf: "",
|
||||||
CompletionTime: new Date(Date.now()),
|
CompletionTime: new Date(Date.now() - 1000),
|
||||||
DecoCapacity: 600
|
DecoCapacity: 600
|
||||||
});
|
});
|
||||||
await guild.save();
|
await guild.save();
|
||||||
|
|||||||
@ -11,7 +11,11 @@ export const getVoidProjectionRewardsController: RequestHandler = async (req, re
|
|||||||
|
|
||||||
if (data.ParticipantInfo.QualifiesForReward && !data.ParticipantInfo.HaveRewardResponse) {
|
if (data.ParticipantInfo.QualifiesForReward && !data.ParticipantInfo.HaveRewardResponse) {
|
||||||
const inventory = await getInventory(accountId);
|
const inventory = await getInventory(accountId);
|
||||||
await crackRelic(inventory, data.ParticipantInfo);
|
const reward = await crackRelic(inventory, data.ParticipantInfo);
|
||||||
|
if (!inventory.MissionRelicRewards || inventory.MissionRelicRewards.length >= data.CurrentWave) {
|
||||||
|
inventory.MissionRelicRewards = [];
|
||||||
|
}
|
||||||
|
inventory.MissionRelicRewards.push({ ItemType: reward.type, ItemCount: reward.itemCount });
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
import type { RequestHandler } from "express";
|
import type { Request, RequestHandler } from "express";
|
||||||
import { Inbox } from "../../models/inboxModel.ts";
|
import { Inbox } from "../../models/inboxModel.ts";
|
||||||
import {
|
import {
|
||||||
createMessage,
|
createMessage,
|
||||||
createNewEventMessages,
|
|
||||||
deleteAllMessagesRead,
|
deleteAllMessagesRead,
|
||||||
|
deleteAllMessagesReadNonCin,
|
||||||
deleteMessageRead,
|
deleteMessageRead,
|
||||||
getAllMessagesSorted,
|
getAllMessagesSorted,
|
||||||
getMessage
|
getMessage,
|
||||||
|
type IMessageCreationTemplate
|
||||||
} from "../../services/inboxService.ts";
|
} from "../../services/inboxService.ts";
|
||||||
import { getAccountForRequest, getAccountFromSuffixedName, getSuffixedName } from "../../services/loginService.ts";
|
import { getAccountForRequest, getAccountFromSuffixedName, getSuffixedName } from "../../services/loginService.ts";
|
||||||
import {
|
import {
|
||||||
@ -21,6 +22,9 @@ import { ExportFlavour } from "warframe-public-export-plus";
|
|||||||
import { handleStoreItemAcquisition } from "../../services/purchaseService.ts";
|
import { handleStoreItemAcquisition } from "../../services/purchaseService.ts";
|
||||||
import { fromStoreItem, isStoreItem } from "../../services/itemDataService.ts";
|
import { fromStoreItem, isStoreItem } from "../../services/itemDataService.ts";
|
||||||
import type { IOid } from "../../types/commonTypes.ts";
|
import type { IOid } from "../../types/commonTypes.ts";
|
||||||
|
import { unixTimesInMs } from "../../constants/timeConstants.ts";
|
||||||
|
import { config } from "../../services/configService.ts";
|
||||||
|
import { Types } from "mongoose";
|
||||||
|
|
||||||
export const inboxController: RequestHandler = async (req, res) => {
|
export const inboxController: RequestHandler = async (req, res) => {
|
||||||
const { deleteId, lastMessage: latestClientMessageId, messageId } = req.query;
|
const { deleteId, lastMessage: latestClientMessageId, messageId } = req.query;
|
||||||
@ -31,11 +35,11 @@ export const inboxController: RequestHandler = async (req, res) => {
|
|||||||
if (deleteId) {
|
if (deleteId) {
|
||||||
if (deleteId === "DeleteAllRead") {
|
if (deleteId === "DeleteAllRead") {
|
||||||
await deleteAllMessagesRead(accountId);
|
await deleteAllMessagesRead(accountId);
|
||||||
res.status(200).end();
|
} else if (deleteId === "DeleteAllReadNonCin") {
|
||||||
return;
|
await deleteAllMessagesReadNonCin(accountId);
|
||||||
|
} else {
|
||||||
|
await deleteMessageRead(parseOid(deleteId as string));
|
||||||
}
|
}
|
||||||
|
|
||||||
await deleteMessageRead(parseOid(deleteId as string));
|
|
||||||
res.status(200).end();
|
res.status(200).end();
|
||||||
} else if (messageId) {
|
} else if (messageId) {
|
||||||
const message = await getMessage(parseOid(messageId as string));
|
const message = await getMessage(parseOid(messageId as string));
|
||||||
@ -134,6 +138,119 @@ export const inboxController: RequestHandler = async (req, res) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const createNewEventMessages = async (req: Request): Promise<void> => {
|
||||||
|
const account = await getAccountForRequest(req);
|
||||||
|
const newEventMessages: IMessageCreationTemplate[] = [];
|
||||||
|
|
||||||
|
// Baro
|
||||||
|
const baroIndex = Math.trunc((Date.now() - 910800000) / (unixTimesInMs.day * 14));
|
||||||
|
const baroStart = baroIndex * (unixTimesInMs.day * 14) + 910800000;
|
||||||
|
const baroActualStart = baroStart + unixTimesInMs.day * (config.worldState?.baroAlwaysAvailable ? 0 : 12);
|
||||||
|
if (Date.now() >= baroActualStart && account.LatestEventMessageDate.getTime() < baroActualStart) {
|
||||||
|
newEventMessages.push({
|
||||||
|
sndr: "/Lotus/Language/G1Quests/VoidTraderName",
|
||||||
|
sub: "/Lotus/Language/CommunityMessages/VoidTraderAppearanceTitle",
|
||||||
|
msg: "/Lotus/Language/CommunityMessages/VoidTraderAppearanceMessage",
|
||||||
|
icon: "/Lotus/Interface/Icons/Npcs/BaroKiTeerPortrait.png",
|
||||||
|
startDate: new Date(baroActualStart),
|
||||||
|
endDate: new Date(baroStart + unixTimesInMs.day * 14),
|
||||||
|
CrossPlatform: true,
|
||||||
|
arg: [
|
||||||
|
{
|
||||||
|
Key: "NODE_NAME",
|
||||||
|
Tag: ["EarthHUB", "MercuryHUB", "SaturnHUB", "PlutoHUB"][baroIndex % 4]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
date: new Date(baroActualStart)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// BUG: Deleting the inbox message manually means it'll just be automatically re-created. This is because we don't use startDate/endDate for these config-toggled events.
|
||||||
|
const promises = [];
|
||||||
|
if (config.worldState?.creditBoost) {
|
||||||
|
promises.push(
|
||||||
|
(async (): Promise<void> => {
|
||||||
|
if (!(await Inbox.exists({ ownerId: account._id, globaUpgradeId: "5b23106f283a555109666672" }))) {
|
||||||
|
newEventMessages.push({
|
||||||
|
globaUpgradeId: new Types.ObjectId("5b23106f283a555109666672"),
|
||||||
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
|
sub: "/Lotus/Language/Items/EventDoubleCreditsName",
|
||||||
|
msg: "/Lotus/Language/Items/EventDoubleCreditsDesc",
|
||||||
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
|
startDate: new Date(),
|
||||||
|
CrossPlatform: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (config.worldState?.affinityBoost) {
|
||||||
|
promises.push(
|
||||||
|
(async (): Promise<void> => {
|
||||||
|
if (!(await Inbox.exists({ ownerId: account._id, globaUpgradeId: "5b23106f283a555109666673" }))) {
|
||||||
|
newEventMessages.push({
|
||||||
|
globaUpgradeId: new Types.ObjectId("5b23106f283a555109666673"),
|
||||||
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
|
sub: "/Lotus/Language/Items/EventDoubleAffinityName",
|
||||||
|
msg: "/Lotus/Language/Items/EventDoubleAffinityDesc",
|
||||||
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
|
startDate: new Date(),
|
||||||
|
CrossPlatform: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (config.worldState?.resourceBoost) {
|
||||||
|
promises.push(
|
||||||
|
(async (): Promise<void> => {
|
||||||
|
if (!(await Inbox.exists({ ownerId: account._id, globaUpgradeId: "5b23106f283a555109666674" }))) {
|
||||||
|
newEventMessages.push({
|
||||||
|
globaUpgradeId: new Types.ObjectId("5b23106f283a555109666674"),
|
||||||
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
|
sub: "/Lotus/Language/Items/EventDoubleResourceName",
|
||||||
|
msg: "/Lotus/Language/Items/EventDoubleResourceDesc",
|
||||||
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
|
startDate: new Date(),
|
||||||
|
CrossPlatform: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (config.worldState?.galleonOfGhouls) {
|
||||||
|
promises.push(
|
||||||
|
(async (): Promise<void> => {
|
||||||
|
if (!(await Inbox.exists({ ownerId: account._id, goalTag: "GalleonRobbery" }))) {
|
||||||
|
newEventMessages.push({
|
||||||
|
sndr: "/Lotus/Language/Bosses/BossCouncilorVayHek",
|
||||||
|
sub: "/Lotus/Language/Events/GalleonRobberyIntroMsgTitle",
|
||||||
|
msg: "/Lotus/Language/Events/GalleonRobberyIntroMsgDesc",
|
||||||
|
icon: "/Lotus/Interface/Icons/Npcs/VayHekPortrait.png",
|
||||||
|
transmission: "/Lotus/Sounds/Dialog/GalleonOfGhouls/DGhoulsWeekOneInbox0010VayHek",
|
||||||
|
att: ["/Lotus/Upgrades/Skins/Events/OgrisOldSchool"],
|
||||||
|
startDate: new Date(),
|
||||||
|
goalTag: "GalleonRobbery"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await Promise.all(promises);
|
||||||
|
|
||||||
|
if (newEventMessages.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await createMessage(account._id, newEventMessages);
|
||||||
|
|
||||||
|
const latestEventMessage = newEventMessages.reduce((prev, current) =>
|
||||||
|
prev.startDate! > current.startDate! ? prev : current
|
||||||
|
);
|
||||||
|
account.LatestEventMessageDate = new Date(latestEventMessage.startDate!);
|
||||||
|
await account.save();
|
||||||
|
};
|
||||||
|
|
||||||
// 33.6.0 has query arguments like lastMessage={"$oid":"68112baebf192e786d1502bb"} instead of lastMessage=68112baebf192e786d1502bb
|
// 33.6.0 has query arguments like lastMessage={"$oid":"68112baebf192e786d1502bb"} instead of lastMessage=68112baebf192e786d1502bb
|
||||||
const parseOid = (oid: string): string => {
|
const parseOid = (oid: string): string => {
|
||||||
if (oid[0] == "{") {
|
if (oid[0] == "{") {
|
||||||
|
|||||||
@ -177,7 +177,7 @@ export const inventoryController: RequestHandler = async (request, response) =>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanupInventory(inventory);
|
await cleanupInventory(inventory);
|
||||||
|
|
||||||
inventory.NextRefill = new Date((today + 1) * 86400000); // tomorrow at 0 UTC
|
inventory.NextRefill = new Date((today + 1) * 86400000); // tomorrow at 0 UTC
|
||||||
//await inventory.save();
|
//await inventory.save();
|
||||||
@ -335,15 +335,16 @@ export const getInventoryResponse = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (config.unlockAllSkins) {
|
if (config.unlockAllSkins) {
|
||||||
const missingWeaponSkins = new Set(Object.keys(ExportCustoms));
|
const ownedWeaponSkins = new Set<string>(inventoryResponse.WeaponSkins.map(x => x.ItemType));
|
||||||
inventoryResponse.WeaponSkins.forEach(x => missingWeaponSkins.delete(x.ItemType));
|
for (const [uniqueName, meta] of Object.entries(ExportCustoms)) {
|
||||||
for (const uniqueName of missingWeaponSkins) {
|
if (!meta.alwaysAvailable && !ownedWeaponSkins.has(uniqueName)) {
|
||||||
inventoryResponse.WeaponSkins.push({
|
inventoryResponse.WeaponSkins.push({
|
||||||
ItemId: {
|
ItemId: {
|
||||||
$oid: "ca70ca70ca70ca70" + catBreadHash(uniqueName).toString(16).padStart(8, "0")
|
$oid: "ca70ca70ca70ca70" + catBreadHash(uniqueName).toString(16).padStart(8, "0")
|
||||||
},
|
},
|
||||||
ItemType: uniqueName
|
ItemType: uniqueName
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,6 +461,9 @@ export const getInventoryResponse = async (
|
|||||||
toLegacyOid(id);
|
toLegacyOid(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (inventoryResponse.GuildId) {
|
||||||
|
toLegacyOid(inventoryResponse.GuildId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,9 @@ import type { IDatabaseAccountJson, ILoginRequest, ILoginResponse } from "../../
|
|||||||
import { logger } from "../../utils/logger.ts";
|
import { logger } from "../../utils/logger.ts";
|
||||||
import { version_compare } from "../../helpers/inventoryHelpers.ts";
|
import { version_compare } from "../../helpers/inventoryHelpers.ts";
|
||||||
import { handleNonceInvalidation } from "../../services/wsService.ts";
|
import { handleNonceInvalidation } from "../../services/wsService.ts";
|
||||||
|
import { getInventory } from "../../services/inventoryService.ts";
|
||||||
|
import { createMessage } from "../../services/inboxService.ts";
|
||||||
|
import { fromStoreItem } from "../../services/itemDataService.ts";
|
||||||
|
|
||||||
export const loginController: RequestHandler = async (request, response) => {
|
export const loginController: RequestHandler = async (request, response) => {
|
||||||
const loginRequest = JSON.parse(String(request.body)) as ILoginRequest; // parse octet stream of json data to json object
|
const loginRequest = JSON.parse(String(request.body)) as ILoginRequest; // parse octet stream of json data to json object
|
||||||
@ -76,6 +79,24 @@ export const loginController: RequestHandler = async (request, response) => {
|
|||||||
|
|
||||||
handleNonceInvalidation(account._id.toString());
|
handleNonceInvalidation(account._id.toString());
|
||||||
|
|
||||||
|
// If the client crashed during an endless fissure mission, discharge rewards to an inbox message. (https://www.reddit.com/r/Warframe/comments/5uwwjm/til_if_you_crash_during_a_fissure_you_keep_any/)
|
||||||
|
const inventory = await getInventory(account._id.toString(), "MissionRelicRewards");
|
||||||
|
if (inventory.MissionRelicRewards) {
|
||||||
|
await createMessage(account._id, [
|
||||||
|
{
|
||||||
|
sndr: "/Lotus/Language/Bosses/Ordis",
|
||||||
|
msg: "/Lotus/Language/Menu/VoidProjectionItemsMessage",
|
||||||
|
sub: "/Lotus/Language/Menu/VoidProjectionItemsSubject",
|
||||||
|
icon: "/Lotus/Interface/Icons/Npcs/Ordis.png",
|
||||||
|
countedAtt: inventory.MissionRelicRewards.map(x => ({ ...x, ItemType: fromStoreItem(x.ItemType) })),
|
||||||
|
attVisualOnly: true,
|
||||||
|
highPriority: true // TOVERIFY
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
inventory.MissionRelicRewards = undefined;
|
||||||
|
await inventory.save();
|
||||||
|
}
|
||||||
|
|
||||||
response.json(createLoginResponse(myAddress, myUrlBase, account.toJSON(), buildLabel));
|
response.json(createLoginResponse(myAddress, myUrlBase, account.toJSON(), buildLabel));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -129,14 +129,22 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
|
|||||||
res.json(deltas);
|
res.json(deltas);
|
||||||
} else if (missionReport.RewardInfo) {
|
} else if (missionReport.RewardInfo) {
|
||||||
logger.debug(`classic mission completion, sending everything`);
|
logger.debug(`classic mission completion, sending everything`);
|
||||||
const inventoryResponse = await getInventoryResponse(inventory, true, account.BuildLabel);
|
const inventoryResponse = await getInventoryResponse(
|
||||||
|
inventory,
|
||||||
|
"xpBasedLevelCapDisabled" in req.query,
|
||||||
|
account.BuildLabel
|
||||||
|
);
|
||||||
res.json({
|
res.json({
|
||||||
InventoryJson: JSON.stringify(inventoryResponse),
|
InventoryJson: JSON.stringify(inventoryResponse),
|
||||||
...deltas
|
...deltas
|
||||||
} satisfies IMissionInventoryUpdateResponse);
|
} satisfies IMissionInventoryUpdateResponse);
|
||||||
} else {
|
} else {
|
||||||
logger.debug(`no reward info, assuming this wasn't a mission completion and we should just sync inventory`);
|
logger.debug(`no reward info, assuming this wasn't a mission completion and we should just sync inventory`);
|
||||||
const inventoryResponse = await getInventoryResponse(inventory, true, account.BuildLabel);
|
const inventoryResponse = await getInventoryResponse(
|
||||||
|
inventory,
|
||||||
|
"xpBasedLevelCapDisabled" in req.query,
|
||||||
|
account.BuildLabel
|
||||||
|
);
|
||||||
res.json({
|
res.json({
|
||||||
InventoryJson: JSON.stringify(inventoryResponse)
|
InventoryJson: JSON.stringify(inventoryResponse)
|
||||||
} satisfies IMissionInventoryUpdateResponseBackToDryDock);
|
} satisfies IMissionInventoryUpdateResponseBackToDryDock);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { fromDbOid, version_compare } from "../../helpers/inventoryHelpers.ts";
|
import { fromDbOid, toMongoDate, version_compare } from "../../helpers/inventoryHelpers.ts";
|
||||||
import type { IKnifeResponse } from "../../helpers/nemesisHelpers.ts";
|
import type { IKnifeResponse } from "../../helpers/nemesisHelpers.ts";
|
||||||
import {
|
import {
|
||||||
antivirusMods,
|
antivirusMods,
|
||||||
@ -149,7 +149,10 @@ export const nemesisController: RequestHandler = async (req, res) => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inventory.Nemesis!.HenchmenKilled += antivirusGain;
|
const antivirusGainMultiplier = (
|
||||||
|
await getInventory(account._id.toString(), "nemesisAntivirusGainMultiplier")
|
||||||
|
).nemesisAntivirusGainMultiplier;
|
||||||
|
inventory.Nemesis!.HenchmenKilled += antivirusGain * (antivirusGainMultiplier ?? 1);
|
||||||
if (inventory.Nemesis!.HenchmenKilled >= 100) {
|
if (inventory.Nemesis!.HenchmenKilled >= 100) {
|
||||||
inventory.Nemesis!.HenchmenKilled = 100;
|
inventory.Nemesis!.HenchmenKilled = 100;
|
||||||
|
|
||||||
@ -307,6 +310,26 @@ export const nemesisController: RequestHandler = async (req, res) => {
|
|||||||
res.json({
|
res.json({
|
||||||
target: inventory.toJSON().Nemesis
|
target: inventory.toJSON().Nemesis
|
||||||
});
|
});
|
||||||
|
} else if ((req.query.mode as string) == "t") {
|
||||||
|
const inventory = await getInventory(account._id.toString(), "LastNemesisAllySpawnTime");
|
||||||
|
//const body = getJSONfromString<IUpdateAllySpawnTimeRequest>(String(req.body));
|
||||||
|
const now = new Date(Math.trunc(Date.now() / 1000) * 1000);
|
||||||
|
inventory.LastNemesisAllySpawnTime = now;
|
||||||
|
await inventory.save();
|
||||||
|
res.json({
|
||||||
|
NewTime: toMongoDate(now)
|
||||||
|
} satisfies IUpdateAllySpawnTimeResponse);
|
||||||
|
} else if ((req.query.mode as string) == "d") {
|
||||||
|
const inventory = await getInventory(account._id.toString(), "NemesisHistory");
|
||||||
|
const body = getJSONfromString<IRelinquishAdversariesRequest>(String(req.body));
|
||||||
|
for (const fp of body.nemesisFingerprints) {
|
||||||
|
const index = inventory.NemesisHistory!.findIndex(x => x.fp == fp);
|
||||||
|
if (index != -1) {
|
||||||
|
inventory.NemesisHistory!.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await inventory.save();
|
||||||
|
res.json(body);
|
||||||
} else if ((req.query.mode as string) == "w") {
|
} else if ((req.query.mode as string) == "w") {
|
||||||
const inventory = await getInventory(account._id.toString(), "Nemesis");
|
const inventory = await getInventory(account._id.toString(), "Nemesis");
|
||||||
//const body = getJSONfromString<INemesisWeakenRequest>(String(req.body));
|
//const body = getJSONfromString<INemesisWeakenRequest>(String(req.body));
|
||||||
@ -444,3 +467,15 @@ const consumeModCharge = (
|
|||||||
response.UpgradeNew.push(true);
|
response.UpgradeNew.push(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface IRelinquishAdversariesRequest {
|
||||||
|
nemesisFingerprints: (bigint | number)[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// interface IUpdateAllySpawnTimeRequest {
|
||||||
|
// LastSpawnTime: IMongoDate;
|
||||||
|
// }
|
||||||
|
|
||||||
|
interface IUpdateAllySpawnTimeResponse {
|
||||||
|
NewTime: IMongoDate;
|
||||||
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import {
|
|||||||
import { createMessage } from "../../services/inboxService.ts";
|
import { createMessage } from "../../services/inboxService.ts";
|
||||||
import { getInventory } from "../../services/inventoryService.ts";
|
import { getInventory } from "../../services/inventoryService.ts";
|
||||||
import { getAccountForRequest, getSuffixedName } from "../../services/loginService.ts";
|
import { getAccountForRequest, getSuffixedName } from "../../services/loginService.ts";
|
||||||
|
import { sendWsBroadcastTo } from "../../services/wsService.ts";
|
||||||
import { GuildPermission } from "../../types/guildTypes.ts";
|
import { GuildPermission } from "../../types/guildTypes.ts";
|
||||||
import type { RequestHandler } from "express";
|
import type { RequestHandler } from "express";
|
||||||
|
|
||||||
@ -85,6 +86,7 @@ export const removeFromGuildController: RequestHandler = async (req, res) => {
|
|||||||
ItemToRemove: "/Lotus/Types/Keys/DojoKey",
|
ItemToRemove: "/Lotus/Types/Keys/DojoKey",
|
||||||
RecipeToRemove: "/Lotus/Types/Keys/DojoKeyBlueprint"
|
RecipeToRemove: "/Lotus/Types/Keys/DojoKeyBlueprint"
|
||||||
});
|
});
|
||||||
|
sendWsBroadcastTo(payload.userId, { update_inventory: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IRemoveFromGuildRequest {
|
interface IRemoveFromGuildRequest {
|
||||||
|
|||||||
@ -77,6 +77,9 @@ export const sellController: RequestHandler = async (req, res) => {
|
|||||||
requiredFields.add("CrewShipSalvagedWeaponSkins");
|
requiredFields.add("CrewShipSalvagedWeaponSkins");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (payload.Items.WeaponSkins) {
|
||||||
|
requiredFields.add("WeaponSkins");
|
||||||
|
}
|
||||||
const inventory = await getInventory(accountId, Array.from(requiredFields).join(" "));
|
const inventory = await getInventory(accountId, Array.from(requiredFields).join(" "));
|
||||||
|
|
||||||
// Give currency
|
// Give currency
|
||||||
@ -302,6 +305,11 @@ export const sellController: RequestHandler = async (req, res) => {
|
|||||||
addFusionTreasures(inventory, [parseFusionTreasure(sellItem.String, sellItem.Count * -1)]);
|
addFusionTreasures(inventory, [parseFusionTreasure(sellItem.String, sellItem.Count * -1)]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (payload.Items.WeaponSkins) {
|
||||||
|
payload.Items.WeaponSkins.forEach(sellItem => {
|
||||||
|
inventory.WeaponSkins.pull({ _id: sellItem.String });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
res.json({
|
res.json({
|
||||||
@ -335,6 +343,7 @@ interface ISellRequest {
|
|||||||
CrewShipWeapons?: ISellItem[];
|
CrewShipWeapons?: ISellItem[];
|
||||||
CrewShipWeaponSkins?: ISellItem[];
|
CrewShipWeaponSkins?: ISellItem[];
|
||||||
FusionTreasures?: ISellItem[];
|
FusionTreasures?: ISellItem[];
|
||||||
|
WeaponSkins?: ISellItem[]; // SNS specific field
|
||||||
};
|
};
|
||||||
SellPrice: number;
|
SellPrice: number;
|
||||||
SellCurrency:
|
SellCurrency:
|
||||||
|
|||||||
@ -57,7 +57,7 @@ export const setGuildMotdController: RequestHandler = async (req, res) => {
|
|||||||
await guild.save();
|
await guild.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!account.BuildLabel || version_compare(account.BuildLabel, "2020.03.24.20.24") > 0) {
|
if (!account.BuildLabel || version_compare(account.BuildLabel, "2020.11.04.18.58") > 0) {
|
||||||
res.json({ IsLongMOTD, MOTD });
|
res.json({ IsLongMOTD, MOTD });
|
||||||
} else {
|
} else {
|
||||||
res.send(MOTD).end();
|
res.send(MOTD).end();
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import { Types } from "mongoose";
|
|||||||
import { ExportDojoRecipes } from "warframe-public-export-plus";
|
import { ExportDojoRecipes } from "warframe-public-export-plus";
|
||||||
import { getAccountForRequest } from "../../services/loginService.ts";
|
import { getAccountForRequest } from "../../services/loginService.ts";
|
||||||
import { getInventory } from "../../services/inventoryService.ts";
|
import { getInventory } from "../../services/inventoryService.ts";
|
||||||
|
import { fromOid } from "../../helpers/inventoryHelpers.ts";
|
||||||
|
|
||||||
interface IStartDojoRecipeRequest {
|
interface IStartDojoRecipeRequest {
|
||||||
PlacedComponent: IDojoComponentClient;
|
PlacedComponent: IDojoComponentClient;
|
||||||
@ -50,7 +51,7 @@ export const startDojoRecipeController: RequestHandler = async (req, res) => {
|
|||||||
_id: componentId,
|
_id: componentId,
|
||||||
pf: request.PlacedComponent.pf,
|
pf: request.PlacedComponent.pf,
|
||||||
ppf: request.PlacedComponent.ppf,
|
ppf: request.PlacedComponent.ppf,
|
||||||
pi: new Types.ObjectId(request.PlacedComponent.pi!.$oid),
|
pi: new Types.ObjectId(fromOid(request.PlacedComponent.pi!)),
|
||||||
op: request.PlacedComponent.op,
|
op: request.PlacedComponent.op,
|
||||||
pp: request.PlacedComponent.pp,
|
pp: request.PlacedComponent.pp,
|
||||||
DecoCapacity: room?.decoCapacity
|
DecoCapacity: room?.decoCapacity
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import type { IUpdateQuestRequest } from "../../services/questService.ts";
|
|||||||
import { updateQuestKey } from "../../services/questService.ts";
|
import { updateQuestKey } from "../../services/questService.ts";
|
||||||
import { getInventory } from "../../services/inventoryService.ts";
|
import { getInventory } from "../../services/inventoryService.ts";
|
||||||
import type { IInventoryChanges } from "../../types/purchaseTypes.ts";
|
import type { IInventoryChanges } from "../../types/purchaseTypes.ts";
|
||||||
|
import { sendWsBroadcastTo } from "../../services/wsService.ts";
|
||||||
|
|
||||||
export const updateQuestController: RequestHandler = async (req, res) => {
|
export const updateQuestController: RequestHandler = async (req, res) => {
|
||||||
const accountId = parseString(req.query.accountId);
|
const accountId = parseString(req.query.accountId);
|
||||||
@ -29,4 +30,5 @@ export const updateQuestController: RequestHandler = async (req, res) => {
|
|||||||
|
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
res.send(updateQuestResponse);
|
res.send(updateQuestResponse);
|
||||||
|
sendWsBroadcastTo(accountId, { update_inventory: true });
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
||||||
import { getInventory } from "../../services/inventoryService.ts";
|
import { getInventory } from "../../services/inventoryService.ts";
|
||||||
import type { RequestHandler } from "express";
|
import type { RequestHandler } from "express";
|
||||||
import { hasAccessToDojo, getGuildForRequestEx, hasGuildPermission } from "../../services/guildService.ts";
|
import { getGuildForRequestEx, hasGuildPermission } from "../../services/guildService.ts";
|
||||||
import { GuildPermission } from "../../types/guildTypes.ts";
|
import { GuildPermission } from "../../types/guildTypes.ts";
|
||||||
import type { ITypeCount } from "../../types/commonTypes.ts";
|
import type { ITypeCount } from "../../types/commonTypes.ts";
|
||||||
|
|
||||||
export const addVaultDecoRecipeController: RequestHandler = async (req, res) => {
|
export const addVaultDecoRecipeController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
const requests = req.body as ITypeCount[];
|
const requests = req.body as ITypeCount[];
|
||||||
const inventory = await getInventory(accountId, "LevelKeys GuildId");
|
const inventory = await getInventory(accountId, "GuildId");
|
||||||
const guild = await getGuildForRequestEx(req, inventory);
|
const guild = await getGuildForRequestEx(req, inventory);
|
||||||
if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Architect))) {
|
if (!(await hasGuildPermission(guild, accountId, GuildPermission.Architect))) {
|
||||||
res.status(400).send("-1").end();
|
res.status(400).send("-1").end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import type { RequestHandler } from "express";
|
import type { RequestHandler } from "express";
|
||||||
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
import { getAccountForRequest } from "../../services/loginService.ts";
|
||||||
import { Account, Ignore } from "../../models/loginModel.ts";
|
import { Account, Ignore } from "../../models/loginModel.ts";
|
||||||
import { Inbox } from "../../models/inboxModel.ts";
|
import { Inbox } from "../../models/inboxModel.ts";
|
||||||
import { Inventory } from "../../models/inventoryModels/inventoryModel.ts";
|
import { Inventory } from "../../models/inventoryModels/inventoryModel.ts";
|
||||||
@ -12,33 +12,44 @@ import { Leaderboard } from "../../models/leaderboardModel.ts";
|
|||||||
import { deleteGuild } from "../../services/guildService.ts";
|
import { deleteGuild } from "../../services/guildService.ts";
|
||||||
import { Friendship } from "../../models/friendModel.ts";
|
import { Friendship } from "../../models/friendModel.ts";
|
||||||
import { sendWsBroadcastTo } from "../../services/wsService.ts";
|
import { sendWsBroadcastTo } from "../../services/wsService.ts";
|
||||||
|
import { config } from "../../services/configService.ts";
|
||||||
|
import { saveConfig } from "../../services/configWriterService.ts";
|
||||||
|
|
||||||
export const deleteAccountController: RequestHandler = async (req, res) => {
|
export const deleteAccountController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const account = await getAccountForRequest(req);
|
||||||
|
|
||||||
|
// If this account is an admin, remove it from administratorNames
|
||||||
|
if (config.administratorNames) {
|
||||||
|
const adminIndex = config.administratorNames.indexOf(account.DisplayName);
|
||||||
|
if (adminIndex != -1) {
|
||||||
|
config.administratorNames.splice(adminIndex, 1);
|
||||||
|
await saveConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If account is the founding warlord of a guild, delete that guild as well.
|
// If account is the founding warlord of a guild, delete that guild as well.
|
||||||
const guildMember = await GuildMember.findOne({ accountId, rank: 0, status: 0 });
|
const guildMember = await GuildMember.findOne({ accountId: account._id, rank: 0, status: 0 });
|
||||||
if (guildMember) {
|
if (guildMember) {
|
||||||
await deleteGuild(guildMember.guildId);
|
await deleteGuild(guildMember.guildId);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
Account.deleteOne({ _id: accountId }),
|
Account.deleteOne({ _id: account._id }),
|
||||||
Friendship.deleteMany({ owner: accountId }),
|
Friendship.deleteMany({ owner: account._id }),
|
||||||
Friendship.deleteMany({ friend: accountId }),
|
Friendship.deleteMany({ friend: account._id }),
|
||||||
GuildMember.deleteMany({ accountId: accountId }),
|
GuildMember.deleteMany({ accountId: account._id }),
|
||||||
Ignore.deleteMany({ ignorer: accountId }),
|
Ignore.deleteMany({ ignorer: account._id }),
|
||||||
Ignore.deleteMany({ ignoree: accountId }),
|
Ignore.deleteMany({ ignoree: account._id }),
|
||||||
Inbox.deleteMany({ ownerId: accountId }),
|
Inbox.deleteMany({ ownerId: account._id }),
|
||||||
Inventory.deleteOne({ accountOwnerId: accountId }),
|
Inventory.deleteOne({ accountOwnerId: account._id }),
|
||||||
Leaderboard.deleteMany({ ownerId: accountId }),
|
Leaderboard.deleteMany({ ownerId: account._id }),
|
||||||
Loadout.deleteOne({ loadoutOwnerId: accountId }),
|
Loadout.deleteOne({ loadoutOwnerId: account._id }),
|
||||||
PersonalRooms.deleteOne({ personalRoomsOwnerId: accountId }),
|
PersonalRooms.deleteOne({ personalRoomsOwnerId: account._id }),
|
||||||
Ship.deleteMany({ ShipOwnerId: accountId }),
|
Ship.deleteMany({ ShipOwnerId: account._id }),
|
||||||
Stats.deleteOne({ accountOwnerId: accountId })
|
Stats.deleteOne({ accountOwnerId: account._id })
|
||||||
]);
|
]);
|
||||||
|
|
||||||
sendWsBroadcastTo(accountId, { logged_out: true });
|
sendWsBroadcastTo(account._id.toString(), { logged_out: true });
|
||||||
|
|
||||||
res.end();
|
res.end();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,36 +0,0 @@
|
|||||||
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
|
||||||
import { getInventory } from "../../services/inventoryService.ts";
|
|
||||||
import type { RequestHandler } from "express";
|
|
||||||
import { broadcastInventoryUpdate } from "../../services/wsService.ts";
|
|
||||||
|
|
||||||
const DEFAULT_UPGRADE_EXPIRY_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
|
|
||||||
|
|
||||||
export const editSuitInvigorationUpgradeController: RequestHandler = async (req, res) => {
|
|
||||||
const accountId = await getAccountIdForRequest(req);
|
|
||||||
const { oid, data } = req.body as {
|
|
||||||
oid: string;
|
|
||||||
data?: {
|
|
||||||
DefensiveUpgrade: string;
|
|
||||||
OffensiveUpgrade: string;
|
|
||||||
UpgradesExpiry?: number;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
const inventory = await getInventory(accountId);
|
|
||||||
const suit = inventory.Suits.id(oid)!;
|
|
||||||
if (data) {
|
|
||||||
suit.DefensiveUpgrade = data.DefensiveUpgrade;
|
|
||||||
suit.OffensiveUpgrade = data.OffensiveUpgrade;
|
|
||||||
if (data.UpgradesExpiry) {
|
|
||||||
suit.UpgradesExpiry = new Date(data.UpgradesExpiry);
|
|
||||||
} else {
|
|
||||||
suit.UpgradesExpiry = new Date(Date.now() + DEFAULT_UPGRADE_EXPIRY_MS);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
suit.DefensiveUpgrade = undefined;
|
|
||||||
suit.OffensiveUpgrade = undefined;
|
|
||||||
suit.UpgradesExpiry = undefined;
|
|
||||||
}
|
|
||||||
await inventory.save();
|
|
||||||
res.end();
|
|
||||||
broadcastInventoryUpdate(req);
|
|
||||||
};
|
|
||||||
@ -66,6 +66,7 @@ interface ItemLists {
|
|||||||
VaultDecoRecipes: ListedItem[];
|
VaultDecoRecipes: ListedItem[];
|
||||||
FlavourItems: ListedItem[];
|
FlavourItems: ListedItem[];
|
||||||
ShipDecorations: ListedItem[];
|
ShipDecorations: ListedItem[];
|
||||||
|
WeaponSkins: ListedItem[];
|
||||||
//circuitGameModes: ListedItem[];
|
//circuitGameModes: ListedItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +108,8 @@ const getItemListsController: RequestHandler = (req, response) => {
|
|||||||
TechProjects: [],
|
TechProjects: [],
|
||||||
VaultDecoRecipes: [],
|
VaultDecoRecipes: [],
|
||||||
FlavourItems: [],
|
FlavourItems: [],
|
||||||
ShipDecorations: []
|
ShipDecorations: [],
|
||||||
|
WeaponSkins: []
|
||||||
/*circuitGameModes: [
|
/*circuitGameModes: [
|
||||||
{
|
{
|
||||||
uniqueName: "Survival",
|
uniqueName: "Survival",
|
||||||
@ -298,10 +300,18 @@ const getItemListsController: RequestHandler = (req, response) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
for (const [uniqueName, item] of Object.entries(ExportCustoms)) {
|
for (const [uniqueName, item] of Object.entries(ExportCustoms)) {
|
||||||
res.miscitems.push({
|
if (
|
||||||
uniqueName: uniqueName,
|
item.productCategory == "WeaponSkins" &&
|
||||||
name: getString(item.name, lang)
|
!uniqueName.startsWith("/Lotus/Types/Game/Lotus") && // Base Items
|
||||||
});
|
!uniqueName.endsWith("ProjectileSkin") && // UnrealTournament ProjectileSkins
|
||||||
|
!uniqueName.endsWith("Coat") // Frost Prime stuff
|
||||||
|
) {
|
||||||
|
res.WeaponSkins.push({
|
||||||
|
uniqueName: uniqueName,
|
||||||
|
name: getString(item.name, lang),
|
||||||
|
alwaysAvailable: item.alwaysAvailable
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [uniqueName, upgrade] of Object.entries(ExportUpgrades)) {
|
for (const [uniqueName, upgrade] of Object.entries(ExportUpgrades)) {
|
||||||
|
|||||||
@ -115,7 +115,7 @@ export const manageQuestsController: RequestHandler = async (req, res) => {
|
|||||||
if (stage > 0) {
|
if (stage > 0) {
|
||||||
await giveKeyChainStageTriggered(inventory, {
|
await giveKeyChainStageTriggered(inventory, {
|
||||||
KeyChain: questKey.ItemType,
|
KeyChain: questKey.ItemType,
|
||||||
ChainStage: stage
|
ChainStage: stage - 1
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,22 +1,31 @@
|
|||||||
import { getInventory } from "../../services/inventoryService.ts";
|
import { getInventory } from "../../services/inventoryService.ts";
|
||||||
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
||||||
import { sendWsBroadcastTo } from "../../services/wsService.ts";
|
import { sendWsBroadcastEx, sendWsBroadcastTo } from "../../services/wsService.ts";
|
||||||
import type { IAccountCheats } from "../../types/inventoryTypes/inventoryTypes.ts";
|
import type { IAccountCheats } from "../../types/inventoryTypes/inventoryTypes.ts";
|
||||||
import type { RequestHandler } from "express";
|
import type { RequestHandler } from "express";
|
||||||
|
import { logger } from "../../utils/logger.ts";
|
||||||
|
|
||||||
export const setAccountCheatController: RequestHandler = async (req, res) => {
|
export const setAccountCheatController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
const payload = req.body as ISetAccountCheatRequest;
|
const payload = req.body as ISetAccountCheatRequest;
|
||||||
const inventory = await getInventory(accountId, payload.key);
|
const inventory = await getInventory(accountId, payload.key);
|
||||||
inventory[payload.key] = payload.value;
|
|
||||||
|
if (payload.value == undefined) {
|
||||||
|
logger.warn(`Aborting setting ${payload.key} as undefined!`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inventory[payload.key] = payload.value as never;
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
res.end();
|
res.end();
|
||||||
if (["infiniteCredits", "infinitePlatinum", "infiniteEndo", "infiniteRegalAya"].indexOf(payload.key) != -1) {
|
if (["infiniteCredits", "infinitePlatinum", "infiniteEndo", "infiniteRegalAya"].indexOf(payload.key) != -1) {
|
||||||
sendWsBroadcastTo(accountId, { update_inventory: true, sync_inventory: true });
|
sendWsBroadcastTo(accountId, { update_inventory: true, sync_inventory: true });
|
||||||
|
} else {
|
||||||
|
sendWsBroadcastEx({ update_inventory: true }, accountId, parseInt(String(req.query.wsid)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
interface ISetAccountCheatRequest {
|
interface ISetAccountCheatRequest {
|
||||||
key: keyof IAccountCheats;
|
key: keyof IAccountCheats;
|
||||||
value: boolean;
|
value: IAccountCheats[keyof IAccountCheats];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,44 +1,19 @@
|
|||||||
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
||||||
import { getInventory } from "../../services/inventoryService.ts";
|
import { getInventory } from "../../services/inventoryService.ts";
|
||||||
import type { RequestHandler } from "express";
|
import type { RequestHandler } from "express";
|
||||||
import { ExportBoosters } from "warframe-public-export-plus";
|
import type { IBooster } from "../../types/inventoryTypes/inventoryTypes.ts";
|
||||||
import { broadcastInventoryUpdate } from "../../services/wsService.ts";
|
import { broadcastInventoryUpdate } from "../../services/wsService.ts";
|
||||||
|
|
||||||
const I32_MAX = 0x7fffffff;
|
|
||||||
|
|
||||||
export const setBoosterController: RequestHandler = async (req, res) => {
|
export const setBoosterController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
const requests = req.body as { ItemType: string; ExpiryDate: number }[];
|
const requests = req.body as IBooster[];
|
||||||
const inventory = await getInventory(accountId, "Boosters");
|
const inventory = await getInventory(accountId, "Boosters");
|
||||||
const boosters = inventory.Boosters;
|
for (const request of requests) {
|
||||||
if (
|
const index = inventory.Boosters.findIndex(item => item.ItemType === request.ItemType);
|
||||||
requests.some(request => {
|
if (index !== -1) {
|
||||||
if (typeof request.ItemType !== "string") return true;
|
inventory.Boosters[index].ExpiryDate = request.ExpiryDate;
|
||||||
if (Object.entries(ExportBoosters).find(([_, item]) => item.typeName === request.ItemType) === undefined)
|
|
||||||
return true;
|
|
||||||
if (typeof request.ExpiryDate !== "number") return true;
|
|
||||||
if (request.ExpiryDate < 0 || request.ExpiryDate > I32_MAX) return true;
|
|
||||||
return false;
|
|
||||||
})
|
|
||||||
) {
|
|
||||||
res.status(400).send("Invalid ItemType provided.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const now = Math.trunc(Date.now() / 1000);
|
|
||||||
for (const { ItemType, ExpiryDate } of requests) {
|
|
||||||
if (ExpiryDate <= now) {
|
|
||||||
// remove expired boosters
|
|
||||||
const index = boosters.findIndex(item => item.ItemType === ItemType);
|
|
||||||
if (index !== -1) {
|
|
||||||
boosters.splice(index, 1);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
const boosterItem = boosters.find(item => item.ItemType === ItemType);
|
inventory.Boosters.push(request);
|
||||||
if (boosterItem) {
|
|
||||||
boosterItem.ExpiryDate = ExpiryDate;
|
|
||||||
} else {
|
|
||||||
boosters.push({ ItemType, ExpiryDate });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { GuildMember } from "../../models/guildModel.ts";
|
import { GuildMember } from "../../models/guildModel.ts";
|
||||||
import { getGuildForRequestEx, hasAccessToDojo } from "../../services/guildService.ts";
|
import { getGuildForRequestEx } from "../../services/guildService.ts";
|
||||||
import { getInventory } from "../../services/inventoryService.ts";
|
import { getInventory } from "../../services/inventoryService.ts";
|
||||||
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
||||||
import type { IGuildCheats } from "../../types/guildTypes.ts";
|
import type { IGuildCheats } from "../../types/guildTypes.ts";
|
||||||
@ -8,12 +8,12 @@ import type { RequestHandler } from "express";
|
|||||||
export const setGuildCheatController: RequestHandler = async (req, res) => {
|
export const setGuildCheatController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
const payload = req.body as ISetGuildCheatRequest;
|
const payload = req.body as ISetGuildCheatRequest;
|
||||||
const inventory = await getInventory(accountId, `${payload.key} GuildId LevelKeys`);
|
const inventory = await getInventory(accountId, `GuildId`);
|
||||||
const guild = await getGuildForRequestEx(req, inventory);
|
const guild = await getGuildForRequestEx(req, inventory);
|
||||||
const member = await GuildMember.findOne({ accountId: accountId, guildId: guild._id });
|
const member = await GuildMember.findOne({ accountId: accountId, guildId: guild._id });
|
||||||
|
|
||||||
if (member) {
|
if (member) {
|
||||||
if (!hasAccessToDojo(inventory) || member.rank > 1) {
|
if (member.rank > 1) {
|
||||||
res.end();
|
res.end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
27
src/controllers/custom/setInvigorationController.ts
Normal file
27
src/controllers/custom/setInvigorationController.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { getAccountIdForRequest } from "../../services/loginService.ts";
|
||||||
|
import { getInventory } from "../../services/inventoryService.ts";
|
||||||
|
import type { RequestHandler } from "express";
|
||||||
|
import { broadcastInventoryUpdate } from "../../services/wsService.ts";
|
||||||
|
|
||||||
|
export const setInvigorationController: RequestHandler = async (req, res) => {
|
||||||
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
const request = req.body as ISetInvigorationRequest;
|
||||||
|
const inventory = await getInventory(accountId, "Suits");
|
||||||
|
const suit = inventory.Suits.id(request.oid);
|
||||||
|
if (suit) {
|
||||||
|
const hasUpgrades = request.DefensiveUpgrade && request.OffensiveUpgrade && request.UpgradesExpiry;
|
||||||
|
suit.DefensiveUpgrade = hasUpgrades ? request.DefensiveUpgrade : undefined;
|
||||||
|
suit.OffensiveUpgrade = hasUpgrades ? request.OffensiveUpgrade : undefined;
|
||||||
|
suit.UpgradesExpiry = hasUpgrades ? new Date(request.UpgradesExpiry) : undefined;
|
||||||
|
await inventory.save();
|
||||||
|
broadcastInventoryUpdate(req);
|
||||||
|
}
|
||||||
|
res.end();
|
||||||
|
};
|
||||||
|
|
||||||
|
interface ISetInvigorationRequest {
|
||||||
|
oid: string;
|
||||||
|
DefensiveUpgrade: string;
|
||||||
|
OffensiveUpgrade: string;
|
||||||
|
UpgradesExpiry: number;
|
||||||
|
}
|
||||||
@ -2,7 +2,6 @@ import { getAccountIdForRequest } from "../../services/loginService.ts";
|
|||||||
import { getInventory } from "../../services/inventoryService.ts";
|
import { getInventory } from "../../services/inventoryService.ts";
|
||||||
import type { RequestHandler } from "express";
|
import type { RequestHandler } from "express";
|
||||||
import {
|
import {
|
||||||
hasAccessToDojo,
|
|
||||||
getGuildForRequestEx,
|
getGuildForRequestEx,
|
||||||
setGuildTechLogState,
|
setGuildTechLogState,
|
||||||
processFundedGuildTechProject,
|
processFundedGuildTechProject,
|
||||||
@ -19,9 +18,9 @@ import { GuildMember } from "../../models/guildModel.ts";
|
|||||||
export const addTechProjectController: RequestHandler = async (req, res) => {
|
export const addTechProjectController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
const requests = req.body as ITechProjectRequest[];
|
const requests = req.body as ITechProjectRequest[];
|
||||||
const inventory = await getInventory(accountId, "LevelKeys GuildId");
|
const inventory = await getInventory(accountId, "GuildId");
|
||||||
const guild = await getGuildForRequestEx(req, inventory);
|
const guild = await getGuildForRequestEx(req, inventory);
|
||||||
if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Tech))) {
|
if (!(await hasGuildPermission(guild, accountId, GuildPermission.Tech))) {
|
||||||
res.status(400).send("-1").end();
|
res.status(400).send("-1").end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -54,9 +53,9 @@ export const addTechProjectController: RequestHandler = async (req, res) => {
|
|||||||
export const removeTechProjectController: RequestHandler = async (req, res) => {
|
export const removeTechProjectController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
const requests = req.body as ITechProjectRequest[];
|
const requests = req.body as ITechProjectRequest[];
|
||||||
const inventory = await getInventory(accountId, "LevelKeys GuildId");
|
const inventory = await getInventory(accountId, "GuildId");
|
||||||
const guild = await getGuildForRequestEx(req, inventory);
|
const guild = await getGuildForRequestEx(req, inventory);
|
||||||
if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Tech))) {
|
if (!(await hasGuildPermission(guild, accountId, GuildPermission.Tech))) {
|
||||||
res.status(400).send("-1").end();
|
res.status(400).send("-1").end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -74,13 +73,13 @@ export const removeTechProjectController: RequestHandler = async (req, res) => {
|
|||||||
export const fundTechProjectController: RequestHandler = async (req, res) => {
|
export const fundTechProjectController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
const requests = req.body as ITechProjectRequest[];
|
const requests = req.body as ITechProjectRequest[];
|
||||||
const inventory = await getInventory(accountId, "LevelKeys GuildId");
|
const inventory = await getInventory(accountId, "GuildId");
|
||||||
const guild = await getGuildForRequestEx(req, inventory);
|
const guild = await getGuildForRequestEx(req, inventory);
|
||||||
const guildMember = (await GuildMember.findOne(
|
const guildMember = (await GuildMember.findOne(
|
||||||
{ accountId, guildId: guild._id },
|
{ accountId, guildId: guild._id },
|
||||||
"RegularCreditsContributed MiscItemsContributed"
|
"RegularCreditsContributed MiscItemsContributed"
|
||||||
))!;
|
))!;
|
||||||
if (!hasAccessToDojo(inventory)) {
|
if (!(await hasGuildPermission(guild, accountId, GuildPermission.Tech))) {
|
||||||
res.status(400).send("-1").end();
|
res.status(400).send("-1").end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -105,9 +104,9 @@ export const fundTechProjectController: RequestHandler = async (req, res) => {
|
|||||||
export const completeTechProjectsController: RequestHandler = async (req, res) => {
|
export const completeTechProjectsController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
const requests = req.body as ITechProjectRequest[];
|
const requests = req.body as ITechProjectRequest[];
|
||||||
const inventory = await getInventory(accountId, "LevelKeys GuildId");
|
const inventory = await getInventory(accountId, "GuildId");
|
||||||
const guild = await getGuildForRequestEx(req, inventory);
|
const guild = await getGuildForRequestEx(req, inventory);
|
||||||
if (!hasAccessToDojo(inventory)) {
|
if (!(await hasGuildPermission(guild, accountId, GuildPermission.Tech))) {
|
||||||
res.status(400).send("-1").end();
|
res.status(400).send("-1").end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,13 +20,14 @@ import type {
|
|||||||
} from "../../types/inventoryTypes/inventoryTypes.ts";
|
} from "../../types/inventoryTypes/inventoryTypes.ts";
|
||||||
import { LoadoutIndex } from "../../types/inventoryTypes/inventoryTypes.ts";
|
import { LoadoutIndex } from "../../types/inventoryTypes/inventoryTypes.ts";
|
||||||
import type { RequestHandler } from "express";
|
import type { RequestHandler } from "express";
|
||||||
import { catBreadHash, getJSONfromString } from "../../helpers/stringHelpers.ts";
|
import { getJSONfromString } from "../../helpers/stringHelpers.ts";
|
||||||
import { ExportCustoms, ExportDojoRecipes } from "warframe-public-export-plus";
|
import { ExportDojoRecipes } from "warframe-public-export-plus";
|
||||||
import type { IStatsClient } from "../../types/statTypes.ts";
|
import type { IStatsClient } from "../../types/statTypes.ts";
|
||||||
import { toStoreItem } from "../../services/itemDataService.ts";
|
import { toStoreItem } from "../../services/itemDataService.ts";
|
||||||
import type { FlattenMaps } from "mongoose";
|
import type { FlattenMaps } from "mongoose";
|
||||||
import type { IEquipmentClient } from "../../types/equipmentTypes.ts";
|
import type { IEquipmentClient } from "../../types/equipmentTypes.ts";
|
||||||
import type { ILoadoutConfigClient } from "../../types/saveLoadoutTypes.ts";
|
import type { ILoadoutConfigClient } from "../../types/saveLoadoutTypes.ts";
|
||||||
|
import { skinLookupTable } from "../../helpers/skinLookupTable.ts";
|
||||||
|
|
||||||
const getProfileViewingDataByPlayerIdImpl = async (playerId: string): Promise<IProfileViewingData | undefined> => {
|
const getProfileViewingDataByPlayerIdImpl = async (playerId: string): Promise<IProfileViewingData | undefined> => {
|
||||||
const account = await Account.findById(playerId, "DisplayName");
|
const account = await Account.findById(playerId, "DisplayName");
|
||||||
@ -261,8 +262,6 @@ interface IXPComponentClient {
|
|||||||
locTags?: Record<string, string>;
|
locTags?: Record<string, string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let skinLookupTable: Record<number, string> | undefined;
|
|
||||||
|
|
||||||
const resolveAndCollectSkins = (
|
const resolveAndCollectSkins = (
|
||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
skins: Set<string>,
|
skins: Set<string>,
|
||||||
@ -274,12 +273,6 @@ const resolveAndCollectSkins = (
|
|||||||
// Resolve oids to type names
|
// Resolve oids to type names
|
||||||
if (config.Skins[i].length == 24) {
|
if (config.Skins[i].length == 24) {
|
||||||
if (config.Skins[i].substring(0, 16) == "ca70ca70ca70ca70") {
|
if (config.Skins[i].substring(0, 16) == "ca70ca70ca70ca70") {
|
||||||
if (!skinLookupTable) {
|
|
||||||
skinLookupTable = {};
|
|
||||||
for (const key of Object.keys(ExportCustoms)) {
|
|
||||||
skinLookupTable[catBreadHash(key)] = key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
config.Skins[i] = skinLookupTable[parseInt(config.Skins[i].substring(16), 16)];
|
config.Skins[i] = skinLookupTable[parseInt(config.Skins[i].substring(16), 16)];
|
||||||
} else {
|
} else {
|
||||||
const skinItem = inventory.WeaponSkins.id(config.Skins[i]);
|
const skinItem = inventory.WeaponSkins.id(config.Skins[i]);
|
||||||
|
|||||||
@ -54,6 +54,9 @@ export const crackRelic = async (
|
|||||||
(await handleStoreItemAcquisition(reward.type, inventory, reward.itemCount)).InventoryChanges
|
(await handleStoreItemAcquisition(reward.type, inventory, reward.itemCount)).InventoryChanges
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Client has picked its own reward (for lack of choice)
|
||||||
|
participant.ChosenRewardOwner = participant.AccountId;
|
||||||
|
|
||||||
return reward;
|
return reward;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
8
src/helpers/skinLookupTable.ts
Normal file
8
src/helpers/skinLookupTable.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { ExportCustoms } from "warframe-public-export-plus";
|
||||||
|
import { catBreadHash } from "./stringHelpers.ts";
|
||||||
|
|
||||||
|
export const skinLookupTable: Record<number, string> = {};
|
||||||
|
|
||||||
|
for (const key of Object.keys(ExportCustoms)) {
|
||||||
|
skinLookupTable[catBreadHash(key)] = key;
|
||||||
|
}
|
||||||
@ -1462,11 +1462,20 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
|||||||
flawlessRelicsAlwaysGiveSilverReward: Boolean,
|
flawlessRelicsAlwaysGiveSilverReward: Boolean,
|
||||||
radiantRelicsAlwaysGiveGoldReward: Boolean,
|
radiantRelicsAlwaysGiveGoldReward: Boolean,
|
||||||
disableDailyTribute: Boolean,
|
disableDailyTribute: Boolean,
|
||||||
|
nemesisHenchmenKillsMultiplierGrineer: Number,
|
||||||
|
nemesisHenchmenKillsMultiplierCorpus: Number,
|
||||||
|
nemesisAntivirusGainMultiplier: Number,
|
||||||
|
nemesisHintProgressMultiplierGrineer: Number,
|
||||||
|
nemesisHintProgressMultiplierCorpus: Number,
|
||||||
|
nemesisExtraWeapon: Number,
|
||||||
|
|
||||||
SubscribedToEmails: { type: Number, default: 0 },
|
SubscribedToEmails: { type: Number, default: 0 },
|
||||||
SubscribedToEmailsPersonalized: { type: Number, default: 0 },
|
SubscribedToEmailsPersonalized: { type: Number, default: 0 },
|
||||||
RewardSeed: BigInt,
|
RewardSeed: BigInt,
|
||||||
|
|
||||||
|
// Temporary data so we can show all relic rewards from an endless mission at EOM
|
||||||
|
MissionRelicRewards: { type: [typeCountSchema], default: undefined },
|
||||||
|
|
||||||
//Credit
|
//Credit
|
||||||
RegularCredits: { type: Number, default: 0 },
|
RegularCredits: { type: Number, default: 0 },
|
||||||
//Platinum
|
//Platinum
|
||||||
@ -1734,7 +1743,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
|||||||
NemesisAbandonedRewards: { type: [String], default: [] },
|
NemesisAbandonedRewards: { type: [String], default: [] },
|
||||||
Nemesis: nemesisSchema,
|
Nemesis: nemesisSchema,
|
||||||
NemesisHistory: { type: [nemesisSchema], default: undefined },
|
NemesisHistory: { type: [nemesisSchema], default: undefined },
|
||||||
//LastNemesisAllySpawnTime: Schema.Types.Mixed,
|
LastNemesisAllySpawnTime: { type: Date, default: undefined },
|
||||||
|
|
||||||
//TradingRulesConfirmed,ShowFriendInvNotifications(Option->Social)
|
//TradingRulesConfirmed,ShowFriendInvNotifications(Option->Social)
|
||||||
Settings: settingsSchema,
|
Settings: settingsSchema,
|
||||||
@ -1835,6 +1844,7 @@ inventorySchema.set("toJSON", {
|
|||||||
delete returnedObject._id;
|
delete returnedObject._id;
|
||||||
delete returnedObject.__v;
|
delete returnedObject.__v;
|
||||||
delete returnedObject.accountOwnerId;
|
delete returnedObject.accountOwnerId;
|
||||||
|
delete returnedObject.MissionRelicRewards;
|
||||||
|
|
||||||
const inventoryDatabase = returnedObject as Partial<IInventoryDatabase>;
|
const inventoryDatabase = returnedObject as Partial<IInventoryDatabase>;
|
||||||
const inventoryResponse = returnedObject as IInventoryClient;
|
const inventoryResponse = returnedObject as IInventoryClient;
|
||||||
@ -1854,6 +1864,9 @@ inventorySchema.set("toJSON", {
|
|||||||
if (inventoryDatabase.BlessingCooldown) {
|
if (inventoryDatabase.BlessingCooldown) {
|
||||||
inventoryResponse.BlessingCooldown = toMongoDate(inventoryDatabase.BlessingCooldown);
|
inventoryResponse.BlessingCooldown = toMongoDate(inventoryDatabase.BlessingCooldown);
|
||||||
}
|
}
|
||||||
|
if (inventoryDatabase.LastNemesisAllySpawnTime) {
|
||||||
|
inventoryResponse.LastNemesisAllySpawnTime = toMongoDate(inventoryDatabase.LastNemesisAllySpawnTime);
|
||||||
|
}
|
||||||
if (inventoryDatabase.NextRefill) {
|
if (inventoryDatabase.NextRefill) {
|
||||||
inventoryResponse.NextRefill = toMongoDate(inventoryDatabase.NextRefill);
|
inventoryResponse.NextRefill = toMongoDate(inventoryDatabase.NextRefill);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,6 +53,7 @@ import { evolveWeaponController } from "../controllers/api/evolveWeaponControlle
|
|||||||
import { findSessionsController } from "../controllers/api/findSessionsController.ts";
|
import { findSessionsController } from "../controllers/api/findSessionsController.ts";
|
||||||
import { fishmongerController } from "../controllers/api/fishmongerController.ts";
|
import { fishmongerController } from "../controllers/api/fishmongerController.ts";
|
||||||
import { focusController } from "../controllers/api/focusController.ts";
|
import { focusController } from "../controllers/api/focusController.ts";
|
||||||
|
import { forceRemoveItemController } from "../controllers/api/forceRemoveItemController.ts";
|
||||||
import { fusionTreasuresController } from "../controllers/api/fusionTreasuresController.ts";
|
import { fusionTreasuresController } from "../controllers/api/fusionTreasuresController.ts";
|
||||||
import { gardeningController } from "../controllers/api/gardeningController.ts";
|
import { gardeningController } from "../controllers/api/gardeningController.ts";
|
||||||
import { genericUpdateController } from "../controllers/api/genericUpdateController.ts";
|
import { genericUpdateController } from "../controllers/api/genericUpdateController.ts";
|
||||||
@ -66,8 +67,8 @@ import { getGuildEventScoreController } from "../controllers/api/getGuildEventSc
|
|||||||
import { getGuildLogController } from "../controllers/api/getGuildLogController.ts";
|
import { getGuildLogController } from "../controllers/api/getGuildLogController.ts";
|
||||||
import { getIgnoredUsersController } from "../controllers/api/getIgnoredUsersController.ts";
|
import { getIgnoredUsersController } from "../controllers/api/getIgnoredUsersController.ts";
|
||||||
import { getNewRewardSeedController } from "../controllers/api/getNewRewardSeedController.ts";
|
import { getNewRewardSeedController } from "../controllers/api/getNewRewardSeedController.ts";
|
||||||
import { getProfileViewingDataPostController } from "../controllers/dynamic/getProfileViewingDataController.ts";
|
|
||||||
import { getPastWeeklyChallengesController } from "../controllers/api/getPastWeeklyChallengesController.ts";
|
import { getPastWeeklyChallengesController } from "../controllers/api/getPastWeeklyChallengesController.ts";
|
||||||
|
import { getProfileViewingDataPostController } from "../controllers/dynamic/getProfileViewingDataController.ts";
|
||||||
import { getShipController } from "../controllers/api/getShipController.ts";
|
import { getShipController } from "../controllers/api/getShipController.ts";
|
||||||
import { getVendorInfoController } from "../controllers/api/getVendorInfoController.ts";
|
import { getVendorInfoController } from "../controllers/api/getVendorInfoController.ts";
|
||||||
import { getVoidProjectionRewardsController } from "../controllers/api/getVoidProjectionRewardsController.ts";
|
import { getVoidProjectionRewardsController } from "../controllers/api/getVoidProjectionRewardsController.ts";
|
||||||
@ -273,6 +274,7 @@ apiRouter.post("/evolveWeapon.php", evolveWeaponController);
|
|||||||
apiRouter.post("/findSessions.php", findSessionsController);
|
apiRouter.post("/findSessions.php", findSessionsController);
|
||||||
apiRouter.post("/fishmonger.php", fishmongerController);
|
apiRouter.post("/fishmonger.php", fishmongerController);
|
||||||
apiRouter.post("/focus.php", focusController);
|
apiRouter.post("/focus.php", focusController);
|
||||||
|
apiRouter.post("/forceRemoveItem.php", forceRemoveItemController);
|
||||||
apiRouter.post("/fusionTreasures.php", fusionTreasuresController);
|
apiRouter.post("/fusionTreasures.php", fusionTreasuresController);
|
||||||
apiRouter.post("/gardening.php", gardeningController);
|
apiRouter.post("/gardening.php", gardeningController);
|
||||||
apiRouter.post("/genericUpdate.php", genericUpdateController);
|
apiRouter.post("/genericUpdate.php", genericUpdateController);
|
||||||
|
|||||||
@ -43,7 +43,7 @@ import { setBoosterController } from "../controllers/custom/setBoosterController
|
|||||||
import { updateFingerprintController } from "../controllers/custom/updateFingerprintController.ts";
|
import { updateFingerprintController } from "../controllers/custom/updateFingerprintController.ts";
|
||||||
import { unlockLevelCapController } from "../controllers/custom/unlockLevelCapController.ts";
|
import { unlockLevelCapController } from "../controllers/custom/unlockLevelCapController.ts";
|
||||||
import { changeModularPartsController } from "../controllers/custom/changeModularPartsController.ts";
|
import { changeModularPartsController } from "../controllers/custom/changeModularPartsController.ts";
|
||||||
import { editSuitInvigorationUpgradeController } from "../controllers/custom/editSuitInvigorationUpgradeController.ts";
|
import { setInvigorationController } from "../controllers/custom/setInvigorationController.ts";
|
||||||
import { setAccountCheatController } from "../controllers/custom/setAccountCheatController.ts";
|
import { setAccountCheatController } from "../controllers/custom/setAccountCheatController.ts";
|
||||||
import { setGuildCheatController } from "../controllers/custom/setGuildCheatController.ts";
|
import { setGuildCheatController } from "../controllers/custom/setGuildCheatController.ts";
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ customRouter.post("/setBooster", setBoosterController);
|
|||||||
customRouter.post("/updateFingerprint", updateFingerprintController);
|
customRouter.post("/updateFingerprint", updateFingerprintController);
|
||||||
customRouter.post("/unlockLevelCap", unlockLevelCapController);
|
customRouter.post("/unlockLevelCap", unlockLevelCapController);
|
||||||
customRouter.post("/changeModularParts", changeModularPartsController);
|
customRouter.post("/changeModularParts", changeModularPartsController);
|
||||||
customRouter.post("/editSuitInvigorationUpgrade", editSuitInvigorationUpgradeController);
|
customRouter.post("/setInvigoration", setInvigorationController);
|
||||||
customRouter.post("/setAccountCheat", setAccountCheatController);
|
customRouter.post("/setAccountCheat", setAccountCheatController);
|
||||||
customRouter.post("/setGuildCheat", setGuildCheatController);
|
customRouter.post("/setGuildCheat", setGuildCheatController);
|
||||||
|
|
||||||
|
|||||||
@ -48,8 +48,14 @@ export interface IConfig {
|
|||||||
anniversary?: number;
|
anniversary?: number;
|
||||||
hallowedNightmares?: boolean;
|
hallowedNightmares?: boolean;
|
||||||
hallowedNightmaresRewardsOverride?: number;
|
hallowedNightmaresRewardsOverride?: number;
|
||||||
|
naberusNightsOverride?: boolean;
|
||||||
proxyRebellion?: boolean;
|
proxyRebellion?: boolean;
|
||||||
proxyRebellionRewardsOverride?: number;
|
proxyRebellionRewardsOverride?: number;
|
||||||
|
voidCorruption2025Week1?: boolean;
|
||||||
|
voidCorruption2025Week2?: boolean;
|
||||||
|
voidCorruption2025Week3?: boolean;
|
||||||
|
voidCorruption2025Week4?: boolean;
|
||||||
|
qtccAlerts?: boolean;
|
||||||
galleonOfGhouls?: number;
|
galleonOfGhouls?: number;
|
||||||
ghoulEmergenceOverride?: boolean;
|
ghoulEmergenceOverride?: boolean;
|
||||||
plagueStarOverride?: boolean;
|
plagueStarOverride?: boolean;
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import type {
|
|||||||
ITechProjectDatabase
|
ITechProjectDatabase
|
||||||
} from "../types/guildTypes.ts";
|
} from "../types/guildTypes.ts";
|
||||||
import { GuildPermission } from "../types/guildTypes.ts";
|
import { GuildPermission } from "../types/guildTypes.ts";
|
||||||
import { toMongoDate, toOid, toOid2 } from "../helpers/inventoryHelpers.ts";
|
import { toMongoDate, toOid, toOid2, version_compare } from "../helpers/inventoryHelpers.ts";
|
||||||
import type { Types } from "mongoose";
|
import type { Types } from "mongoose";
|
||||||
import type { IDojoBuild, IDojoResearch } from "warframe-public-export-plus";
|
import type { IDojoBuild, IDojoResearch } from "warframe-public-export-plus";
|
||||||
import { ExportDojoRecipes, ExportResources } from "warframe-public-export-plus";
|
import { ExportDojoRecipes, ExportResources } from "warframe-public-export-plus";
|
||||||
@ -68,9 +68,15 @@ export const getGuildClient = async (
|
|||||||
let missingEntry = true;
|
let missingEntry = true;
|
||||||
const dataFillInPromises: Promise<void>[] = [];
|
const dataFillInPromises: Promise<void>[] = [];
|
||||||
for (const guildMember of guildMembers) {
|
for (const guildMember of guildMembers) {
|
||||||
|
// Use 1-based indexing for clan ranks for versions before U24. In my testing, 2018.06.14.23.21 and below used 1-based indexing and 2019.04.04.21.31 and above used 0-based indexing. I didn't narrow it down further, but I think U24 is a good spot for them to have changed it.
|
||||||
|
let rankBase = 0;
|
||||||
|
if (account.BuildLabel && version_compare(account.BuildLabel, "2018.11.08.14.45") < 0) {
|
||||||
|
rankBase += 1;
|
||||||
|
}
|
||||||
|
|
||||||
const member: IGuildMemberClient = {
|
const member: IGuildMemberClient = {
|
||||||
_id: toOid2(guildMember.accountId, account.BuildLabel),
|
_id: toOid2(guildMember.accountId, account.BuildLabel),
|
||||||
Rank: guildMember.rank,
|
Rank: guildMember.rank + rankBase,
|
||||||
Status: guildMember.status,
|
Status: guildMember.status,
|
||||||
Note: guildMember.RequestMsg,
|
Note: guildMember.RequestMsg,
|
||||||
RequestExpiry: guildMember.RequestExpiry ? toMongoDate(guildMember.RequestExpiry) : undefined
|
RequestExpiry: guildMember.RequestExpiry ? toMongoDate(guildMember.RequestExpiry) : undefined
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import type {
|
|||||||
} from "../types/inventoryTypes/commonInventoryTypes.ts";
|
} from "../types/inventoryTypes/commonInventoryTypes.ts";
|
||||||
import type { IMongoDate } from "../types/commonTypes.ts";
|
import type { IMongoDate } from "../types/commonTypes.ts";
|
||||||
import type {
|
import type {
|
||||||
|
IBooster,
|
||||||
IDialogueClient,
|
IDialogueClient,
|
||||||
IDialogueDatabase,
|
IDialogueDatabase,
|
||||||
IDialogueHistoryClient,
|
IDialogueHistoryClient,
|
||||||
@ -72,6 +73,7 @@ import type {
|
|||||||
ITailorShop,
|
ITailorShop,
|
||||||
ITailorShopDatabase
|
ITailorShopDatabase
|
||||||
} from "../types/personalRoomsTypes.ts";
|
} from "../types/personalRoomsTypes.ts";
|
||||||
|
import { fromMongoDate } from "../helpers/inventoryHelpers.ts";
|
||||||
|
|
||||||
const convertDate = (value: IMongoDate): Date => {
|
const convertDate = (value: IMongoDate): Date => {
|
||||||
return new Date(parseInt(value.$date.$numberLong));
|
return new Date(parseInt(value.$date.$numberLong));
|
||||||
@ -325,7 +327,15 @@ export const importInventory = (db: TInventoryDatabaseDocument, client: Partial<
|
|||||||
"GiftsRemaining",
|
"GiftsRemaining",
|
||||||
"ChallengesFixVersion",
|
"ChallengesFixVersion",
|
||||||
"Founder",
|
"Founder",
|
||||||
"Guide"
|
"Guide",
|
||||||
|
"BountyScore",
|
||||||
|
"EntratiVaultCountLastPeriod",
|
||||||
|
"EntratiLabConquestUnlocked",
|
||||||
|
"EntratiLabConquestHardModeStatus",
|
||||||
|
"EntratiLabConquestCacheScoreMission",
|
||||||
|
"EchoesHexConquestUnlocked",
|
||||||
|
"EchoesHexConquestHardModeStatus",
|
||||||
|
"EchoesHexConquestCacheScoreMission"
|
||||||
] as const) {
|
] as const) {
|
||||||
if (client[key] !== undefined) {
|
if (client[key] !== undefined) {
|
||||||
db[key] = client[key];
|
db[key] = client[key];
|
||||||
@ -353,12 +363,28 @@ export const importInventory = (db: TInventoryDatabaseDocument, client: Partial<
|
|||||||
"NodeIntrosCompleted",
|
"NodeIntrosCompleted",
|
||||||
"DeathMarks",
|
"DeathMarks",
|
||||||
"Wishlist",
|
"Wishlist",
|
||||||
"NemesisAbandonedRewards"
|
"NemesisAbandonedRewards",
|
||||||
|
"EntratiLabConquestActiveFrameVariants",
|
||||||
|
"EchoesHexConquestActiveFrameVariants",
|
||||||
|
"EchoesHexConquestActiveStickers"
|
||||||
] as const) {
|
] as const) {
|
||||||
if (client[key] !== undefined) {
|
if (client[key] !== undefined) {
|
||||||
db[key] = client[key];
|
db[key] = client[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// IMongoDate
|
||||||
|
for (const key of [
|
||||||
|
"Created",
|
||||||
|
"TrainingDate",
|
||||||
|
"BlessingCooldown",
|
||||||
|
"LastNemesisAllySpawnTime",
|
||||||
|
"NextRefill",
|
||||||
|
"EntratiVaultCountResetDate"
|
||||||
|
] as const) {
|
||||||
|
if (client[key] !== undefined) {
|
||||||
|
db[key] = fromMongoDate(client[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
// IRewardAtten[]
|
// IRewardAtten[]
|
||||||
for (const key of ["SortieRewardAttenuation", "SpecialItemRewardAttenuation"] as const) {
|
for (const key of ["SortieRewardAttenuation", "SpecialItemRewardAttenuation"] as const) {
|
||||||
if (client[key] !== undefined) {
|
if (client[key] !== undefined) {
|
||||||
@ -463,6 +489,9 @@ export const importInventory = (db: TInventoryDatabaseDocument, client: Partial<
|
|||||||
if (client.Accolades !== undefined) {
|
if (client.Accolades !== undefined) {
|
||||||
db.Accolades = client.Accolades;
|
db.Accolades = client.Accolades;
|
||||||
}
|
}
|
||||||
|
if (client.Boosters !== undefined) {
|
||||||
|
replaceArray<IBooster>(db.Boosters, client.Boosters);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const importLoadOutConfig = (client: ILoadoutConfigClient): ILoadoutConfigDatabase => {
|
export const importLoadOutConfig = (client: ILoadoutConfigClient): ILoadoutConfigDatabase => {
|
||||||
|
|||||||
@ -1,11 +1,6 @@
|
|||||||
import type { IMessageDatabase } from "../models/inboxModel.ts";
|
import type { IMessageDatabase } from "../models/inboxModel.ts";
|
||||||
import { Inbox } from "../models/inboxModel.ts";
|
import { Inbox } from "../models/inboxModel.ts";
|
||||||
import { getAccountForRequest } from "./loginService.ts";
|
import type { HydratedDocument, Types } from "mongoose";
|
||||||
import type { HydratedDocument } from "mongoose";
|
|
||||||
import { Types } from "mongoose";
|
|
||||||
import type { Request } from "express";
|
|
||||||
import { unixTimesInMs } from "../constants/timeConstants.ts";
|
|
||||||
import { config } from "./configService.ts";
|
|
||||||
|
|
||||||
export const getAllMessagesSorted = async (accountId: string): Promise<HydratedDocument<IMessageDatabase>[]> => {
|
export const getAllMessagesSorted = async (accountId: string): Promise<HydratedDocument<IMessageDatabase>[]> => {
|
||||||
const inbox = await Inbox.find({ ownerId: accountId }).sort({ date: -1 });
|
const inbox = await Inbox.find({ ownerId: accountId }).sort({ date: -1 });
|
||||||
@ -29,117 +24,8 @@ export const deleteAllMessagesRead = async (accountId: string): Promise<void> =>
|
|||||||
await Inbox.deleteMany({ ownerId: accountId, r: true });
|
await Inbox.deleteMany({ ownerId: accountId, r: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createNewEventMessages = async (req: Request): Promise<void> => {
|
export const deleteAllMessagesReadNonCin = async (accountId: string): Promise<void> => {
|
||||||
const account = await getAccountForRequest(req);
|
await Inbox.deleteMany({ ownerId: accountId, r: true, cinematic: null });
|
||||||
const newEventMessages: IMessageCreationTemplate[] = [];
|
|
||||||
|
|
||||||
// Baro
|
|
||||||
const baroIndex = Math.trunc((Date.now() - 910800000) / (unixTimesInMs.day * 14));
|
|
||||||
const baroStart = baroIndex * (unixTimesInMs.day * 14) + 910800000;
|
|
||||||
const baroActualStart = baroStart + unixTimesInMs.day * (config.worldState?.baroAlwaysAvailable ? 0 : 12);
|
|
||||||
if (Date.now() >= baroActualStart && account.LatestEventMessageDate.getTime() < baroActualStart) {
|
|
||||||
newEventMessages.push({
|
|
||||||
sndr: "/Lotus/Language/G1Quests/VoidTraderName",
|
|
||||||
sub: "/Lotus/Language/CommunityMessages/VoidTraderAppearanceTitle",
|
|
||||||
msg: "/Lotus/Language/CommunityMessages/VoidTraderAppearanceMessage",
|
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/BaroKiTeerPortrait.png",
|
|
||||||
startDate: new Date(baroActualStart),
|
|
||||||
endDate: new Date(baroStart + unixTimesInMs.day * 14),
|
|
||||||
CrossPlatform: true,
|
|
||||||
arg: [
|
|
||||||
{
|
|
||||||
Key: "NODE_NAME",
|
|
||||||
Tag: ["EarthHUB", "MercuryHUB", "SaturnHUB", "PlutoHUB"][baroIndex % 4]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
date: new Date(baroActualStart)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// BUG: Deleting the inbox message manually means it'll just be automatically re-created. This is because we don't use startDate/endDate for these config-toggled events.
|
|
||||||
const promises = [];
|
|
||||||
if (config.worldState?.creditBoost) {
|
|
||||||
promises.push(
|
|
||||||
(async (): Promise<void> => {
|
|
||||||
if (!(await Inbox.exists({ ownerId: account._id, globaUpgradeId: "5b23106f283a555109666672" }))) {
|
|
||||||
newEventMessages.push({
|
|
||||||
globaUpgradeId: new Types.ObjectId("5b23106f283a555109666672"),
|
|
||||||
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
|
||||||
sub: "/Lotus/Language/Items/EventDoubleCreditsName",
|
|
||||||
msg: "/Lotus/Language/Items/EventDoubleCreditsDesc",
|
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
|
||||||
startDate: new Date(),
|
|
||||||
CrossPlatform: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (config.worldState?.affinityBoost) {
|
|
||||||
promises.push(
|
|
||||||
(async (): Promise<void> => {
|
|
||||||
if (!(await Inbox.exists({ ownerId: account._id, globaUpgradeId: "5b23106f283a555109666673" }))) {
|
|
||||||
newEventMessages.push({
|
|
||||||
globaUpgradeId: new Types.ObjectId("5b23106f283a555109666673"),
|
|
||||||
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
|
||||||
sub: "/Lotus/Language/Items/EventDoubleAffinityName",
|
|
||||||
msg: "/Lotus/Language/Items/EventDoubleAffinityDesc",
|
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
|
||||||
startDate: new Date(),
|
|
||||||
CrossPlatform: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (config.worldState?.resourceBoost) {
|
|
||||||
promises.push(
|
|
||||||
(async (): Promise<void> => {
|
|
||||||
if (!(await Inbox.exists({ ownerId: account._id, globaUpgradeId: "5b23106f283a555109666674" }))) {
|
|
||||||
newEventMessages.push({
|
|
||||||
globaUpgradeId: new Types.ObjectId("5b23106f283a555109666674"),
|
|
||||||
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
|
||||||
sub: "/Lotus/Language/Items/EventDoubleResourceName",
|
|
||||||
msg: "/Lotus/Language/Items/EventDoubleResourceDesc",
|
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
|
||||||
startDate: new Date(),
|
|
||||||
CrossPlatform: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (config.worldState?.galleonOfGhouls) {
|
|
||||||
promises.push(
|
|
||||||
(async (): Promise<void> => {
|
|
||||||
if (!(await Inbox.exists({ ownerId: account._id, goalTag: "GalleonRobbery" }))) {
|
|
||||||
newEventMessages.push({
|
|
||||||
sndr: "/Lotus/Language/Bosses/BossCouncilorVayHek",
|
|
||||||
sub: "/Lotus/Language/Events/GalleonRobberyIntroMsgTitle",
|
|
||||||
msg: "/Lotus/Language/Events/GalleonRobberyIntroMsgDesc",
|
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/VayHekPortrait.png",
|
|
||||||
transmission: "/Lotus/Sounds/Dialog/GalleonOfGhouls/DGhoulsWeekOneInbox0010VayHek",
|
|
||||||
att: ["/Lotus/Upgrades/Skins/Events/OgrisOldSchool"],
|
|
||||||
startDate: new Date(),
|
|
||||||
goalTag: "GalleonRobbery"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
await Promise.all(promises);
|
|
||||||
|
|
||||||
if (newEventMessages.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await createMessage(account._id, newEventMessages);
|
|
||||||
|
|
||||||
const latestEventMessage = newEventMessages.reduce((prev, current) =>
|
|
||||||
prev.startDate! > current.startDate! ? prev : current
|
|
||||||
);
|
|
||||||
account.LatestEventMessageDate = new Date(latestEventMessage.startDate!);
|
|
||||||
await account.save();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createMessage = async (
|
export const createMessage = async (
|
||||||
|
|||||||
@ -92,6 +92,7 @@ import type {
|
|||||||
} from "../types/equipmentTypes.ts";
|
} from "../types/equipmentTypes.ts";
|
||||||
import { EquipmentFeatures, Status } from "../types/equipmentTypes.ts";
|
import { EquipmentFeatures, Status } from "../types/equipmentTypes.ts";
|
||||||
import type { ITypeCount } from "../types/commonTypes.ts";
|
import type { ITypeCount } from "../types/commonTypes.ts";
|
||||||
|
import { skinLookupTable } from "../helpers/skinLookupTable.ts";
|
||||||
|
|
||||||
export const createInventory = async (
|
export const createInventory = async (
|
||||||
accountOwnerId: Types.ObjectId,
|
accountOwnerId: Types.ObjectId,
|
||||||
@ -1489,7 +1490,13 @@ export const addSkin = (
|
|||||||
inventoryChanges: IInventoryChanges = {}
|
inventoryChanges: IInventoryChanges = {}
|
||||||
): IInventoryChanges => {
|
): IInventoryChanges => {
|
||||||
if (inventory.WeaponSkins.some(x => x.ItemType == typeName)) {
|
if (inventory.WeaponSkins.some(x => x.ItemType == typeName)) {
|
||||||
logger.debug(`refusing to add WeaponSkin ${typeName} because account already owns it`);
|
if (typeName == "/Lotus/Upgrades/Skins/Clan/BountyHunterBadgeItem") {
|
||||||
|
logger.debug(`account already owns stratos emblem, increasing bounty score instead`);
|
||||||
|
inventory.BountyScore ??= 0;
|
||||||
|
inventory.BountyScore += 1;
|
||||||
|
} else {
|
||||||
|
logger.debug(`refusing to add WeaponSkin ${typeName} because account already owns it`);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const index =
|
const index =
|
||||||
inventory.WeaponSkins.push({
|
inventory.WeaponSkins.push({
|
||||||
@ -2254,7 +2261,7 @@ export const setupKahlSyndicate = (inventory: TInventoryDatabaseDocument): void
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const cleanupInventory = (inventory: TInventoryDatabaseDocument): void => {
|
export const cleanupInventory = async (inventory: TInventoryDatabaseDocument): Promise<void> => {
|
||||||
inventory.CurrentLoadOutIds = inventory.CurrentLoadOutIds.map(fromDbOid);
|
inventory.CurrentLoadOutIds = inventory.CurrentLoadOutIds.map(fromDbOid);
|
||||||
|
|
||||||
let index = inventory.MiscItems.findIndex(x => x.ItemType == "");
|
let index = inventory.MiscItems.findIndex(x => x.ItemType == "");
|
||||||
@ -2308,6 +2315,99 @@ export const cleanupInventory = (inventory: TInventoryDatabaseDocument): void =>
|
|||||||
logger.debug(`removed ModularParts from ${numFixed} non-modular items`);
|
logger.debug(`removed ModularParts from ${numFixed} non-modular items`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const weaponMap = new Map<string, string>();
|
||||||
|
for (const skin of inventory.WeaponSkins) {
|
||||||
|
weaponMap.set(skin.ItemType, skin._id.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemsToAdd = new Set<string>();
|
||||||
|
|
||||||
|
for (const key of equipmentKeys) {
|
||||||
|
if (key in inventory) {
|
||||||
|
for (const equipment of inventory[key]) {
|
||||||
|
for (const config of equipment.Configs) {
|
||||||
|
if (config.Skins) collectSkins(config.Skins, weaponMap, itemsToAdd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key of ["AdultOperatorLoadOuts", "OperatorLoadOuts", "KahlLoadOuts"] as const) {
|
||||||
|
if (key in inventory) {
|
||||||
|
for (const loadOut of inventory[key]) {
|
||||||
|
if (loadOut.Skins) collectSkins(loadOut.Skins, weaponMap, itemsToAdd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inventory.LotusCustomization?.Skins)
|
||||||
|
collectSkins(inventory.LotusCustomization.Skins, weaponMap, itemsToAdd);
|
||||||
|
|
||||||
|
if (itemsToAdd.size > 0) {
|
||||||
|
logger.debug(`Adding ${itemsToAdd.size} items due to migration from unlockAllSkins cheat`);
|
||||||
|
const inventoryChanges = await addItems(inventory, Array.from(itemsToAdd));
|
||||||
|
|
||||||
|
if (inventoryChanges.WeaponSkins) {
|
||||||
|
for (const skin of inventoryChanges.WeaponSkins as IWeaponSkinClient[]) {
|
||||||
|
weaponMap.set(skin.ItemType, skin.ItemId.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key of equipmentKeys) {
|
||||||
|
if (key in inventory) {
|
||||||
|
for (const equipment of inventory[key]) {
|
||||||
|
for (const config of equipment.Configs) {
|
||||||
|
if (config.Skins) replaceSkinIds(config.Skins, weaponMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key of ["AdultOperatorLoadOuts", "OperatorLoadOuts", "KahlLoadOuts"] as const) {
|
||||||
|
if (key in inventory) {
|
||||||
|
for (const loadOut of inventory[key]) {
|
||||||
|
if (loadOut.Skins) replaceSkinIds(loadOut.Skins, weaponMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inventory.LotusCustomization?.Skins) replaceSkinIds(inventory.LotusCustomization.Skins, weaponMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const collectSkins = (skins: string[], weaponMap: Map<string, string>, itemsToAdd: Set<string>): void => {
|
||||||
|
for (const skinId of skins) {
|
||||||
|
if (skinId.startsWith("ca70ca70ca70ca70")) {
|
||||||
|
const typeName = skinLookupTable[parseInt(skinId.slice(16), 16)];
|
||||||
|
if (!weaponMap.has(typeName)) {
|
||||||
|
const { requirement } = ExportCustoms[typeName];
|
||||||
|
if (typeof requirement == "string") {
|
||||||
|
itemsToAdd.add(requirement);
|
||||||
|
} else {
|
||||||
|
itemsToAdd.add(typeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const replaceSkinIds = (skins: string[], weaponMap: Map<string, string>): void => {
|
||||||
|
for (let i = 0; i < skins.length; i++) {
|
||||||
|
const skinId = skins[i];
|
||||||
|
if (skinId.startsWith("ca70ca70ca70ca70")) {
|
||||||
|
const typeName = skinLookupTable[parseInt(skinId.slice(16), 16)];
|
||||||
|
const inventoryId = weaponMap.get(typeName);
|
||||||
|
if (inventoryId) {
|
||||||
|
skins[i] = inventoryId;
|
||||||
|
} else if (typeName in ExportCustoms) {
|
||||||
|
const { requirement } = ExportCustoms[typeName];
|
||||||
|
skins[i] = typeof requirement == "string" ? typeName : "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDialogue = (inventory: TInventoryDatabaseDocument, dialogueName: string): IDialogueDatabase => {
|
export const getDialogue = (inventory: TInventoryDatabaseDocument, dialogueName: string): IDialogueDatabase => {
|
||||||
|
|||||||
@ -210,10 +210,29 @@ export const addMissionInventoryUpdates = async (
|
|||||||
inventory.NemesisAbandonedRewards = inventoryUpdates.RewardInfo.NemesisAbandonedRewards;
|
inventory.NemesisAbandonedRewards = inventoryUpdates.RewardInfo.NemesisAbandonedRewards;
|
||||||
}
|
}
|
||||||
if (inventoryUpdates.RewardInfo.NemesisHenchmenKills && inventory.Nemesis) {
|
if (inventoryUpdates.RewardInfo.NemesisHenchmenKills && inventory.Nemesis) {
|
||||||
inventory.Nemesis.HenchmenKilled += inventoryUpdates.RewardInfo.NemesisHenchmenKills;
|
let HenchmenKilledMultiplier = 1;
|
||||||
|
switch (inventory.Nemesis.Faction) {
|
||||||
|
case "FC_GRINEER":
|
||||||
|
HenchmenKilledMultiplier = inventory.nemesisHenchmenKillsMultiplierGrineer ?? 1;
|
||||||
|
break;
|
||||||
|
case "FC_CORPUS":
|
||||||
|
HenchmenKilledMultiplier = inventory.nemesisHenchmenKillsMultiplierCorpus ?? 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
inventory.Nemesis.HenchmenKilled +=
|
||||||
|
inventoryUpdates.RewardInfo.NemesisHenchmenKills * HenchmenKilledMultiplier;
|
||||||
}
|
}
|
||||||
if (inventoryUpdates.RewardInfo.NemesisHintProgress && inventory.Nemesis) {
|
if (inventoryUpdates.RewardInfo.NemesisHintProgress && inventory.Nemesis) {
|
||||||
inventory.Nemesis.HintProgress += inventoryUpdates.RewardInfo.NemesisHintProgress;
|
let HintProgressMultiplier = 1;
|
||||||
|
switch (inventory.Nemesis.Faction) {
|
||||||
|
case "FC_GRINEER":
|
||||||
|
HintProgressMultiplier = inventory.nemesisHintProgressMultiplierGrineer ?? 1;
|
||||||
|
break;
|
||||||
|
case "FC_CORPUS":
|
||||||
|
HintProgressMultiplier = inventory.nemesisHintProgressMultiplierCorpus ?? 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
inventory.Nemesis.HintProgress += inventoryUpdates.RewardInfo.NemesisHintProgress * HintProgressMultiplier;
|
||||||
if (inventory.Nemesis.Faction != "FC_INFESTATION" && inventory.Nemesis.Hints.length != 3) {
|
if (inventory.Nemesis.Faction != "FC_INFESTATION" && inventory.Nemesis.Hints.length != 3) {
|
||||||
const progressNeeded = [35, 60, 100][inventory.Nemesis.Hints.length];
|
const progressNeeded = [35, 60, 100][inventory.Nemesis.Hints.length];
|
||||||
if (inventory.Nemesis.HintProgress >= progressNeeded) {
|
if (inventory.Nemesis.HintProgress >= progressNeeded) {
|
||||||
@ -290,9 +309,6 @@ export const addMissionInventoryUpdates = async (
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "Missions":
|
|
||||||
addMissionComplete(inventory, value);
|
|
||||||
break;
|
|
||||||
case "LastRegionPlayed":
|
case "LastRegionPlayed":
|
||||||
if (!(config.unfaithfulBugFixes?.ignore1999LastRegionPlayed && value === "1999MapName")) {
|
if (!(config.unfaithfulBugFixes?.ignore1999LastRegionPlayed && value === "1999MapName")) {
|
||||||
inventory.LastRegionPlayed = value;
|
inventory.LastRegionPlayed = value;
|
||||||
@ -819,6 +835,8 @@ export const addMissionInventoryUpdates = async (
|
|||||||
const att: string[] = [];
|
const att: string[] = [];
|
||||||
let countedAtt: ITypeCount[] | undefined;
|
let countedAtt: ITypeCount[] | undefined;
|
||||||
|
|
||||||
|
const extraWeaponCheat = inventory.nemesisExtraWeapon ?? 0; // 0 means no extra weapon and token
|
||||||
|
|
||||||
if (value.killed) {
|
if (value.killed) {
|
||||||
if (
|
if (
|
||||||
value.weaponLoc &&
|
value.weaponLoc &&
|
||||||
@ -827,6 +845,20 @@ export const addMissionInventoryUpdates = async (
|
|||||||
const weaponType = manifest.weapons[inventory.Nemesis.WeaponIdx];
|
const weaponType = manifest.weapons[inventory.Nemesis.WeaponIdx];
|
||||||
giveNemesisWeaponRecipe(inventory, weaponType, value.nemesisName, value.weaponLoc, profile);
|
giveNemesisWeaponRecipe(inventory, weaponType, value.nemesisName, value.weaponLoc, profile);
|
||||||
att.push(weaponType);
|
att.push(weaponType);
|
||||||
|
if (extraWeaponCheat >= 1) {
|
||||||
|
for (let i = 0; i < extraWeaponCheat; i++) {
|
||||||
|
const randomIndex = Math.floor(Math.random() * manifest.weapons.length);
|
||||||
|
const randomWeapon = manifest.weapons[randomIndex];
|
||||||
|
giveNemesisWeaponRecipe(
|
||||||
|
inventory,
|
||||||
|
randomWeapon,
|
||||||
|
value.nemesisName,
|
||||||
|
undefined,
|
||||||
|
profile
|
||||||
|
);
|
||||||
|
att.push(randomWeapon);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//if (value.petLoc) {
|
//if (value.petLoc) {
|
||||||
if (profile.petHead) {
|
if (profile.petHead) {
|
||||||
@ -870,7 +902,7 @@ export const addMissionInventoryUpdates = async (
|
|||||||
countedAtt = [
|
countedAtt = [
|
||||||
{
|
{
|
||||||
ItemType: "/Lotus/Types/Items/MiscItems/CodaWeaponBucks",
|
ItemType: "/Lotus/Types/Items/MiscItems/CodaWeaponBucks",
|
||||||
ItemCount: getKillTokenRewardCount(inventory.Nemesis.fp)
|
ItemCount: getKillTokenRewardCount(inventory.Nemesis.fp) * (extraWeaponCheat + 1)
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
addMiscItems(inventory, countedAtt);
|
addMiscItems(inventory, countedAtt);
|
||||||
@ -1119,6 +1151,27 @@ export const addMissionRewards = async (
|
|||||||
let ConquestCompletedMissionsCount;
|
let ConquestCompletedMissionsCount;
|
||||||
|
|
||||||
let missionCompletionCredits = 0;
|
let missionCompletionCredits = 0;
|
||||||
|
|
||||||
|
if (rewardInfo.alertId) {
|
||||||
|
const alert = getWorldState().Alerts.find(x => x._id.$oid == rewardInfo.alertId);
|
||||||
|
if (!alert) {
|
||||||
|
logger.warn(`mission completed unknown alert`, { alertId: rewardInfo.alertId });
|
||||||
|
} else {
|
||||||
|
if (inventory.CompletedAlerts.includes(alert._id.$oid)) {
|
||||||
|
logger.debug(`alert ${alert._id.$oid} already completed, skipping alert reward`);
|
||||||
|
} else {
|
||||||
|
inventory.CompletedAlerts.push(alert._id.$oid);
|
||||||
|
if (alert.MissionInfo.missionReward) {
|
||||||
|
missionCompletionCredits += addFixedLevelRewards(
|
||||||
|
alert.MissionInfo.missionReward,
|
||||||
|
MissionRewards,
|
||||||
|
rewardInfo
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//inventory change is what the client has not rewarded itself, also the client needs to know the credit changes for display
|
//inventory change is what the client has not rewarded itself, also the client needs to know the credit changes for display
|
||||||
|
|
||||||
if (rewardInfo.goalId) {
|
if (rewardInfo.goalId) {
|
||||||
@ -1173,6 +1226,9 @@ export const addMissionRewards = async (
|
|||||||
if (missions && missions.Tag in ExportRegions) {
|
if (missions && missions.Tag in ExportRegions) {
|
||||||
const node = ExportRegions[missions.Tag];
|
const node = ExportRegions[missions.Tag];
|
||||||
|
|
||||||
|
// cannot add this with normal updates because { Tier: 1 } would mark the SP node as completed even on a failure
|
||||||
|
addMissionComplete(inventory, missions);
|
||||||
|
|
||||||
//node based credit rewards for mission completion
|
//node based credit rewards for mission completion
|
||||||
if (isEligibleForCreditReward(rewardInfo, missions, node)) {
|
if (isEligibleForCreditReward(rewardInfo, missions, node)) {
|
||||||
const levelCreditReward = getLevelCreditRewards(node);
|
const levelCreditReward = getLevelCreditRewards(node);
|
||||||
@ -1299,13 +1355,21 @@ export const addMissionRewards = async (
|
|||||||
rngRewardCredits: inventoryChanges.RegularCredits ?? 0
|
rngRewardCredits: inventoryChanges.RegularCredits ?? 0
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (voidTearWave && voidTearWave.Participants[0].QualifiesForReward) {
|
||||||
voidTearWave &&
|
if (!voidTearWave.Participants[0].HaveRewardResponse) {
|
||||||
voidTearWave.Participants[0].QualifiesForReward &&
|
// non-endless fissure; giving reward now
|
||||||
!voidTearWave.Participants[0].HaveRewardResponse
|
const reward = await crackRelic(inventory, voidTearWave.Participants[0], inventoryChanges);
|
||||||
) {
|
MissionRewards.push({ StoreItem: reward.type, ItemCount: reward.itemCount });
|
||||||
const reward = await crackRelic(inventory, voidTearWave.Participants[0], inventoryChanges);
|
} else if (inventory.MissionRelicRewards) {
|
||||||
MissionRewards.push({ StoreItem: reward.type, ItemCount: reward.itemCount });
|
// endless fissure; already gave reward(s) but should still show in EOM screen
|
||||||
|
for (const reward of inventory.MissionRelicRewards) {
|
||||||
|
MissionRewards.push({
|
||||||
|
StoreItem: reward.ItemType,
|
||||||
|
ItemCount: reward.ItemCount
|
||||||
|
});
|
||||||
|
}
|
||||||
|
inventory.MissionRelicRewards = undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strippedItems) {
|
if (strippedItems) {
|
||||||
@ -1400,7 +1464,9 @@ export const addMissionRewards = async (
|
|||||||
|
|
||||||
if (inventory.Nemesis.Faction == "FC_INFESTATION") {
|
if (inventory.Nemesis.Faction == "FC_INFESTATION") {
|
||||||
inventory.Nemesis.MissionCount += 1;
|
inventory.Nemesis.MissionCount += 1;
|
||||||
inventory.Nemesis.HenchmenKilled = Math.min(inventory.Nemesis.HenchmenKilled + 5, 95); // 5 progress per mission until 95
|
let antivirusGain = 5;
|
||||||
|
antivirusGain *= inventory.nemesisAntivirusGainMultiplier ?? 1;
|
||||||
|
inventory.Nemesis.HenchmenKilled = Math.min(inventory.Nemesis.HenchmenKilled + antivirusGain, 95); // 5 progress per mission until 95
|
||||||
|
|
||||||
inventoryChanges.Nemesis.MissionCount ??= 0;
|
inventoryChanges.Nemesis.MissionCount ??= 0;
|
||||||
inventoryChanges.Nemesis.MissionCount += 1;
|
inventoryChanges.Nemesis.MissionCount += 1;
|
||||||
@ -2438,95 +2504,95 @@ const goalMessagesByKey: Record<string, { sndr: string; msg: string; sub: string
|
|||||||
icon: "/Lotus/Interface/Icons/Npcs/Seasonal/NoraNight.png"
|
icon: "/Lotus/Interface/Icons/Npcs/Seasonal/NoraNight.png"
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/LanternEndlessEventKeyA": {
|
"/Lotus/Types/Keys/LanternEndlessEventKeyA": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/G1Quests/GenericEventRewardMsgDesc",
|
msg: "/Lotus/Language/G1Quests/GenericEventRewardMsgDesc",
|
||||||
sub: "/Lotus/Language/G1Quests/GenericTacAlertRewardMsgTitle",
|
sub: "/Lotus/Language/G1Quests/GenericTacAlertRewardMsgTitle",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
|
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/LanternEndlessEventKeyB": {
|
"/Lotus/Types/Keys/LanternEndlessEventKeyB": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/G1Quests/GenericEventRewardMsgDesc",
|
msg: "/Lotus/Language/G1Quests/GenericEventRewardMsgDesc",
|
||||||
sub: "/Lotus/Language/G1Quests/GenericTacAlertRewardMsgTitle",
|
sub: "/Lotus/Language/G1Quests/GenericTacAlertRewardMsgTitle",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
|
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/LanternEndlessEventKeyD": {
|
"/Lotus/Types/Keys/LanternEndlessEventKeyD": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/G1Quests/GenericEventRewardMsgDesc",
|
msg: "/Lotus/Language/G1Quests/GenericEventRewardMsgDesc",
|
||||||
sub: "/Lotus/Language/G1Quests/GenericTacAlertRewardMsgTitle",
|
sub: "/Lotus/Language/G1Quests/GenericTacAlertRewardMsgTitle",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
|
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/LanternEndlessEventKeyC": {
|
"/Lotus/Types/Keys/LanternEndlessEventKeyC": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/G1Quests/GenericEventRewardMsgDesc",
|
msg: "/Lotus/Language/G1Quests/GenericEventRewardMsgDesc",
|
||||||
sub: "/Lotus/Language/G1Quests/GenericTacAlertRewardMsgTitle",
|
sub: "/Lotus/Language/G1Quests/GenericTacAlertRewardMsgTitle",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
|
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyHalloween": {
|
"/Lotus/Types/Keys/TacAlertKeyHalloween": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsBonusBody",
|
msg: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsBonusBody",
|
||||||
sub: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsBonusTitle",
|
sub: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsBonusTitle",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
|
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyHalloweenBonus": {
|
"/Lotus/Types/Keys/TacAlertKeyHalloweenBonus": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsBody",
|
msg: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsBody",
|
||||||
sub: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsTitle",
|
sub: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsTitle",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
|
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyHalloweenTimeAttack": {
|
"/Lotus/Types/Keys/TacAlertKeyHalloweenTimeAttack": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsBody",
|
msg: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsBody",
|
||||||
sub: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsTitle",
|
sub: "/Lotus/Language/G1Quests/TacAlertHalloweenRewardsTitle",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
|
icon: "/Lotus/Interface/Icons/Npcs/LotusVamp_d.png"
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyProxyRebellionOne": {
|
"/Lotus/Types/Keys/TacAlertKeyProxyRebellionOne": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/G1Quests/RazorbackArmadaRewardBody",
|
msg: "/Lotus/Language/G1Quests/RazorbackArmadaRewardBody",
|
||||||
sub: "/Lotus/Language/G1Quests/GenericTacAlertSmallRewardMsgTitle",
|
sub: "/Lotus/Language/G1Quests/GenericTacAlertSmallRewardMsgTitle",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["CREDIT_REWARD"]
|
arg: ["CREDIT_REWARD"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyProxyRebellionTwo": {
|
"/Lotus/Types/Keys/TacAlertKeyProxyRebellionTwo": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/G1Quests/RazorbackArmadaRewardBody",
|
msg: "/Lotus/Language/G1Quests/RazorbackArmadaRewardBody",
|
||||||
sub: "/Lotus/Language/G1Quests/GenericTacAlertSmallRewardMsgTitle",
|
sub: "/Lotus/Language/G1Quests/GenericTacAlertSmallRewardMsgTitle",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["CREDIT_REWARD"]
|
arg: ["CREDIT_REWARD"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyProxyRebellionThree": {
|
"/Lotus/Types/Keys/TacAlertKeyProxyRebellionThree": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/G1Quests/RazorbackArmadaRewardBody",
|
msg: "/Lotus/Language/G1Quests/RazorbackArmadaRewardBody",
|
||||||
sub: "/Lotus/Language/G1Quests/GenericTacAlertSmallRewardMsgTitle",
|
sub: "/Lotus/Language/G1Quests/GenericTacAlertSmallRewardMsgTitle",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["CREDIT_REWARD"]
|
arg: ["CREDIT_REWARD"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyProxyRebellionFour": {
|
"/Lotus/Types/Keys/TacAlertKeyProxyRebellionFour": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/G1Quests/GenericTacAlertBadgeRewardMsgDesc",
|
msg: "/Lotus/Language/G1Quests/GenericTacAlertBadgeRewardMsgDesc",
|
||||||
sub: "/Lotus/Language/G1Quests/GenericTacAlertBadgeRewardMsgTitle",
|
sub: "/Lotus/Language/G1Quests/GenericTacAlertBadgeRewardMsgTitle",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyProjectNightwatchEasy": {
|
"/Lotus/Types/Keys/TacAlertKeyProjectNightwatchEasy": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/G1Quests/ProjectNightwatchRewardMsgA",
|
msg: "/Lotus/Language/G1Quests/ProjectNightwatchRewardMsgA",
|
||||||
sub: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionOneTitle",
|
sub: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionOneTitle",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["CREDIT_REWARD"]
|
arg: ["CREDIT_REWARD"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyProjectNightwatch": {
|
"/Lotus/Types/Keys/TacAlertKeyProjectNightwatch": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionRewardBody",
|
msg: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionRewardBody",
|
||||||
sub: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionTwoTitle",
|
sub: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionTwoTitle",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyProjectNightwatchHard": {
|
"/Lotus/Types/Keys/TacAlertKeyProjectNightwatchHard": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionRewardBody",
|
msg: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionRewardBody",
|
||||||
sub: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionThreeTitle",
|
sub: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionThreeTitle",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyProjectNightwatchBonus": {
|
"/Lotus/Types/Keys/TacAlertKeyProjectNightwatchBonus": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionRewardBody",
|
msg: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionRewardBody",
|
||||||
sub: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionFourTitle",
|
sub: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionFourTitle",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
|
||||||
@ -2562,140 +2628,140 @@ const goalMessagesByKey: Record<string, { sndr: string; msg: string; sub: string
|
|||||||
icon: "/Lotus/Interface/Icons/Npcs/Entrati/Father.png"
|
icon: "/Lotus/Interface/Icons/Npcs/Entrati/Father.png"
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2019E": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2019E": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgB",
|
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgB",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleB",
|
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleB",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2020F": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2020F": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgC",
|
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgC",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleB",
|
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleB",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2024ChallengeModeA": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2024ChallengeModeA": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgD",
|
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgD",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleD",
|
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleD",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2017C": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2017C": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2019RewardMsgC",
|
msg: "/Lotus/Language/Messages/Anniversary2019RewardMsgC",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2019MissionTitleC",
|
sub: "/Lotus/Language/Messages/Anniversary2019MissionTitleC",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2020H": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2020H": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2020RewardMsgH",
|
msg: "/Lotus/Language/Messages/Anniversary2020RewardMsgH",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2020MissionTitleH",
|
sub: "/Lotus/Language/Messages/Anniversary2020MissionTitleH",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2022J": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2022J": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2022RewardMsgJ",
|
msg: "/Lotus/Language/Messages/Anniversary2022RewardMsgJ",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2022MissionTitleJ",
|
sub: "/Lotus/Language/Messages/Anniversary2022MissionTitleJ",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025D": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025D": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgB",
|
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgB",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleB",
|
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleB",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025ChallengeModeA": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025ChallengeModeA": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgC",
|
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgC",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleC",
|
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleC",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2020G": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2020G": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2020RewardMsgG",
|
msg: "/Lotus/Language/Messages/Anniversary2020RewardMsgG",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2020MissionTitleG",
|
sub: "/Lotus/Language/Messages/Anniversary2020MissionTitleG",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2017B": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2017B": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2019RewardMsgB",
|
msg: "/Lotus/Language/Messages/Anniversary2019RewardMsgB",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2019MissionTitleB",
|
sub: "/Lotus/Language/Messages/Anniversary2019MissionTitleB",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2017A": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2017A": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2019RewardMsgA",
|
msg: "/Lotus/Language/Messages/Anniversary2019RewardMsgA",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2019MissionTitleA",
|
sub: "/Lotus/Language/Messages/Anniversary2019MissionTitleA",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2023K": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2023K": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgG",
|
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgG",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleG",
|
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleG",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025ChallengeModeB": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025ChallengeModeB": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgD",
|
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgD",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleD",
|
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleD",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025A": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025A": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgA",
|
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgA",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleA",
|
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleA",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2018D": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2018D": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgG",
|
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgG",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleG",
|
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleG",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025C": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025C": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgF",
|
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgF",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleF",
|
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleF",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2024L": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2024L": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgA",
|
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgA",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleA",
|
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleA",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2024ChallengeModeB": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2024ChallengeModeB": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgE",
|
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgE",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleE",
|
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleE",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2021I": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2021I": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgH",
|
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgH",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleH",
|
sub: "/Lotus/Language/Messages/Anniversary2024MissionTitleH",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
arg: ["PLAYER_NAME"]
|
arg: ["PLAYER_NAME"]
|
||||||
},
|
},
|
||||||
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025B": {
|
"/Lotus/Types/Keys/TacAlertKeyAnniversary2025B": {
|
||||||
sndr: "/Lotus/Language/Bosses/Lotus",
|
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||||
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgE",
|
msg: "/Lotus/Language/Messages/Anniversary2025RewardMsgE",
|
||||||
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleE",
|
sub: "/Lotus/Language/Messages/Anniversary2025MissionTitleE",
|
||||||
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
|
||||||
|
|||||||
@ -74,7 +74,7 @@ export const updateQuestStage = (
|
|||||||
if (!questStage) {
|
if (!questStage) {
|
||||||
const questStageIndex =
|
const questStageIndex =
|
||||||
quest.Progress.push({
|
quest.Progress.push({
|
||||||
c: questStageUpdate.c ?? 0,
|
c: questStageUpdate.c ?? -1,
|
||||||
i: questStageUpdate.i ?? false,
|
i: questStageUpdate.i ?? false,
|
||||||
m: questStageUpdate.m ?? false,
|
m: questStageUpdate.m ?? false,
|
||||||
b: questStageUpdate.b ?? []
|
b: questStageUpdate.b ?? []
|
||||||
@ -331,7 +331,7 @@ export const giveKeyChainMessage = async (
|
|||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const keyChainMessage = getKeyChainMessage(keyChainInfo);
|
const keyChainMessage = getKeyChainMessage(keyChainInfo);
|
||||||
|
|
||||||
if (questKey.Progress![0].c > 0) {
|
if ((questKey.Progress?.[0]?.c ?? 0) > 0) {
|
||||||
keyChainMessage.att = [];
|
keyChainMessage.att = [];
|
||||||
keyChainMessage.countedAtt = [];
|
keyChainMessage.countedAtt = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import type {
|
|||||||
ICalendarDay,
|
ICalendarDay,
|
||||||
ICalendarEvent,
|
ICalendarEvent,
|
||||||
ICalendarSeason,
|
ICalendarSeason,
|
||||||
|
IAlert,
|
||||||
IGoal,
|
IGoal,
|
||||||
IInvasion,
|
IInvasion,
|
||||||
ILiteSortie,
|
ILiteSortie,
|
||||||
@ -112,6 +113,89 @@ const sortieBossNode: Record<Exclude<TSortieBoss, "SORTIE_BOSS_CORRUPTED_VOR">,
|
|||||||
SORTIE_BOSS_VOR: "SolNode108"
|
SORTIE_BOSS_VOR: "SolNode108"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const configAlerts: Record<string, IAlert> = {
|
||||||
|
voidCorruption2025Week1: {
|
||||||
|
_id: { $oid: "677d452e2f324ee7b90f8ccf" },
|
||||||
|
Activation: { $date: { $numberLong: "1736524800000" } },
|
||||||
|
Expiry: { $date: { $numberLong: "2000000000000" } },
|
||||||
|
MissionInfo: {
|
||||||
|
location: "SolNode61",
|
||||||
|
missionType: "MT_SABOTAGE",
|
||||||
|
faction: "FC_CORPUS",
|
||||||
|
difficulty: 1,
|
||||||
|
missionReward: {
|
||||||
|
credits: 30000,
|
||||||
|
items: ["/Lotus/StoreItems/Upgrades/Mods/Pistol/DualStat/CorruptedFireRateDamagePistol"]
|
||||||
|
},
|
||||||
|
levelOverride: "/Lotus/Levels/Proc/Corpus/CorpusShipCoreSabotage",
|
||||||
|
enemySpec: "/Lotus/Types/Game/EnemySpecs/CorpusShipEnemySpecs/CorpusShipSquadA",
|
||||||
|
extraEnemySpec: "/Lotus/Types/Game/EnemySpecs/GamemodeExtraEnemySpecs/CorpusSabotageTiersA",
|
||||||
|
minEnemyLevel: 10,
|
||||||
|
maxEnemyLevel: 15
|
||||||
|
}
|
||||||
|
},
|
||||||
|
voidCorruption2025Week2: {
|
||||||
|
_id: { $oid: "677d45811daeae9de40e8c0f" },
|
||||||
|
Activation: { $date: { $numberLong: "1737129600000" } },
|
||||||
|
Expiry: { $date: { $numberLong: "2000000000000" } },
|
||||||
|
MissionInfo: {
|
||||||
|
location: "SettlementNode11",
|
||||||
|
missionType: "MT_DEFENSE",
|
||||||
|
faction: "FC_CORPUS",
|
||||||
|
difficulty: 1,
|
||||||
|
missionReward: {
|
||||||
|
credits: 30000,
|
||||||
|
items: ["/Lotus/StoreItems/Upgrades/Mods/Pistol/DualStat/CorruptedCritChanceFireRatePistol"]
|
||||||
|
},
|
||||||
|
levelOverride: "/Lotus/Levels/Proc/Corpus/CorpusShipDefense",
|
||||||
|
enemySpec: "/Lotus/Types/Game/EnemySpecs/CorpusShipEnemySpecs/CorpusShipSquadDefenseB",
|
||||||
|
minEnemyLevel: 20,
|
||||||
|
maxEnemyLevel: 25,
|
||||||
|
maxRotations: 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
voidCorruption2025Week3: {
|
||||||
|
_id: { $oid: "677d45a494ad716c90006b9a" },
|
||||||
|
Activation: { $date: { $numberLong: "1737734400000" } },
|
||||||
|
Expiry: { $date: { $numberLong: "2000000000000" } },
|
||||||
|
MissionInfo: {
|
||||||
|
location: "SolNode118",
|
||||||
|
missionType: "MT_ARTIFACT",
|
||||||
|
faction: "FC_CORPUS",
|
||||||
|
difficulty: 1,
|
||||||
|
missionReward: {
|
||||||
|
credits: 30000,
|
||||||
|
items: ["/Lotus/StoreItems/Upgrades/Mods/Pistol/DualStat/CorruptedCritDamagePistol"]
|
||||||
|
},
|
||||||
|
levelOverride: "/Lotus/Levels/Proc/Corpus/CorpusShipDisruption",
|
||||||
|
enemySpec: "/Lotus/Types/Game/EnemySpecs/CorpusShipEnemySpecs/CorpusShipSurvivalA",
|
||||||
|
extraEnemySpec: "/Lotus/Types/Game/EnemySpecs/SpecialMissionSpecs/DisruptionCorpusShip",
|
||||||
|
customAdvancedSpawners: ["/Lotus/Types/Enemies/AdvancedSpawners/ErrantSpecterInvasion"],
|
||||||
|
minEnemyLevel: 30,
|
||||||
|
maxEnemyLevel: 35
|
||||||
|
}
|
||||||
|
},
|
||||||
|
voidCorruption2025Week4: {
|
||||||
|
_id: { $oid: "677d4700682d173abb0e19fe" },
|
||||||
|
Activation: { $date: { $numberLong: "1738339200000" } },
|
||||||
|
Expiry: { $date: { $numberLong: "2000000000000" } },
|
||||||
|
MissionInfo: {
|
||||||
|
location: "SolNode4",
|
||||||
|
missionType: "MT_EXTERMINATION",
|
||||||
|
faction: "FC_CORPUS",
|
||||||
|
difficulty: 1,
|
||||||
|
missionReward: {
|
||||||
|
credits: 30000,
|
||||||
|
items: ["/Lotus/StoreItems/Upgrades/Mods/Pistol/DualStat/CorruptedDamageRecoilPistol"]
|
||||||
|
},
|
||||||
|
levelOverride: "/Lotus/Levels/Proc/Corpus/CorpusShipExterminate",
|
||||||
|
enemySpec: "/Lotus/Types/Game/EnemySpecs/CorpusShipEnemySpecs/CorpusShipExterminateMixed",
|
||||||
|
minEnemyLevel: 40,
|
||||||
|
maxEnemyLevel: 45
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const eidolonJobs: readonly string[] = [
|
const eidolonJobs: readonly string[] = [
|
||||||
"/Lotus/Types/Gameplay/Eidolon/Jobs/AssassinateBountyAss",
|
"/Lotus/Types/Gameplay/Eidolon/Jobs/AssassinateBountyAss",
|
||||||
"/Lotus/Types/Gameplay/Eidolon/Jobs/AssassinateBountyCap",
|
"/Lotus/Types/Gameplay/Eidolon/Jobs/AssassinateBountyCap",
|
||||||
@ -280,6 +364,14 @@ export const getSortie = (day: number): ISortie => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const willHaveAssassination = boss != "SORTIE_BOSS_CORRUPTED_VOR" && rng.randomInt(0, 2) == 2;
|
||||||
|
if (willHaveAssassination) {
|
||||||
|
const index = nodes.indexOf(sortieBossNode[boss]);
|
||||||
|
if (index != -1) {
|
||||||
|
nodes.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const selectedNodes: ISortieMission[] = [];
|
const selectedNodes: ISortieMission[] = [];
|
||||||
const missionTypes = new Set();
|
const missionTypes = new Set();
|
||||||
|
|
||||||
@ -309,7 +401,7 @@ export const getSortie = (day: number): ISortie => {
|
|||||||
"SORTIE_MODIFIER_BOW_ONLY"
|
"SORTIE_MODIFIER_BOW_ONLY"
|
||||||
];
|
];
|
||||||
|
|
||||||
if (i == 2 && boss != "SORTIE_BOSS_CORRUPTED_VOR" && rng.randomInt(0, 2) == 2) {
|
if (i == 2 && willHaveAssassination) {
|
||||||
const tileset = sortieTilesets[sortieBossNode[boss] as keyof typeof sortieTilesets] as TSortieTileset;
|
const tileset = sortieTilesets[sortieBossNode[boss] as keyof typeof sortieTilesets] as TSortieTileset;
|
||||||
pushTilesetModifiers(modifiers, tileset);
|
pushTilesetModifiers(modifiers, tileset);
|
||||||
|
|
||||||
@ -361,7 +453,9 @@ export const getSortie = (day: number): ISortie => {
|
|||||||
Activation: { $date: { $numberLong: dayStart.toString() } },
|
Activation: { $date: { $numberLong: dayStart.toString() } },
|
||||||
Expiry: { $date: { $numberLong: dayEnd.toString() } },
|
Expiry: { $date: { $numberLong: dayEnd.toString() } },
|
||||||
Reward: "/Lotus/Types/Game/MissionDecks/SortieRewards",
|
Reward: "/Lotus/Types/Game/MissionDecks/SortieRewards",
|
||||||
Seed: seed,
|
Seed: selectedNodes.find(x => x.tileset == "CorpusIcePlanetTileset")
|
||||||
|
? 2081 // this seed produces 12 zeroes in a row if asked to pick (0, 1); this way the CorpusIcePlanetTileset image is always index 0, the 'correct' choice.
|
||||||
|
: seed,
|
||||||
Boss: boss,
|
Boss: boss,
|
||||||
Variants: selectedNodes
|
Variants: selectedNodes
|
||||||
};
|
};
|
||||||
@ -1382,6 +1476,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
const weekStart = EPOCH + week * 604800000;
|
const weekStart = EPOCH + week * 604800000;
|
||||||
const weekEnd = weekStart + 604800000;
|
const weekEnd = weekStart + 604800000;
|
||||||
const date = new Date(timeMs);
|
const date = new Date(timeMs);
|
||||||
|
const defenseWavesPerRotation = buildLabel && version_compare(buildLabel, "2025.03.18.16.07") < 0 ? 5 : 3;
|
||||||
|
|
||||||
const worldState: IWorldState = {
|
const worldState: IWorldState = {
|
||||||
BuildLabel: typeof buildLabel == "string" ? buildLabel.split(" ").join("+") : buildConfig.buildLabel,
|
BuildLabel: typeof buildLabel == "string" ? buildLabel.split(" ").join("+") : buildConfig.buildLabel,
|
||||||
@ -1471,6 +1566,123 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
worldState.VoidTraders.push(vt);
|
worldState.VoidTraders.push(vt);
|
||||||
fullyStockBaro(vt);
|
fullyStockBaro(vt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.worldState) {
|
||||||
|
for (const [key, alert] of Object.entries(configAlerts)) {
|
||||||
|
if (config.worldState[key as keyof typeof config.worldState]) {
|
||||||
|
if (alert.MissionInfo.missionType == "MT_DEFENSE") {
|
||||||
|
alert.MissionInfo.maxWaveNum = defenseWavesPerRotation * (alert.MissionInfo.maxRotations ?? 1);
|
||||||
|
alert.MissionInfo.maxRotations = undefined;
|
||||||
|
}
|
||||||
|
worldState.Alerts.push(alert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.worldState?.qtccAlerts) {
|
||||||
|
worldState.Alerts.push(
|
||||||
|
{
|
||||||
|
_id: {
|
||||||
|
$oid: "68dc23c42e9d3acfa708ff3b"
|
||||||
|
},
|
||||||
|
Activation: {
|
||||||
|
$date: {
|
||||||
|
$numberLong: "1759327200000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Expiry: {
|
||||||
|
$date: {
|
||||||
|
$numberLong: "2000000000000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MissionInfo: {
|
||||||
|
location: "SolNode123",
|
||||||
|
missionType: "MT_SURVIVAL",
|
||||||
|
faction: "FC_CORPUS",
|
||||||
|
difficulty: 1,
|
||||||
|
missionReward: {
|
||||||
|
credits: 10000,
|
||||||
|
items: ["/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/Plushy2021QTCC"]
|
||||||
|
},
|
||||||
|
levelOverride: "/Lotus/Levels/Proc/Corpus/CorpusShipSurvivalRaid",
|
||||||
|
enemySpec: "/Lotus/Types/Game/EnemySpecs/CorpusShipEnemySpecs/CorpusShipSurvivalA",
|
||||||
|
minEnemyLevel: 20,
|
||||||
|
maxEnemyLevel: 30,
|
||||||
|
descText: "/Lotus/Language/Alerts/TennoUnitedAlert",
|
||||||
|
maxWaveNum: 5
|
||||||
|
},
|
||||||
|
Tag: "LotusGift",
|
||||||
|
ForceUnlock: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_id: {
|
||||||
|
$oid: "68dc2466e298b4f04206687a"
|
||||||
|
},
|
||||||
|
Activation: {
|
||||||
|
$date: {
|
||||||
|
$numberLong: "1759327200000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Expiry: {
|
||||||
|
$date: {
|
||||||
|
$numberLong: "2000000000000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MissionInfo: {
|
||||||
|
location: "SolNode149",
|
||||||
|
missionType: "MT_DEFENSE",
|
||||||
|
faction: "FC_GRINEER",
|
||||||
|
difficulty: 1,
|
||||||
|
missionReward: {
|
||||||
|
credits: 10000,
|
||||||
|
items: ["/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/Plushy2022QTCC"]
|
||||||
|
},
|
||||||
|
levelOverride: "/Lotus/Levels/Proc/Grineer/GrineerShipyardsDefense",
|
||||||
|
enemySpec: "/Lotus/Types/Game/EnemySpecs/GrineerShipyardsDefenseA",
|
||||||
|
minEnemyLevel: 20,
|
||||||
|
maxEnemyLevel: 30,
|
||||||
|
descText: "/Lotus/Language/Alerts/TennoUnitedAlert",
|
||||||
|
maxWaveNum: defenseWavesPerRotation * 1
|
||||||
|
},
|
||||||
|
Tag: "LotusGift",
|
||||||
|
ForceUnlock: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_id: {
|
||||||
|
$oid: "68dc26865e7cb56b820b4252"
|
||||||
|
},
|
||||||
|
Activation: {
|
||||||
|
$date: {
|
||||||
|
$numberLong: "1759327200000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Expiry: {
|
||||||
|
$date: {
|
||||||
|
$numberLong: "2000000000000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MissionInfo: {
|
||||||
|
location: "SolNode39",
|
||||||
|
missionType: "MT_EXCAVATE",
|
||||||
|
faction: "FC_GRINEER",
|
||||||
|
difficulty: 1,
|
||||||
|
missionReward: {
|
||||||
|
credits: 10000,
|
||||||
|
items: ["/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyVirminkQTCC"]
|
||||||
|
},
|
||||||
|
levelOverride: "/Lotus/Levels/Proc/Grineer/GrineerForestExcavation",
|
||||||
|
enemySpec: "/Lotus/Types/Game/EnemySpecs/ForestGrineerExcavationA",
|
||||||
|
minEnemyLevel: 20,
|
||||||
|
maxEnemyLevel: 30,
|
||||||
|
descText: "/Lotus/Language/Alerts/TennoUnitedAlert",
|
||||||
|
maxWaveNum: 5
|
||||||
|
},
|
||||||
|
Tag: "LotusGift",
|
||||||
|
ForceUnlock: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const isFebruary = date.getUTCMonth() == 1;
|
const isFebruary = date.getUTCMonth() == 1;
|
||||||
if (config.worldState?.starDaysOverride ?? isFebruary) {
|
if (config.worldState?.starDaysOverride ?? isFebruary) {
|
||||||
worldState.Goals.push({
|
worldState.Goals.push({
|
||||||
@ -2306,22 +2518,22 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
// 2016
|
// 2016
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
items: ["/Lotus/StoreItems/Upgrades/Skins/Sigils/OrokinCatalyst"]
|
items: ["/Lotus/StoreItems/Types/Items/MiscItems/OrokinCatalyst"]
|
||||||
},
|
|
||||||
{
|
|
||||||
items: ["/Lotus/StoreItems/Upgrades/Skins/Sigils/DotD2016Sigil"]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
items: [
|
items: [
|
||||||
"/Lotus/StoreItems/Types/Items/MiscItems/OrokinReactor",
|
"/Lotus/StoreItems/Upgrades/Skins/Sigils/DotD2016Sigil",
|
||||||
"/Lotus/StoreItems/Upgrades/Skins/Clan/BountyHunterBadgeItem"
|
"/Lotus/StoreItems/Upgrades/Skins/Clan/BountyHunterBadgeItem"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
items: ["/Lotus/StoreItems/Types/Items/MiscItems/OrokinReactor"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
// 2015
|
// 2015
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
items: ["/Lotus/StoreItems/Upgrades/Skins/Sigils/OrokinCatalyst"]
|
items: ["/Lotus/StoreItems/Types/Items/MiscItems/OrokinCatalyst"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
items: ["/Lotus/StoreItems/Upgrades/Skins/Clan/BountyHunterBadgeItem"]
|
items: ["/Lotus/StoreItems/Upgrades/Skins/Clan/BountyHunterBadgeItem"]
|
||||||
@ -2504,6 +2716,37 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
BonusReward: { items: ["/Lotus/StoreItems/Upgrades/Skins/Clan/BountyHunterBadgeItem"] }
|
BonusReward: { items: ["/Lotus/StoreItems/Upgrades/Skins/Clan/BountyHunterBadgeItem"] }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isOctober = date.getUTCMonth() == 9; // October = month index 9
|
||||||
|
if (config.worldState?.naberusNightsOverride ?? isOctober) {
|
||||||
|
worldState.Goals.push({
|
||||||
|
_id: { $oid: "66fd602de1778d583419e8e7" },
|
||||||
|
Activation: {
|
||||||
|
$date: {
|
||||||
|
$numberLong: config.worldState?.naberusNightsOverride
|
||||||
|
? "1727881200000"
|
||||||
|
: Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1).toString()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Expiry: {
|
||||||
|
$date: {
|
||||||
|
$numberLong: config.worldState?.naberusNightsOverride
|
||||||
|
? "2000000000000"
|
||||||
|
: Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 1).toString()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Count: 0,
|
||||||
|
Goal: 0,
|
||||||
|
Success: 0,
|
||||||
|
Personal: true,
|
||||||
|
Desc: "/Lotus/Language/Events/HalloweenNaberusName",
|
||||||
|
ToolTip: "/Lotus/Language/Events/HalloweenNaberusDesc",
|
||||||
|
Icon: "/Lotus/Interface/Icons/JackOLanternColour.png",
|
||||||
|
Tag: "DeimosHalloween",
|
||||||
|
Node: "DeimosHub"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (config.worldState?.bellyOfTheBeast) {
|
if (config.worldState?.bellyOfTheBeast) {
|
||||||
worldState.Goals.push({
|
worldState.Goals.push({
|
||||||
_id: { $oid: "67a5035c2a198564d62e165e" },
|
_id: { $oid: "67a5035c2a198564d62e165e" },
|
||||||
|
|||||||
@ -55,6 +55,12 @@ export interface IAccountCheats {
|
|||||||
flawlessRelicsAlwaysGiveSilverReward?: boolean;
|
flawlessRelicsAlwaysGiveSilverReward?: boolean;
|
||||||
radiantRelicsAlwaysGiveGoldReward?: boolean;
|
radiantRelicsAlwaysGiveGoldReward?: boolean;
|
||||||
disableDailyTribute?: boolean;
|
disableDailyTribute?: boolean;
|
||||||
|
nemesisHenchmenKillsMultiplierGrineer?: number;
|
||||||
|
nemesisHenchmenKillsMultiplierCorpus?: number;
|
||||||
|
nemesisAntivirusGainMultiplier?: number;
|
||||||
|
nemesisHintProgressMultiplierGrineer?: number;
|
||||||
|
nemesisHintProgressMultiplierCorpus?: number;
|
||||||
|
nemesisExtraWeapon?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IInventoryDatabase
|
export interface IInventoryDatabase
|
||||||
@ -86,6 +92,7 @@ export interface IInventoryDatabase
|
|||||||
| "NextRefill"
|
| "NextRefill"
|
||||||
| "Nemesis"
|
| "Nemesis"
|
||||||
| "NemesisHistory"
|
| "NemesisHistory"
|
||||||
|
| "LastNemesisAllySpawnTime"
|
||||||
| "EntratiVaultCountResetDate"
|
| "EntratiVaultCountResetDate"
|
||||||
| "BrandedSuits"
|
| "BrandedSuits"
|
||||||
| "LockedWeaponGroup"
|
| "LockedWeaponGroup"
|
||||||
@ -130,6 +137,7 @@ export interface IInventoryDatabase
|
|||||||
NextRefill?: Date;
|
NextRefill?: Date;
|
||||||
Nemesis?: INemesisDatabase;
|
Nemesis?: INemesisDatabase;
|
||||||
NemesisHistory?: INemesisBaseDatabase[];
|
NemesisHistory?: INemesisBaseDatabase[];
|
||||||
|
LastNemesisAllySpawnTime?: Date;
|
||||||
EntratiVaultCountResetDate?: Date;
|
EntratiVaultCountResetDate?: Date;
|
||||||
BrandedSuits?: Types.ObjectId[];
|
BrandedSuits?: Types.ObjectId[];
|
||||||
LockedWeaponGroup?: ILockedWeaponGroupDatabase;
|
LockedWeaponGroup?: ILockedWeaponGroupDatabase;
|
||||||
@ -141,6 +149,7 @@ export interface IInventoryDatabase
|
|||||||
LastInventorySync?: Types.ObjectId;
|
LastInventorySync?: Types.ObjectId;
|
||||||
EndlessXP?: IEndlessXpProgressDatabase[];
|
EndlessXP?: IEndlessXpProgressDatabase[];
|
||||||
PersonalGoalProgress?: IGoalProgressDatabase[];
|
PersonalGoalProgress?: IGoalProgressDatabase[];
|
||||||
|
MissionRelicRewards?: ITypeCount[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IQuestKeyDatabase {
|
export interface IQuestKeyDatabase {
|
||||||
@ -353,7 +362,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
|
|||||||
ThemeStyle: string;
|
ThemeStyle: string;
|
||||||
ThemeBackground: string;
|
ThemeBackground: string;
|
||||||
ThemeSounds: string;
|
ThemeSounds: string;
|
||||||
BountyScore: number;
|
BountyScore?: number;
|
||||||
//ChallengeInstanceStates: IChallengeInstanceState[];
|
//ChallengeInstanceStates: IChallengeInstanceState[];
|
||||||
LoginMilestoneRewards: string[];
|
LoginMilestoneRewards: string[];
|
||||||
RecentVendorPurchases?: IRecentVendorPurchaseClient[];
|
RecentVendorPurchases?: IRecentVendorPurchaseClient[];
|
||||||
@ -365,7 +374,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
|
|||||||
//InvasionChainProgress: IInvasionChainProgress[];
|
//InvasionChainProgress: IInvasionChainProgress[];
|
||||||
Nemesis?: INemesisClient;
|
Nemesis?: INemesisClient;
|
||||||
NemesisHistory?: INemesisBaseClient[];
|
NemesisHistory?: INemesisBaseClient[];
|
||||||
//LastNemesisAllySpawnTime?: IMongoDate;
|
LastNemesisAllySpawnTime?: IMongoDate;
|
||||||
Settings?: ISettings;
|
Settings?: ISettings;
|
||||||
PersonalTechProjects: IPersonalTechProjectClient[];
|
PersonalTechProjects: IPersonalTechProjectClient[];
|
||||||
PlayerSkills: IPlayerSkills;
|
PlayerSkills: IPlayerSkills;
|
||||||
|
|||||||
@ -178,6 +178,7 @@ export interface IRewardInfo {
|
|||||||
goalManifest?: string;
|
goalManifest?: string;
|
||||||
invasionId?: string;
|
invasionId?: string;
|
||||||
invasionAllyFaction?: "FC_GRINEER" | "FC_CORPUS";
|
invasionAllyFaction?: "FC_GRINEER" | "FC_CORPUS";
|
||||||
|
alertId?: string;
|
||||||
sortieId?: string;
|
sortieId?: string;
|
||||||
sortieTag?: "Mission1" | "Mission2" | "Final";
|
sortieTag?: "Mission1" | "Mission2" | "Final";
|
||||||
sortiePrereqs?: string[];
|
sortiePrereqs?: string[];
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import type { IMissionReward } from "warframe-public-export-plus";
|
import type { IMissionReward, TFaction, TMissionType } from "warframe-public-export-plus";
|
||||||
import type { IMongoDate, IOid } from "./commonTypes.ts";
|
import type { IMongoDate, IOid } from "./commonTypes.ts";
|
||||||
|
|
||||||
export interface IWorldState {
|
export interface IWorldState {
|
||||||
@ -7,7 +7,7 @@ export interface IWorldState {
|
|||||||
Time: number;
|
Time: number;
|
||||||
InGameMarket: IInGameMarket;
|
InGameMarket: IInGameMarket;
|
||||||
Goals: IGoal[];
|
Goals: IGoal[];
|
||||||
Alerts: [];
|
Alerts: IAlert[];
|
||||||
Sorties: ISortie[];
|
Sorties: ISortie[];
|
||||||
LiteSorties: ILiteSortie[];
|
LiteSorties: ILiteSortie[];
|
||||||
SyndicateMissions: ISyndicateMissionInfo[];
|
SyndicateMissions: ISyndicateMissionInfo[];
|
||||||
@ -35,6 +35,33 @@ export interface IWorldState {
|
|||||||
Tmp?: string;
|
Tmp?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IAlert {
|
||||||
|
_id: IOid;
|
||||||
|
Activation: IMongoDate;
|
||||||
|
Expiry: IMongoDate;
|
||||||
|
MissionInfo: IAlertMissionInfo;
|
||||||
|
Tag?: string;
|
||||||
|
ForceUnlock?: true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAlertMissionInfo {
|
||||||
|
location: string;
|
||||||
|
missionType: TMissionType;
|
||||||
|
faction: TFaction;
|
||||||
|
difficulty: number;
|
||||||
|
missionReward?: IMissionReward;
|
||||||
|
levelOverride?: string;
|
||||||
|
enemySpec?: string;
|
||||||
|
extraEnemySpec?: string;
|
||||||
|
customAdvancedSpawners?: string[];
|
||||||
|
minEnemyLevel?: number;
|
||||||
|
maxEnemyLevel?: number;
|
||||||
|
maxWaveNum?: number;
|
||||||
|
descText?: string;
|
||||||
|
|
||||||
|
maxRotations?: number; // SNS specific field
|
||||||
|
}
|
||||||
|
|
||||||
export interface IGoal {
|
export interface IGoal {
|
||||||
_id: IOid;
|
_id: IOid;
|
||||||
Activation: IMongoDate;
|
Activation: IMongoDate;
|
||||||
|
|||||||
@ -476,9 +476,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card" style="height: 400px;">
|
<div class="card" style="height: 400px;">
|
||||||
<h5 class="card-header" data-loc="inventory_Boosters"></h5>
|
<h5 class="card-header" data-loc="inventory_boosters"></h5>
|
||||||
<div class="card-body d-flex flex-column">
|
<div class="card-body d-flex flex-column">
|
||||||
<form class="input-group mb-3" onsubmit="doAcquireBoosters();return false;">
|
<form class="input-group mb-3" onsubmit="doAcquireBooster();return false;">
|
||||||
<input class="form-control" id="acquire-type-Boosters" list="datalist-Boosters" />
|
<input class="form-control" id="acquire-type-Boosters" list="datalist-Boosters" />
|
||||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||||
</form>
|
</form>
|
||||||
@ -526,6 +526,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="card" style="height: 400px;">
|
||||||
|
<h5 class="card-header" data-loc="inventory_weaponSkins"></h5>
|
||||||
|
<div class="card-body d-flex flex-column">
|
||||||
|
<form class="input-group mb-3" onsubmit="doAcquireEquipment('WeaponSkins');return false;">
|
||||||
|
<input class="form-control" id="acquire-type-WeaponSkins" list="datalist-WeaponSkins" />
|
||||||
|
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||||
|
</form>
|
||||||
|
<div class="overflow-auto">
|
||||||
|
<table class="table table-hover w-100">
|
||||||
|
<tbody id="WeaponSkins-list"></tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h5 class="card-header" data-loc="general_bulkActions"></h5>
|
<h5 class="card-header" data-loc="general_bulkActions"></h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -538,6 +556,7 @@
|
|||||||
<button class="btn btn-primary" onclick="debounce(addMissingEquipment, ['SentinelWeapons']);" data-loc="inventory_bulkAddSentinelWeapons"></button>
|
<button class="btn btn-primary" onclick="debounce(addMissingEquipment, ['SentinelWeapons']);" data-loc="inventory_bulkAddSentinelWeapons"></button>
|
||||||
<button class="btn btn-primary" onclick="debounce(addMissingEquipment, ['FlavourItems']);" data-loc="inventory_bulkAddFlavourItems"></button>
|
<button class="btn btn-primary" onclick="debounce(addMissingEquipment, ['FlavourItems']);" data-loc="inventory_bulkAddFlavourItems"></button>
|
||||||
<button class="btn btn-primary" onclick="debounce(addMissingEquipment, ['ShipDecorations']);" data-loc="inventory_bulkAddShipDecorations"></button>
|
<button class="btn btn-primary" onclick="debounce(addMissingEquipment, ['ShipDecorations']);" data-loc="inventory_bulkAddShipDecorations"></button>
|
||||||
|
<button class="btn btn-primary" onclick="debounce(addMissingEquipment, ['WeaponSkins']);" data-loc="inventory_bulkAddWeaponSkins"></button>
|
||||||
<button class="btn btn-primary" onclick="debounce(addMissingEvolutionProgress);" data-loc="inventory_bulkAddEvolutionProgress"></button>
|
<button class="btn btn-primary" onclick="debounce(addMissingEvolutionProgress);" data-loc="inventory_bulkAddEvolutionProgress"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-2 d-flex flex-wrap gap-2">
|
<div class="mb-2 d-flex flex-wrap gap-2">
|
||||||
@ -719,12 +738,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="edit-suit-invigorations-card" class="card mb-3 d-none">
|
<div id="edit-suit-invigorations-card" class="card mb-3 d-none">
|
||||||
<h5 class="card-header" data-loc="detailedView_suitInvigorationLabel"></h5>
|
<h5 class="card-header" data-loc="detailedView_invigorationLabel"></h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form onsubmit="submitSuitInvigorationUpgrade(event)">
|
<form onsubmit="submitInvigoration(event)">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="invigoration-offensive" class="form-label" data-loc="invigorations_offensiveLabel"></label>
|
<label for="invigoration-offensive" class="form-label" data-loc="detailedView_invigorationOffensiveLabel"></label>
|
||||||
<select class="form-select" id="dv-invigoration-offensive">
|
<select class="form-select" id="invigoration-offensive">
|
||||||
<option value="" data-loc="general_none"></option>
|
<option value="" data-loc="general_none"></option>
|
||||||
<option value="/Lotus/Upgrades/Invigorations/Offensive/OffensiveInvigorationPowerStrength" data-loc="invigorations_offensive_AbilityStrength"></option>
|
<option value="/Lotus/Upgrades/Invigorations/Offensive/OffensiveInvigorationPowerStrength" data-loc="invigorations_offensive_AbilityStrength"></option>
|
||||||
<option value="/Lotus/Upgrades/Invigorations/Offensive/OffensiveInvigorationPowerRange" data-loc="invigorations_offensive_AbilityRange"></option>
|
<option value="/Lotus/Upgrades/Invigorations/Offensive/OffensiveInvigorationPowerRange" data-loc="invigorations_offensive_AbilityRange"></option>
|
||||||
@ -737,10 +756,9 @@
|
|||||||
<option value="/Lotus/Upgrades/Invigorations/Offensive/OffensiveInvigorationMeleeCritChance" data-loc="invigorations_offensive_MeleeCritChance"></option>
|
<option value="/Lotus/Upgrades/Invigorations/Offensive/OffensiveInvigorationMeleeCritChance" data-loc="invigorations_offensive_MeleeCritChance"></option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="invigoration-defensive" class="form-label" data-loc="invigorations_defensiveLabel"></label>
|
<label for="invigoration-defensive" class="form-label" data-loc="detailedView_invigorationUtilityLabel"></label>
|
||||||
<select class="form-select" id="dv-invigoration-defensive">
|
<select class="form-select" id="invigoration-defensive">
|
||||||
<option value="" data-loc="general_none"></option>
|
<option value="" data-loc="general_none"></option>
|
||||||
<option value="/Lotus/Upgrades/Invigorations/Utility/UtilityInvigorationPowerEfficiency" data-loc="invigorations_utility_AbilityEfficiency"></option>
|
<option value="/Lotus/Upgrades/Invigorations/Utility/UtilityInvigorationPowerEfficiency" data-loc="invigorations_utility_AbilityEfficiency"></option>
|
||||||
<option value="/Lotus/Upgrades/Invigorations/Utility/UtilityInvigorationMovementSpeed" data-loc="invigorations_utility_SprintSpeed"></option>
|
<option value="/Lotus/Upgrades/Invigorations/Utility/UtilityInvigorationMovementSpeed" data-loc="invigorations_utility_SprintSpeed"></option>
|
||||||
@ -755,15 +773,13 @@
|
|||||||
<option value="/Lotus/Upgrades/Invigorations/Utility/UtilityInvigorationEnergyRegen" data-loc="invigorations_utility_EnergyRegen"></option>
|
<option value="/Lotus/Upgrades/Invigorations/Utility/UtilityInvigorationEnergyRegen" data-loc="invigorations_utility_EnergyRegen"></option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="invigoration-expiry" class="form-label" data-loc="invigorations_expiryLabel"></label>
|
<label for="invigoration-expiry" class="form-label" data-loc="detailedView_invigorationExpiryLabel"></label>
|
||||||
<input type="datetime-local" class="form-control" id="dv-invigoration-expiry" />
|
<input type="datetime-local" class="form-control" max="2038-01-19T03:14" id="invigoration-expiry" onblur="this.value=new Date(this.value)>new Date(this.max)?new Date(this.max).toISOString().slice(0,16):this.value"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="d-flex gap-2">
|
<div class="d-flex gap-2">
|
||||||
<button type="submit" class="btn btn-primary" data-loc="general_setButton"></button>
|
<button type="submit" class="btn btn-primary" data-loc="general_setButton"></button>
|
||||||
<button type="button" class="btn btn-danger" onclick="clearSuitInvigorationUpgrades()" data-loc="code_remove"></button>
|
<button type="button" class="btn btn-danger" onclick="setInvigoration()" data-loc="code_remove"></button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -1018,6 +1034,48 @@
|
|||||||
<input class="form-check-input" type="checkbox" id="finishInvasionsInOneMission" />
|
<input class="form-check-input" type="checkbox" id="finishInvasionsInOneMission" />
|
||||||
<label class="form-check-label" for="finishInvasionsInOneMission" data-loc="cheats_finishInvasionsInOneMission"></label>
|
<label class="form-check-label" for="finishInvasionsInOneMission" data-loc="cheats_finishInvasionsInOneMission"></label>
|
||||||
</div>
|
</div>
|
||||||
|
<form class="form-group mt-2">
|
||||||
|
<label class="form-label" for="nemesisHenchmenKillsMultiplierGrineer" data-loc="cheats_nemesisHenchmenKillsMultiplierGrineer"></label>
|
||||||
|
<div class="input-group">
|
||||||
|
<input class="form-control" id="nemesisHenchmenKillsMultiplierGrineer" type="number" min="0" max="65535" data-default="1" />
|
||||||
|
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<form class="form-group mt-2">
|
||||||
|
<label class="form-label" for="nemesisHenchmenKillsMultiplierCorpus" data-loc="cheats_nemesisHenchmenKillsMultiplierCorpus"></label>
|
||||||
|
<div class="input-group">
|
||||||
|
<input class="form-control" id="nemesisHenchmenKillsMultiplierCorpus" type="number" min="0" max="65535" data-default="1" />
|
||||||
|
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<form class="form-group mt-2">
|
||||||
|
<label class="form-label" for="nemesisAntivirusGainMultiplier" data-loc="cheats_nemesisAntivirusGainMultiplier"></label>
|
||||||
|
<div class="input-group">
|
||||||
|
<input class="form-control" id="nemesisAntivirusGainMultiplier" type="number" min="0" max="65535" data-default="1" />
|
||||||
|
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<form class="form-group mt-2">
|
||||||
|
<label class="form-label" for="nemesisHintProgressMultiplierGrineer" data-loc="cheats_nemesisHintProgressMultiplierGrineer"></label>
|
||||||
|
<div class="input-group">
|
||||||
|
<input class="form-control" id="nemesisHintProgressMultiplierGrineer" type="number" min="0" max="65535" data-default="1" />
|
||||||
|
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<form class="form-group mt-2">
|
||||||
|
<label class="form-label" for="nemesisHintProgressMultiplierCorpus" data-loc="cheats_nemesisHintProgressMultiplierCorpus"></label>
|
||||||
|
<div class="input-group">
|
||||||
|
<input class="form-control" id="nemesisHintProgressMultiplierCorpus" type="number" min="0" max="65535" data-default="1" />
|
||||||
|
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<form class="form-group mt-2">
|
||||||
|
<label class="form-label" for="nemesisExtraWeapon" data-loc="cheats_nemesisExtraWeapon"></label>
|
||||||
|
<div class="input-group">
|
||||||
|
<input class="form-control" id="nemesisExtraWeapon" type="number" min="0" max="65535" data-default="0" />
|
||||||
|
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
<div class="mt-2 mb-2 d-flex flex-wrap gap-2">
|
<div class="mt-2 mb-2 d-flex flex-wrap gap-2">
|
||||||
<button class="btn btn-primary" onclick="debounce(doUnlockAllShipFeatures);" data-loc="cheats_unlockAllShipFeatures"></button>
|
<button class="btn btn-primary" onclick="debounce(doUnlockAllShipFeatures);" data-loc="cheats_unlockAllShipFeatures"></button>
|
||||||
<button class="btn btn-primary" onclick="debounce(unlockAllMissions);" data-loc="cheats_unlockAllMissions"></button>
|
<button class="btn btn-primary" onclick="debounce(unlockAllMissions);" data-loc="cheats_unlockAllMissions"></button>
|
||||||
@ -1036,7 +1094,7 @@
|
|||||||
<label class="form-label" for="changeSyndicate" data-loc="cheats_changeSupportedSyndicate"></label>
|
<label class="form-label" for="changeSyndicate" data-loc="cheats_changeSupportedSyndicate"></label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<select class="form-control" id="changeSyndicate"></select>
|
<select class="form-control" id="changeSyndicate"></select>
|
||||||
<button class="btn btn-primary" type="submit" data-loc="cheats_changeButton"></button>
|
<button class="btn btn-secondary" type="submit" data-loc="cheats_changeButton"></button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -1150,6 +1208,10 @@
|
|||||||
<label class="form-check-label" for="worldState.hallowedFlame" data-loc="worldState_hallowedFlame"></label>
|
<label class="form-check-label" for="worldState.hallowedFlame" data-loc="worldState_hallowedFlame"></label>
|
||||||
<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>
|
<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>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="worldState.qtccAlerts" />
|
||||||
|
<label class="form-check-label" for="worldState.qtccAlerts" data-loc="worldState_qtccAlerts"></label>
|
||||||
|
</div>
|
||||||
<div class="form-group mt-2 d-flex gap-2">
|
<div class="form-group mt-2 d-flex gap-2">
|
||||||
<div class="flex-fill">
|
<div class="flex-fill">
|
||||||
<label class="form-label" for="worldState.hallowedNightmares" data-loc="worldState_hallowedNightmares"></label>
|
<label class="form-label" for="worldState.hallowedNightmares" data-loc="worldState_hallowedNightmares"></label>
|
||||||
@ -1168,6 +1230,14 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group mt-2">
|
||||||
|
<label class="form-label" for="worldState.naberusNightsOverride" data-loc="worldState_naberusNights"></label>
|
||||||
|
<select class="form-control" id="worldState.naberusNightsOverride" data-default="null">
|
||||||
|
<option value="null" data-loc="normal"></option>
|
||||||
|
<option value="true" data-loc="enabled"></option>
|
||||||
|
<option value="false" data-loc="disabled"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="form-group mt-2 d-flex gap-2">
|
<div class="form-group mt-2 d-flex gap-2">
|
||||||
<div class="flex-fill">
|
<div class="flex-fill">
|
||||||
<label class="form-label" for="worldState.proxyRebellion" data-loc="worldState_proxyRebellion"></label>
|
<label class="form-label" for="worldState.proxyRebellion" data-loc="worldState_proxyRebellion"></label>
|
||||||
@ -1185,6 +1255,27 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mt-2">
|
||||||
|
<label class="form-label" data-loc="worldState_voidCorruption" data-loc-replace="2025"></label>
|
||||||
|
<div class="d-flex flex-wrap gap-3">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="worldState.voidCorruption2025Week1" />
|
||||||
|
<label class="form-check-label" for="worldState.voidCorruption2025Week1" data-loc="worldState_week" data-loc-replace="1"></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="worldState.voidCorruption2025Week2" />
|
||||||
|
<label class="form-check-label" for="worldState.voidCorruption2025Week2" data-loc="worldState_week" data-loc-replace="2"></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="worldState.voidCorruption2025Week3" />
|
||||||
|
<label class="form-check-label" for="worldState.voidCorruption2025Week3" data-loc="worldState_week" data-loc-replace="3"></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="worldState.voidCorruption2025Week4" />
|
||||||
|
<label class="form-check-label" for="worldState.voidCorruption2025Week4" data-loc="worldState_week" data-loc-replace="4"></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group mt-2">
|
<div class="form-group mt-2">
|
||||||
<label class="form-label" for="worldState.galleonOfGhouls" data-loc="worldState_galleonOfGhouls"></label>
|
<label class="form-label" for="worldState.galleonOfGhouls" data-loc="worldState_galleonOfGhouls"></label>
|
||||||
<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>
|
<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>
|
||||||
@ -1456,6 +1547,7 @@
|
|||||||
<datalist id="datalist-VaultDecoRecipes"></datalist>
|
<datalist id="datalist-VaultDecoRecipes"></datalist>
|
||||||
<datalist id="datalist-FlavourItems"></datalist>
|
<datalist id="datalist-FlavourItems"></datalist>
|
||||||
<datalist id="datalist-ShipDecorations"></datalist>
|
<datalist id="datalist-ShipDecorations"></datalist>
|
||||||
|
<datalist id="datalist-WeaponSkins"></datalist>
|
||||||
<datalist id="datalist-circuitGameModes">
|
<datalist id="datalist-circuitGameModes">
|
||||||
<option>Survival</option>
|
<option>Survival</option>
|
||||||
<option>VoidFlood</option>
|
<option>VoidFlood</option>
|
||||||
|
|||||||
@ -599,6 +599,46 @@ function fetchItemList() {
|
|||||||
}
|
}
|
||||||
itemMap[item.uniqueName] = { ...item, type };
|
itemMap[item.uniqueName] = { ...item, type };
|
||||||
});
|
});
|
||||||
|
} else if (type == "WeaponSkins") {
|
||||||
|
let beardNumber = 1;
|
||||||
|
let cutNumber = 13;
|
||||||
|
let adultHeadNumber = 1;
|
||||||
|
let headNumber = 1;
|
||||||
|
items.forEach(item => {
|
||||||
|
if (item.name == "") {
|
||||||
|
if (item.uniqueName.includes("/Beards/")) {
|
||||||
|
item.name = loc("code_drifterBeardName")
|
||||||
|
.split("|INDEX|")
|
||||||
|
.join(beardNumber.toString().padStart(3, "0"));
|
||||||
|
beardNumber++;
|
||||||
|
} else if (item.uniqueName.includes("/Hair/")) {
|
||||||
|
item.name = loc("code_cutName")
|
||||||
|
.split("|INDEX|")
|
||||||
|
.join(cutNumber.toString().padStart(3, "0"));
|
||||||
|
cutNumber++;
|
||||||
|
if (cutNumber == 19) cutNumber = 21;
|
||||||
|
} else if (item.uniqueName.includes("/Heads/Adult")) {
|
||||||
|
item.name = loc("code_drifterFaceName")
|
||||||
|
.split("|INDEX|")
|
||||||
|
.join(adultHeadNumber.toString().padStart(3, "0"));
|
||||||
|
adultHeadNumber++;
|
||||||
|
} else if (item.uniqueName.includes("/Heads/")) {
|
||||||
|
item.name = loc("code_operatorFaceName")
|
||||||
|
.split("|INDEX|")
|
||||||
|
.join(headNumber.toString().padStart(3, "0"));
|
||||||
|
headNumber++;
|
||||||
|
} else {
|
||||||
|
item.name = item.uniqueName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!item.alwaysAvailable) {
|
||||||
|
const option = document.createElement("option");
|
||||||
|
option.setAttribute("data-key", item.uniqueName);
|
||||||
|
option.value = item.name;
|
||||||
|
document.getElementById("datalist-" + type).appendChild(option);
|
||||||
|
}
|
||||||
|
itemMap[item.uniqueName] = { ...item, type };
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
const nameToItems = {};
|
const nameToItems = {};
|
||||||
items.forEach(item => {
|
items.forEach(item => {
|
||||||
@ -837,10 +877,9 @@ function updateInventory() {
|
|||||||
a.href = "#";
|
a.href = "#";
|
||||||
a.onclick = function (event) {
|
a.onclick = function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
revalidateAuthz().then(() => {
|
revalidateAuthz().then(async () => {
|
||||||
const promises = [];
|
|
||||||
if (item.XP < maxXP) {
|
if (item.XP < maxXP) {
|
||||||
promises.push(addGearExp(category, item.ItemId.$oid, maxXP - item.XP));
|
await addGearExp(category, item.ItemId.$oid, maxXP - item.XP);
|
||||||
}
|
}
|
||||||
if ("exalted" in itemMap[item.ItemType]) {
|
if ("exalted" in itemMap[item.ItemType]) {
|
||||||
for (const exaltedType of itemMap[item.ItemType].exalted) {
|
for (const exaltedType of itemMap[item.ItemType].exalted) {
|
||||||
@ -851,20 +890,16 @@ function updateInventory() {
|
|||||||
const exaltedCap =
|
const exaltedCap =
|
||||||
itemMap[exaltedType]?.type == "weapons" ? 800_000 : 1_600_000;
|
itemMap[exaltedType]?.type == "weapons" ? 800_000 : 1_600_000;
|
||||||
if (exaltedItem.XP < exaltedCap) {
|
if (exaltedItem.XP < exaltedCap) {
|
||||||
promises.push(
|
await addGearExp(
|
||||||
addGearExp(
|
"SpecialItems",
|
||||||
"SpecialItems",
|
exaltedItem.ItemId.$oid,
|
||||||
exaltedItem.ItemId.$oid,
|
exaltedCap - exaltedItem.XP
|
||||||
exaltedCap - exaltedItem.XP
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Promise.all(promises).then(() => {
|
updateInventory();
|
||||||
updateInventory();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
a.title = loc("code_maxRank");
|
a.title = loc("code_maxRank");
|
||||||
@ -1007,6 +1042,67 @@ function updateInventory() {
|
|||||||
document.getElementById("EvolutionProgress-list").appendChild(tr);
|
document.getElementById("EvolutionProgress-list").appendChild(tr);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.getElementById("Boosters-list").innerHTML = "";
|
||||||
|
data.Boosters.forEach(item => {
|
||||||
|
if (item.ExpiryDate < Math.floor(Date.now() / 1000)) {
|
||||||
|
// Booster has expired, skip it
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tr = document.createElement("tr");
|
||||||
|
{
|
||||||
|
const td = document.createElement("td");
|
||||||
|
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
|
||||||
|
tr.appendChild(td);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const td = document.createElement("td");
|
||||||
|
td.classList = "text-end text-nowrap";
|
||||||
|
{
|
||||||
|
const form = document.createElement("form");
|
||||||
|
form.style.display = "inline-block";
|
||||||
|
form.onsubmit = function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
const maxDate = new Date(input.max);
|
||||||
|
const selectedDate = new Date(input.value);
|
||||||
|
if (selectedDate > maxDate) {
|
||||||
|
input.value = maxDate.toISOString().slice(0, 16);
|
||||||
|
}
|
||||||
|
doChangeBoosterExpiry(item.ItemType, input);
|
||||||
|
};
|
||||||
|
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "datetime-local";
|
||||||
|
input.classList = "form-control form-control-sm";
|
||||||
|
input.value = formatDatetime("%Y-%m-%d %H:%M:%s", item.ExpiryDate * 1000);
|
||||||
|
input.max = "2038-01-19T03:14";
|
||||||
|
input.onblur = function () {
|
||||||
|
const maxDate = new Date(input.max);
|
||||||
|
const selectedDate = new Date(input.value);
|
||||||
|
if (selectedDate > maxDate) {
|
||||||
|
input.value = maxDate.toISOString().slice(0, 16);
|
||||||
|
}
|
||||||
|
doChangeBoosterExpiry(item.ItemType, input);
|
||||||
|
};
|
||||||
|
|
||||||
|
form.appendChild(input);
|
||||||
|
td.appendChild(form);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.href = "#";
|
||||||
|
a.onclick = function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
setBooster(item.ItemType, 0);
|
||||||
|
};
|
||||||
|
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("Boosters-list").appendChild(tr);
|
||||||
|
});
|
||||||
|
|
||||||
document.getElementById("FlavourItems-list").innerHTML = "";
|
document.getElementById("FlavourItems-list").innerHTML = "";
|
||||||
data.FlavourItems.forEach(item => {
|
data.FlavourItems.forEach(item => {
|
||||||
const datalist = document.getElementById("datalist-FlavourItems");
|
const datalist = document.getElementById("datalist-FlavourItems");
|
||||||
@ -1047,6 +1143,44 @@ function updateInventory() {
|
|||||||
document.getElementById("FlavourItems-list").appendChild(tr);
|
document.getElementById("FlavourItems-list").appendChild(tr);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.getElementById("WeaponSkins-list").innerHTML = "";
|
||||||
|
data.WeaponSkins.forEach(item => {
|
||||||
|
if (item.ItemId.$oid.startsWith("ca70ca70ca70ca70")) return;
|
||||||
|
const datalist = document.getElementById("datalist-WeaponSkins");
|
||||||
|
const optionToRemove = datalist.querySelector(`option[data-key="${item.ItemType}"]`);
|
||||||
|
if (optionToRemove) {
|
||||||
|
datalist.removeChild(optionToRemove);
|
||||||
|
}
|
||||||
|
const tr = document.createElement("tr");
|
||||||
|
{
|
||||||
|
const td = document.createElement("td");
|
||||||
|
const name = itemMap[item.ItemType]?.name?.trim();
|
||||||
|
td.textContent = name || item.ItemType;
|
||||||
|
tr.appendChild(td);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const td = document.createElement("td");
|
||||||
|
td.classList = "text-end text-nowrap";
|
||||||
|
{
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.href = "#";
|
||||||
|
a.onclick = function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
document.getElementById("WeaponSkins-list").removeChild(tr);
|
||||||
|
reAddToItemList(itemMap, "WeaponSkins", item.ItemType);
|
||||||
|
disposeOfGear("WeaponSkins", 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("WeaponSkins-list").appendChild(tr);
|
||||||
|
});
|
||||||
|
|
||||||
const datalistEvolutionProgress = document.querySelectorAll("#datalist-EvolutionProgress option");
|
const datalistEvolutionProgress = document.querySelectorAll("#datalist-EvolutionProgress option");
|
||||||
const formEvolutionProgress = document.querySelector('form[onsubmit*="doAcquireEvolution()"]');
|
const formEvolutionProgress = document.querySelector('form[onsubmit*="doAcquireEvolution()"]');
|
||||||
|
|
||||||
@ -1146,7 +1280,7 @@ function updateInventory() {
|
|||||||
a.href = "#";
|
a.href = "#";
|
||||||
a.onclick = function (event) {
|
a.onclick = function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
doQuestUpdate("setInactive", item.ItemType);
|
debounce(doQuestUpdate, "setInactive", item.ItemType);
|
||||||
};
|
};
|
||||||
a.title = loc("code_setInactive");
|
a.title = loc("code_setInactive");
|
||||||
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M464 256A208 208 0 1 0 48 256a208 208 0 1 0 416 0zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256zm192-96l128 0c17.7 0 32 14.3 32 32l0 128c0 17.7-14.3 32-32 32l-128 0c-17.7 0-32-14.3-32-32l0-128c0-17.7 14.3-32 32-32z"/></svg>`;
|
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M464 256A208 208 0 1 0 48 256a208 208 0 1 0 416 0zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256zm192-96l128 0c17.7 0 32 14.3 32 32l0 128c0 17.7-14.3 32-32 32l-128 0c-17.7 0-32-14.3-32-32l0-128c0-17.7 14.3-32 32-32z"/></svg>`;
|
||||||
@ -1157,7 +1291,7 @@ function updateInventory() {
|
|||||||
a.href = "#";
|
a.href = "#";
|
||||||
a.onclick = function (event) {
|
a.onclick = function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
doQuestUpdate("resetKey", item.ItemType);
|
debounce(doQuestUpdate, "resetKey", item.ItemType);
|
||||||
};
|
};
|
||||||
a.title = loc("code_reset");
|
a.title = loc("code_reset");
|
||||||
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M463.5 224l8.5 0c13.3 0 24-10.7 24-24l0-128c0-9.7-5.8-18.5-14.8-22.2s-19.3-1.7-26.2 5.2L413.4 96.6c-87.6-86.5-228.7-86.2-315.8 1c-87.5 87.5-87.5 229.3 0 316.8s229.3 87.5 316.8 0c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0c-62.5 62.5-163.8 62.5-226.3 0s-62.5-163.8 0-226.3c62.2-62.2 162.7-62.5 225.3-1L327 183c-6.9 6.9-8.9 17.2-5.2 26.2s12.5 14.8 22.2 14.8l119.5 0z"/></svg>`;
|
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M463.5 224l8.5 0c13.3 0 24-10.7 24-24l0-128c0-9.7-5.8-18.5-14.8-22.2s-19.3-1.7-26.2 5.2L413.4 96.6c-87.6-86.5-228.7-86.2-315.8 1c-87.5 87.5-87.5 229.3 0 316.8s229.3 87.5 316.8 0c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0c-62.5 62.5-163.8 62.5-226.3 0s-62.5-163.8 0-226.3c62.2-62.2 162.7-62.5 225.3-1L327 183c-6.9 6.9-8.9 17.2-5.2 26.2s12.5 14.8 22.2 14.8l119.5 0z"/></svg>`;
|
||||||
@ -1168,7 +1302,7 @@ function updateInventory() {
|
|||||||
a.href = "#";
|
a.href = "#";
|
||||||
a.onclick = function (event) {
|
a.onclick = function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
doQuestUpdate("completeKey", item.ItemType);
|
debounce(doQuestUpdate, "completeKey", item.ItemType);
|
||||||
};
|
};
|
||||||
a.title = loc("code_complete");
|
a.title = loc("code_complete");
|
||||||
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M438.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L160 338.7 393.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"/></svg>`;
|
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M438.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L160 338.7 393.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"/></svg>`;
|
||||||
@ -1179,7 +1313,7 @@ function updateInventory() {
|
|||||||
a.href = "#";
|
a.href = "#";
|
||||||
a.onclick = function (event) {
|
a.onclick = function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
doQuestUpdate("prevStage", item.ItemType);
|
debounce(doQuestUpdate, "prevStage", item.ItemType);
|
||||||
};
|
};
|
||||||
a.title = loc("code_prevStage");
|
a.title = loc("code_prevStage");
|
||||||
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="M41.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l160 160c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 256 246.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-160 160z"/></svg>`;
|
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="M41.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l160 160c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 256 246.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-160 160z"/></svg>`;
|
||||||
@ -1194,7 +1328,7 @@ function updateInventory() {
|
|||||||
a.href = "#";
|
a.href = "#";
|
||||||
a.onclick = function (event) {
|
a.onclick = function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
doQuestUpdate("nextStage", item.ItemType);
|
debounce(doQuestUpdate, "nextStage", item.ItemType);
|
||||||
};
|
};
|
||||||
a.title = loc("code_nextStage");
|
a.title = loc("code_nextStage");
|
||||||
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="M278.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-160 160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160z"/></svg>`;
|
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="M278.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-160 160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160z"/></svg>`;
|
||||||
@ -1206,7 +1340,7 @@ function updateInventory() {
|
|||||||
a.onclick = function (event) {
|
a.onclick = function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
reAddToItemList(itemMap, "QuestKeys", item.ItemType);
|
reAddToItemList(itemMap, "QuestKeys", item.ItemType);
|
||||||
doQuestUpdate("deleteKey", item.ItemType);
|
debounce(doQuestUpdate, "deleteKey", item.ItemType);
|
||||||
};
|
};
|
||||||
a.title = loc("code_remove");
|
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>`;
|
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>`;
|
||||||
@ -1452,12 +1586,13 @@ function updateInventory() {
|
|||||||
document.getElementById("crystals-list").appendChild(tr);
|
document.getElementById("crystals-list").appendChild(tr);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById("edit-suit-invigorations-card").classList.remove("d-none");
|
{
|
||||||
const { OffensiveUpgrade, DefensiveUpgrade, UpgradesExpiry } =
|
document.getElementById("edit-suit-invigorations-card").classList.remove("d-none");
|
||||||
suitInvigorationUpgradeData(item);
|
document.getElementById("invigoration-offensive").value = item.OffensiveUpgrade || "";
|
||||||
document.getElementById("dv-invigoration-offensive").value = OffensiveUpgrade;
|
document.getElementById("invigoration-defensive").value = item.DefensiveUpgrade || "";
|
||||||
document.getElementById("dv-invigoration-defensive").value = DefensiveUpgrade;
|
document.getElementById("invigoration-expiry").value =
|
||||||
document.getElementById("dv-invigoration-expiry").value = UpgradesExpiry;
|
formatDatetime("%Y-%m-%d %H:%M", Number(item.UpgradesExpiry?.$date.$numberLong)) || "";
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
document.getElementById("loadout-card").classList.remove("d-none");
|
document.getElementById("loadout-card").classList.remove("d-none");
|
||||||
@ -1619,63 +1754,6 @@ function updateInventory() {
|
|||||||
}
|
}
|
||||||
document.getElementById("changeSyndicate").value = data.SupportedSyndicate ?? "";
|
document.getElementById("changeSyndicate").value = data.SupportedSyndicate ?? "";
|
||||||
|
|
||||||
document.getElementById("Boosters-list").innerHTML = "";
|
|
||||||
const now = Math.floor(Date.now() / 1000);
|
|
||||||
data.Boosters.forEach(({ ItemType, ExpiryDate }) => {
|
|
||||||
if (ExpiryDate < now) {
|
|
||||||
// Booster has expired, skip it
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const tr = document.createElement("tr");
|
|
||||||
{
|
|
||||||
const td = document.createElement("td");
|
|
||||||
td.textContent = itemMap[ItemType]?.name ?? ItemType;
|
|
||||||
tr.appendChild(td);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const td = document.createElement("td");
|
|
||||||
td.classList = "text-end text-nowrap";
|
|
||||||
const timeString = formatDatetime("%Y-%m-%d %H:%M:%s", ExpiryDate * 1000);
|
|
||||||
const inlineForm = document.createElement("form");
|
|
||||||
const input = document.createElement("input");
|
|
||||||
|
|
||||||
inlineForm.style.display = "inline-block";
|
|
||||||
inlineForm.onsubmit = function (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
doChangeBoosterExpiry(ItemType, input);
|
|
||||||
};
|
|
||||||
input.type = "datetime-local";
|
|
||||||
input.classList.add("form-control");
|
|
||||||
input.classList.add("form-control-sm");
|
|
||||||
input.value = timeString;
|
|
||||||
let changed = false;
|
|
||||||
input.onchange = function () {
|
|
||||||
changed = true;
|
|
||||||
};
|
|
||||||
input.onblur = function () {
|
|
||||||
if (changed) {
|
|
||||||
doChangeBoosterExpiry(ItemType, input);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
inlineForm.appendChild(input);
|
|
||||||
|
|
||||||
td.appendChild(inlineForm);
|
|
||||||
|
|
||||||
const removeButton = document.createElement("a");
|
|
||||||
removeButton.title = loc("code_remove");
|
|
||||||
removeButton.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>`;
|
|
||||||
removeButton.href = "#";
|
|
||||||
removeButton.onclick = function (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
setBooster(ItemType, 0);
|
|
||||||
};
|
|
||||||
td.appendChild(removeButton);
|
|
||||||
|
|
||||||
tr.appendChild(td);
|
|
||||||
}
|
|
||||||
document.getElementById("Boosters-list").appendChild(tr);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (single.getCurrentPath().startsWith("/webui/guildView")) {
|
if (single.getCurrentPath().startsWith("/webui/guildView")) {
|
||||||
const guildReq = $.get("/custom/getGuild?guildId=" + window.guildId);
|
const guildReq = $.get("/custom/getGuild?guildId=" + window.guildId);
|
||||||
guildReq.done(guildData => {
|
guildReq.done(guildData => {
|
||||||
@ -1771,7 +1849,7 @@ function updateInventory() {
|
|||||||
a.href = "#";
|
a.href = "#";
|
||||||
a.onclick = function (event) {
|
a.onclick = function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
fundGuildTechProject(item.ItemType);
|
debounce(fundGuildTechProject, item.ItemType);
|
||||||
};
|
};
|
||||||
a.title = loc("code_fund");
|
a.title = loc("code_fund");
|
||||||
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free v7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M214.6 17.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 117.3 160 488c0 17.7 14.3 32 32 32s32-14.3 32-32l0-370.7 105.4 105.4c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z"/></svg>`;
|
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free v7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M214.6 17.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 117.3 160 488c0 17.7 14.3 32 32 32s32-14.3 32-32l0-370.7 105.4 105.4c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z"/></svg>`;
|
||||||
@ -1788,7 +1866,7 @@ function updateInventory() {
|
|||||||
a.href = "#";
|
a.href = "#";
|
||||||
a.onclick = function (event) {
|
a.onclick = function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
completeGuildTechProject(item.ItemType);
|
debounce(completeGuildTechProject, item.ItemType);
|
||||||
};
|
};
|
||||||
a.title = loc("code_complete");
|
a.title = loc("code_complete");
|
||||||
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--!Font Awesome Free v7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M371.7 43.1C360.1 32 343 28.9 328.3 35.2S304 56 304 72l0 136.3-172.3-165.1C120.1 32 103 28.9 88.3 35.2S64 56 64 72l0 368c0 16 9.6 30.5 24.3 36.8s31.8 3.2 43.4-7.9L304 303.7 304 440c0 16 9.6 30.5 24.3 36.8s31.8 3.2 43.4-7.9l192-184c7.9-7.5 12.3-18 12.3-28.9s-4.5-21.3-12.3-28.9l-192-184z"/></svg>`;
|
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--!Font Awesome Free v7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M371.7 43.1C360.1 32 343 28.9 328.3 35.2S304 56 304 72l0 136.3-172.3-165.1C120.1 32 103 28.9 88.3 35.2S64 56 64 72l0 368c0 16 9.6 30.5 24.3 36.8s31.8 3.2 43.4-7.9L304 303.7 304 440c0 16 9.6 30.5 24.3 36.8s31.8 3.2 43.4-7.9l192-184c7.9-7.5 12.3-18 12.3-28.9s-4.5-21.3-12.3-28.9l-192-184z"/></svg>`;
|
||||||
@ -1801,7 +1879,7 @@ function updateInventory() {
|
|||||||
a.onclick = function (event) {
|
a.onclick = function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
reAddToItemList(itemMap, "TechProjects", item.ItemType);
|
reAddToItemList(itemMap, "TechProjects", item.ItemType);
|
||||||
removeGuildTechProject(item.ItemType);
|
debounce(removeGuildTechProject, item.ItemType);
|
||||||
};
|
};
|
||||||
a.title = loc("code_remove");
|
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>`;
|
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>`;
|
||||||
@ -1986,34 +2064,12 @@ function updateInventory() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const elm of accountCheats) {
|
for (const elm of accountCheats) {
|
||||||
elm.checked = !!data[elm.id];
|
if (elm.type === "checkbox") {
|
||||||
}
|
elm.checked = !!data[elm.id];
|
||||||
});
|
} else if (elm.type === "number") {
|
||||||
});
|
elm.value = data[elm.id] !== undefined ? data[elm.id] : elm.getAttribute("data-default") || "";
|
||||||
}
|
|
||||||
|
|
||||||
function addVaultDecoRecipe() {
|
|
||||||
const uniqueName = getKey(document.getElementById("acquire-type-VaultDecoRecipes"));
|
|
||||||
if (!guildId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!uniqueName) {
|
|
||||||
$("acquire-type-VaultDecoRecipes").addClass("is-invalid").focus();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
revalidateAuthz().then(() => {
|
|
||||||
const req = $.post({
|
|
||||||
url: "/custom/addVaultDecoRecipe?" + window.authz + "&guildId=" + window.guildId,
|
|
||||||
contentType: "application/json",
|
|
||||||
data: JSON.stringify([
|
|
||||||
{
|
|
||||||
ItemType: uniqueName,
|
|
||||||
ItemCount: 1
|
|
||||||
}
|
}
|
||||||
])
|
}
|
||||||
});
|
|
||||||
req.done(() => {
|
|
||||||
updateInventory();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -2866,8 +2922,8 @@ function removeCountItems(uniqueName, count) {
|
|||||||
|
|
||||||
function addItemByItemType() {
|
function addItemByItemType() {
|
||||||
const ItemType = document.getElementById("typeName-type").value;
|
const ItemType = document.getElementById("typeName-type").value;
|
||||||
// Must start with "/Lotus/", contain only A–Z letters, no "//", and not end with "/"
|
// Must start with "/Lotus/", contain only letters A–Z, digits 0–9, no "//", and not end with "/"
|
||||||
if (!ItemType || !/^\/Lotus\/(?:[A-Za-z]+(?:\/[A-Za-z]+)*)$/.test(ItemType)) {
|
if (!ItemType || !/^\/Lotus\/(?:[A-Za-z0-9]+(?:\/[A-Za-z0-9]+)*)$/.test(ItemType)) {
|
||||||
$("#typeName-type").addClass("is-invalid").focus();
|
$("#typeName-type").addClass("is-invalid").focus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3217,13 +3273,53 @@ function doIntrinsicsUnlockAll() {
|
|||||||
document.querySelectorAll("#account-cheats input[type=checkbox]").forEach(elm => {
|
document.querySelectorAll("#account-cheats input[type=checkbox]").forEach(elm => {
|
||||||
elm.onchange = function () {
|
elm.onchange = function () {
|
||||||
revalidateAuthz().then(() => {
|
revalidateAuthz().then(() => {
|
||||||
|
const value = elm.checked;
|
||||||
$.post({
|
$.post({
|
||||||
url: "/custom/setAccountCheat?" + window.authz,
|
url: "/custom/setAccountCheat?" + window.authz,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
data: JSON.stringify({
|
data: JSON.stringify({
|
||||||
key: elm.id,
|
key: elm.id,
|
||||||
value: elm.checked
|
value: value
|
||||||
})
|
})
|
||||||
|
}).done(() => {
|
||||||
|
elm.checked = value;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelectorAll("#account-cheats .input-group").forEach(grp => {
|
||||||
|
const input = grp.querySelector("input");
|
||||||
|
const select = grp.querySelector("select");
|
||||||
|
const btn = grp.querySelector("button");
|
||||||
|
if (input) {
|
||||||
|
input.oninput = input.onchange = function () {
|
||||||
|
btn.classList.remove("btn-secondary");
|
||||||
|
btn.classList.add("btn-primary");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (select) {
|
||||||
|
select.oninput = select.onchange = function () {
|
||||||
|
btn.classList.remove("btn-secondary");
|
||||||
|
btn.classList.add("btn-primary");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
btn.onclick = function () {
|
||||||
|
btn.classList.remove("btn-primary");
|
||||||
|
btn.classList.add("btn-secondary");
|
||||||
|
const input = btn.closest(".input-group").querySelector('input[type="number"]');
|
||||||
|
if (!input) return;
|
||||||
|
revalidateAuthz().then(() => {
|
||||||
|
const value = input.value;
|
||||||
|
$.post({
|
||||||
|
url: "/custom/setAccountCheat?" + window.authz,
|
||||||
|
contentType: "application/json",
|
||||||
|
data: JSON.stringify({
|
||||||
|
key: input.id,
|
||||||
|
value: parseInt(value)
|
||||||
|
})
|
||||||
|
}).done(() => {
|
||||||
|
btn.value = value;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -3467,9 +3563,9 @@ function doBulkQuestUpdate(operation) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function toast(text) {
|
function toast(text, type = "primary") {
|
||||||
const toast = document.createElement("div");
|
const toast = document.createElement("div");
|
||||||
toast.className = "toast align-items-center text-bg-primary border-0";
|
toast.className = `toast align-items-center text-bg-${type} border-0`;
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
||||||
div.className = "d-flex";
|
div.className = "d-flex";
|
||||||
const body = document.createElement("div");
|
const body = document.createElement("div");
|
||||||
@ -3542,7 +3638,7 @@ function handleModularSelection(category) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function setBooster(ItemType, ExpiryDate, callback) {
|
function setBooster(ItemType, ExpiryDate) {
|
||||||
revalidateAuthz().then(() => {
|
revalidateAuthz().then(() => {
|
||||||
$.post({
|
$.post({
|
||||||
url: "/custom/setBooster?" + window.authz,
|
url: "/custom/setBooster?" + window.authz,
|
||||||
@ -3555,33 +3651,27 @@ function setBooster(ItemType, ExpiryDate, callback) {
|
|||||||
])
|
])
|
||||||
}).done(function () {
|
}).done(function () {
|
||||||
updateInventory();
|
updateInventory();
|
||||||
if (callback) callback();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function doAcquireBoosters() {
|
function doAcquireBooster() {
|
||||||
const uniqueName = getKey(document.getElementById("acquire-type-Boosters"));
|
const uniqueName = getKey(document.getElementById("acquire-type-Boosters"));
|
||||||
if (!uniqueName) {
|
if (!uniqueName) {
|
||||||
$("#acquire-type-Boosters").addClass("is-invalid").focus();
|
$("#acquire-type-Boosters").addClass("is-invalid").focus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const ExpiryDate = Date.now() / 1000 + 3 * 24 * 60 * 60; // default 3 days
|
setBooster(uniqueName, Math.floor(Date.now() / 1000 + 3 * 24 * 60 * 60));
|
||||||
setBooster(uniqueName, ExpiryDate, () => {
|
document.getElementById("acquire-type-Boosters").value = "";
|
||||||
$("#acquire-type-Boosters").val("");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function doChangeBoosterExpiry(ItemType, ExpiryDateInput) {
|
function doChangeBoosterExpiry(ItemType, ExpiryDateInput) {
|
||||||
console.log("Changing booster expiry for", ItemType, "to", ExpiryDateInput.value);
|
const ExpiryDate = Math.floor(new Date(ExpiryDateInput.value).getTime() / 1000);
|
||||||
// cast local datetime string to unix timestamp
|
|
||||||
const ExpiryDate = Math.trunc(new Date(ExpiryDateInput.value).getTime() / 1000);
|
|
||||||
if (isNaN(ExpiryDate)) {
|
if (isNaN(ExpiryDate)) {
|
||||||
ExpiryDateInput.addClass("is-invalid").focus();
|
ExpiryDateInput.addClass("is-invalid").focus();
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
setBooster(ItemType, ExpiryDate);
|
setBooster(ItemType, ExpiryDate);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatDatetime(fmt, date) {
|
function formatDatetime(fmt, date) {
|
||||||
@ -4027,73 +4117,31 @@ function handleModularPartsChange(event) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function suitInvigorationUpgradeData(suitData) {
|
|
||||||
let expiryDate = "";
|
|
||||||
if (suitData.UpgradesExpiry) {
|
|
||||||
if (suitData.UpgradesExpiry.$date) {
|
|
||||||
expiryDate = new Date(parseInt(suitData.UpgradesExpiry.$date.$numberLong));
|
|
||||||
} else if (typeof suitData.UpgradesExpiry === "number") {
|
|
||||||
expiryDate = new Date(suitData.UpgradesExpiry);
|
|
||||||
} else if (suitData.UpgradesExpiry instanceof Date) {
|
|
||||||
expiryDate = suitData.UpgradesExpiry;
|
|
||||||
}
|
|
||||||
if (expiryDate && !isNaN(expiryDate.getTime())) {
|
|
||||||
const year = expiryDate.getFullYear();
|
|
||||||
const month = String(expiryDate.getMonth() + 1).padStart(2, "0");
|
|
||||||
const day = String(expiryDate.getDate()).padStart(2, "0");
|
|
||||||
const hours = String(expiryDate.getHours()).padStart(2, "0");
|
|
||||||
const minutes = String(expiryDate.getMinutes()).padStart(2, "0");
|
|
||||||
expiryDate = `${year}-${month}-${day}T${hours}:${minutes}`;
|
|
||||||
} else {
|
|
||||||
expiryDate = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
oid: suitData.ItemId.$oid,
|
|
||||||
OffensiveUpgrade: suitData.OffensiveUpgrade || "",
|
|
||||||
DefensiveUpgrade: suitData.DefensiveUpgrade || "",
|
|
||||||
UpgradesExpiry: expiryDate
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function submitSuitInvigorationUpgrade(event) {
|
function submitInvigoration(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const oid = new URLSearchParams(window.location.search).get("itemId");
|
const OffensiveUpgrade = document.getElementById("invigoration-offensive").value;
|
||||||
const offensiveUpgrade = document.getElementById("dv-invigoration-offensive").value;
|
const DefensiveUpgrade = document.getElementById("invigoration-defensive").value;
|
||||||
const defensiveUpgrade = document.getElementById("dv-invigoration-defensive").value;
|
const expiry = document.getElementById("invigoration-expiry").value;
|
||||||
const expiry = document.getElementById("dv-invigoration-expiry").value;
|
|
||||||
|
|
||||||
if (!offensiveUpgrade || !defensiveUpgrade) {
|
if (!OffensiveUpgrade || !DefensiveUpgrade) {
|
||||||
alert(loc("code_requiredInvigorationUpgrade"));
|
toast(loc("code_requiredInvigorationUpgrade"), "warning");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = {
|
setInvigoration({
|
||||||
OffensiveUpgrade: offensiveUpgrade,
|
OffensiveUpgrade,
|
||||||
DefensiveUpgrade: defensiveUpgrade
|
DefensiveUpgrade,
|
||||||
};
|
UpgradesExpiry: expiry ? new Date(expiry).getTime() : Date.now() + 7 * 24 * 60 * 60 * 1000
|
||||||
|
});
|
||||||
if (expiry) {
|
|
||||||
data.UpgradesExpiry = new Date(expiry).getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
editSuitInvigorationUpgrade(oid, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearSuitInvigorationUpgrades() {
|
function setInvigoration(data) {
|
||||||
editSuitInvigorationUpgrade(new URLSearchParams(window.location.search).get("itemId"), null);
|
const oid = new URLSearchParams(window.location.search).get("itemId");
|
||||||
}
|
|
||||||
|
|
||||||
async function editSuitInvigorationUpgrade(oid, data) {
|
|
||||||
/* data?: {
|
|
||||||
DefensiveUpgrade: string;
|
|
||||||
OffensiveUpgrade: string;
|
|
||||||
UpgradesExpiry?: number;
|
|
||||||
}*/
|
|
||||||
$.post({
|
$.post({
|
||||||
url: "/custom/editSuitInvigorationUpgrade?" + window.authz,
|
url: "/custom/setInvigoration?" + window.authz,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
data: JSON.stringify({ oid, data })
|
data: JSON.stringify({ oid, ...data })
|
||||||
}).done(function () {
|
}).done(function () {
|
||||||
updateInventory();
|
updateInventory();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -75,8 +75,12 @@ dict = {
|
|||||||
code_funded: `[UNTRANSLATED] Funded`,
|
code_funded: `[UNTRANSLATED] Funded`,
|
||||||
code_replays: `[UNTRANSLATED] Replays`,
|
code_replays: `[UNTRANSLATED] Replays`,
|
||||||
code_stalker: `Stalker`,
|
code_stalker: `Stalker`,
|
||||||
|
code_cutName: `Frisur: |INDEX|`,
|
||||||
|
code_drifterBeardName: `Drifter-Bart: |INDEX|`,
|
||||||
|
code_drifterFaceName: `Drifter-Gesicht: |INDEX|`,
|
||||||
|
code_operatorFaceName: `Operator-Gesicht: |INDEX|`,
|
||||||
code_succChange: `Erfolgreich geändert.`,
|
code_succChange: `Erfolgreich geändert.`,
|
||||||
code_requiredInvigorationUpgrade: `Du musst sowohl ein offensives & defensives Upgrade auswählen.`,
|
code_requiredInvigorationUpgrade: `[UNTRANSLATED] You must select both an offensive & utility upgrade.`,
|
||||||
login_description: `Melde dich mit deinem OpenWF-Account an (denselben Angaben wie im Spiel, wenn du dich mit diesem Server verbindest).`,
|
login_description: `Melde dich mit deinem OpenWF-Account an (denselben Angaben wie im Spiel, wenn du dich mit diesem Server verbindest).`,
|
||||||
login_emailLabel: `E-Mail-Adresse`,
|
login_emailLabel: `E-Mail-Adresse`,
|
||||||
login_passwordLabel: `Passwort`,
|
login_passwordLabel: `Passwort`,
|
||||||
@ -109,9 +113,10 @@ dict = {
|
|||||||
inventory_moaPets: `Moas`,
|
inventory_moaPets: `Moas`,
|
||||||
inventory_kubrowPets: `Bestien`,
|
inventory_kubrowPets: `Bestien`,
|
||||||
inventory_evolutionProgress: `Incarnon-Entwicklungsfortschritte`,
|
inventory_evolutionProgress: `Incarnon-Entwicklungsfortschritte`,
|
||||||
inventory_Boosters: `Booster`,
|
inventory_boosters: `Booster`,
|
||||||
inventory_flavourItems: `<abbr title="Animationssets, Glyphen, Farbpaletten usw.">Sammlerstücke</abbr>`,
|
inventory_flavourItems: `<abbr title="Animationssets, Glyphen, Farbpaletten usw.">Sammlerstücke</abbr>`,
|
||||||
inventory_shipDecorations: `Schiffsdekorationen`,
|
inventory_shipDecorations: `Schiffsdekorationen`,
|
||||||
|
inventory_weaponSkins: `Skins`,
|
||||||
inventory_bulkAddSuits: `Fehlende Warframes hinzufügen`,
|
inventory_bulkAddSuits: `Fehlende Warframes hinzufügen`,
|
||||||
inventory_bulkAddWeapons: `Fehlende Waffen hinzufügen`,
|
inventory_bulkAddWeapons: `Fehlende Waffen hinzufügen`,
|
||||||
inventory_bulkAddSpaceSuits: `Fehlende Archwings hinzufügen`,
|
inventory_bulkAddSpaceSuits: `Fehlende Archwings hinzufügen`,
|
||||||
@ -121,6 +126,7 @@ dict = {
|
|||||||
inventory_bulkAddFlavourItems: `[UNTRANSLATED] Add Missing Flavour Items`,
|
inventory_bulkAddFlavourItems: `[UNTRANSLATED] Add Missing Flavour Items`,
|
||||||
inventory_bulkAddShipDecorations: `[UNTRANSLATED] Add Missing Ship Decorations`,
|
inventory_bulkAddShipDecorations: `[UNTRANSLATED] Add Missing Ship Decorations`,
|
||||||
inventory_bulkAddEvolutionProgress: `Fehlende Incarnon-Entwicklungsfortschritte hinzufügen`,
|
inventory_bulkAddEvolutionProgress: `Fehlende Incarnon-Entwicklungsfortschritte hinzufügen`,
|
||||||
|
inventory_bulkAddWeaponSkins: `[UNTRANSLATED] Add Missing Skins`,
|
||||||
inventory_bulkRankUpSuits: `Alle Warframes auf Max. Rang`,
|
inventory_bulkRankUpSuits: `Alle Warframes auf Max. Rang`,
|
||||||
inventory_bulkRankUpWeapons: `Alle Waffen auf Max. Rang`,
|
inventory_bulkRankUpWeapons: `Alle Waffen auf Max. Rang`,
|
||||||
inventory_bulkRankUpSpaceSuits: `Alle Archwings auf Max. Rang`,
|
inventory_bulkRankUpSpaceSuits: `Alle Archwings auf Max. Rang`,
|
||||||
@ -147,7 +153,7 @@ dict = {
|
|||||||
detailedView_valenceBonusLabel: `Valenz-Bonus`,
|
detailedView_valenceBonusLabel: `Valenz-Bonus`,
|
||||||
detailedView_valenceBonusDescription: `Du kannst den Valenz-Bonus deiner Waffe festlegen oder entfernen.`,
|
detailedView_valenceBonusDescription: `Du kannst den Valenz-Bonus deiner Waffe festlegen oder entfernen.`,
|
||||||
detailedView_modularPartsLabel: `Modulare Teile ändern`,
|
detailedView_modularPartsLabel: `Modulare Teile ändern`,
|
||||||
detailedView_suitInvigorationLabel: `Warframe-Kräftigung`,
|
detailedView_invigorationLabel: `Kräftigung`,
|
||||||
detailedView_loadoutLabel: `Loadouts`,
|
detailedView_loadoutLabel: `Loadouts`,
|
||||||
|
|
||||||
invigorations_offensive_AbilityStrength: `+200% Fähigkeitsstärke`,
|
invigorations_offensive_AbilityStrength: `+200% Fähigkeitsstärke`,
|
||||||
@ -172,9 +178,9 @@ dict = {
|
|||||||
invigorations_utility_Jumps: `+5 Sprung-Zurücksetzungen`,
|
invigorations_utility_Jumps: `+5 Sprung-Zurücksetzungen`,
|
||||||
invigorations_utility_EnergyRegen: `+2 Energieregeneration pro Sekunde`,
|
invigorations_utility_EnergyRegen: `+2 Energieregeneration pro Sekunde`,
|
||||||
|
|
||||||
invigorations_offensiveLabel: `Offensives Upgrade`,
|
detailedView_invigorationOffensiveLabel: `Offensives Upgrade`,
|
||||||
invigorations_defensiveLabel: `Defensives Upgrade`,
|
detailedView_invigorationUtilityLabel: `[UNTRANSLATED] Utility Upgrade`,
|
||||||
invigorations_expiryLabel: `Upgrades Ablaufdatum (optional)`,
|
detailedView_invigorationExpiryLabel: `[UNTRANSLATED] Invigoration Expiry (optional)`,
|
||||||
|
|
||||||
abilityOverride_label: `Fähigkeitsüberschreibung`,
|
abilityOverride_label: `Fähigkeitsüberschreibung`,
|
||||||
abilityOverride_onSlot: `auf Slot`,
|
abilityOverride_onSlot: `auf Slot`,
|
||||||
@ -193,7 +199,7 @@ dict = {
|
|||||||
cheats_skipTutorial: `Tutorial überspringen`,
|
cheats_skipTutorial: `Tutorial überspringen`,
|
||||||
cheats_skipAllDialogue: `Alle Dialoge überspringen`,
|
cheats_skipAllDialogue: `Alle Dialoge überspringen`,
|
||||||
cheats_unlockAllScans: `Alle Scans freischalten`,
|
cheats_unlockAllScans: `Alle Scans freischalten`,
|
||||||
cheats_unlockSuccRelog: `[UNTRANSLATED] Success. Please that you'll need to relog for the client to refresh this.`,
|
cheats_unlockSuccRelog: `[UNTRANSLATED] Success. Please note that you'll need to relog for the client to refresh this.`,
|
||||||
cheats_unlockAllMissions: `Alle Missionen freischalten`,
|
cheats_unlockAllMissions: `Alle Missionen freischalten`,
|
||||||
cheats_unlockAllMissions_ok: `Erfolgreich. Bitte beachte, dass du ein Dojo/Relais besuchen oder dich neu einloggen musst, damit die Sternenkarte aktualisiert wird.`,
|
cheats_unlockAllMissions_ok: `Erfolgreich. Bitte beachte, dass du ein Dojo/Relais besuchen oder dich neu einloggen musst, damit die Sternenkarte aktualisiert wird.`,
|
||||||
cheats_infiniteCredits: `Unendlich Credits`,
|
cheats_infiniteCredits: `Unendlich Credits`,
|
||||||
@ -227,7 +233,7 @@ dict = {
|
|||||||
cheats_baroFullyStocked: `Baro hat volles Inventar`,
|
cheats_baroFullyStocked: `Baro hat volles Inventar`,
|
||||||
cheats_syndicateMissionsRepeatable: `Syndikat-Missionen wiederholbar`,
|
cheats_syndicateMissionsRepeatable: `Syndikat-Missionen wiederholbar`,
|
||||||
cheats_unlockAllProfitTakerStages: `Alle Profiteintreiber-Phasen freischalten`,
|
cheats_unlockAllProfitTakerStages: `Alle Profiteintreiber-Phasen freischalten`,
|
||||||
cheats_unlockSuccInventory: `[UNTRANSLATED] Success. Please note that you'll need to resync your inventory, e.g. using the bootstrapper's /sync command, visiting a dojo/relay, or relogging..`,
|
cheats_unlockSuccInventory: `[UNTRANSLATED] Success. Please note that you'll need to resync your inventory, e.g. using the bootstrapper's /sync command in game chat, visiting a dojo/relay, or relogging.`,
|
||||||
cheats_instantFinishRivenChallenge: `Riven-Mod Herausforderung sofort abschließen`,
|
cheats_instantFinishRivenChallenge: `Riven-Mod Herausforderung sofort abschließen`,
|
||||||
cheats_instantResourceExtractorDrones: `Sofortige Ressourcen-Extraktor-Drohnen`,
|
cheats_instantResourceExtractorDrones: `Sofortige Ressourcen-Extraktor-Drohnen`,
|
||||||
cheats_noResourceExtractorDronesDamage: `Kein Schaden für Ressourcen-Extraktor-Drohnen`,
|
cheats_noResourceExtractorDronesDamage: `Kein Schaden für Ressourcen-Extraktor-Drohnen`,
|
||||||
@ -257,6 +263,12 @@ dict = {
|
|||||||
cheats_changeButton: `Ändern`,
|
cheats_changeButton: `Ändern`,
|
||||||
cheats_markAllAsRead: `Posteingang als gelesen markieren`,
|
cheats_markAllAsRead: `Posteingang als gelesen markieren`,
|
||||||
cheats_finishInvasionsInOneMission: `[UNTRANSLATED] Finish Invasions in One Mission`,
|
cheats_finishInvasionsInOneMission: `[UNTRANSLATED] Finish Invasions in One Mission`,
|
||||||
|
cheats_nemesisHenchmenKillsMultiplierGrineer: `[UNTRANSLATED] Rage Progess Multiplier (Grineer)`,
|
||||||
|
cheats_nemesisHenchmenKillsMultiplierCorpus: `[UNTRANSLATED] Rage Progess Multiplier (Corpus)`,
|
||||||
|
cheats_nemesisAntivirusGainMultiplier: `[UNTRANSLATED] Antivirus Progress Multiplier`,
|
||||||
|
cheats_nemesisHintProgressMultiplierGrineer: `[UNTRANSLATED] Hint Progress Multiplier (Grineer)`,
|
||||||
|
cheats_nemesisHintProgressMultiplierCorpus: `[UNTRANSLATED] Hint Progress Multiplier (Corpus)`,
|
||||||
|
cheats_nemesisExtraWeapon: `[UNTRANSLATED] Extra Nemesis Weapon / Token On Vanquish (0 to disable)`,
|
||||||
|
|
||||||
worldState: `Weltstatus`,
|
worldState: `Weltstatus`,
|
||||||
worldState_creditBoost: `Event Booster: Credit`,
|
worldState_creditBoost: `Event Booster: Credit`,
|
||||||
@ -273,11 +285,13 @@ dict = {
|
|||||||
worldState_dogDays: `Hitzefrei`,
|
worldState_dogDays: `Hitzefrei`,
|
||||||
worldState_dogDaysRewards: `[UNTRANSLATED] Dog Days Rewards`,
|
worldState_dogDaysRewards: `[UNTRANSLATED] Dog Days Rewards`,
|
||||||
worldState_wolfHunt: `Wolfsjagd (2025)`,
|
worldState_wolfHunt: `Wolfsjagd (2025)`,
|
||||||
|
worldState_voidCorruption: `Void-Korruption (|VAL|)`,
|
||||||
worldState_orphixVenom: `Orphix Gift`,
|
worldState_orphixVenom: `Orphix Gift`,
|
||||||
worldState_longShadow: `Lange Schatten`,
|
worldState_longShadow: `Lange Schatten`,
|
||||||
worldState_hallowedFlame: `Geweihte Flamme`,
|
worldState_hallowedFlame: `Geweihte Flamme`,
|
||||||
worldState_hallowedNightmares: `Geweihte Albträume`,
|
worldState_hallowedNightmares: `Geweihte Albträume`,
|
||||||
worldState_hallowedNightmaresRewards: `[UNTRANSLATED] Hallowed Nightmares Rewards`,
|
worldState_hallowedNightmaresRewards: `[UNTRANSLATED] Hallowed Nightmares Rewards`,
|
||||||
|
worldState_naberusNights: `[UNTRANSLATED] Nights of Naberus`,
|
||||||
worldState_proxyRebellion: `Proxy-Rebellion`,
|
worldState_proxyRebellion: `Proxy-Rebellion`,
|
||||||
worldState_proxyRebellionRewards: `[UNTRANSLATED] Proxy Rebellion Rewards`,
|
worldState_proxyRebellionRewards: `[UNTRANSLATED] Proxy Rebellion Rewards`,
|
||||||
worldState_bellyOfTheBeast: `Das Innere der Bestie`,
|
worldState_bellyOfTheBeast: `Das Innere der Bestie`,
|
||||||
@ -286,6 +300,7 @@ dict = {
|
|||||||
worldState_eightClawProgressOverride: `[UNTRANSLATED] Eight Claw Progress`,
|
worldState_eightClawProgressOverride: `[UNTRANSLATED] Eight Claw Progress`,
|
||||||
worldState_thermiaFractures: `Thermische Risse`,
|
worldState_thermiaFractures: `Thermische Risse`,
|
||||||
worldState_thermiaFracturesProgressOverride: `[UNTRANSLATED] Thermia Fractures Progress`,
|
worldState_thermiaFracturesProgressOverride: `[UNTRANSLATED] Thermia Fractures Progress`,
|
||||||
|
worldState_qtccAlerts: `[UNTRANSLATED] Quest to Conquer Cancer Alerts`,
|
||||||
worldState_from_year: `[UNTRANSLATED] from |VAL|`,
|
worldState_from_year: `[UNTRANSLATED] from |VAL|`,
|
||||||
worldState_pre_year: `[UNTRANSLATED] pre |VAL|`,
|
worldState_pre_year: `[UNTRANSLATED] pre |VAL|`,
|
||||||
worldState_week: `[UNTRANSLATED] Week |VAL|`,
|
worldState_week: `[UNTRANSLATED] Week |VAL|`,
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
dict = {
|
dict = {
|
||||||
general_inventoryUpdateNote: `Note: To see changes in-game, you need to resync your inventory, e.g. using the bootstrapper's /sync command, visiting a dojo/relay, or relogging.`,
|
general_inventoryUpdateNote: `Note: To see changes in-game, you need to resync your inventory, e.g. using the bootstrapper's /sync command in game chat, visiting a dojo/relay, or relogging.`,
|
||||||
general_inventoryUpdateNoteGameWs: `Note: You may need to reopen any menu you are on for changes to be reflected.`,
|
general_inventoryUpdateNoteGameWs: `Note: You may need to reopen any menu you are on for changes to be reflected.`,
|
||||||
general_addButton: `Add`,
|
general_addButton: `Add`,
|
||||||
general_setButton: `Set`,
|
general_setButton: `Set`,
|
||||||
@ -74,8 +74,12 @@ dict = {
|
|||||||
code_funded: `Funded`,
|
code_funded: `Funded`,
|
||||||
code_replays: `Replays`,
|
code_replays: `Replays`,
|
||||||
code_stalker: `Stalker`,
|
code_stalker: `Stalker`,
|
||||||
|
code_cutName: `Cut |INDEX|`,
|
||||||
|
code_drifterBeardName: `Drifter Beard |INDEX|`,
|
||||||
|
code_drifterFaceName: `Drifter Visage |INDEX|`,
|
||||||
|
code_operatorFaceName: `Operator Visage |INDEX|`,
|
||||||
code_succChange: `Successfully changed.`,
|
code_succChange: `Successfully changed.`,
|
||||||
code_requiredInvigorationUpgrade: `You must select both an offensive & defensive upgrade.`,
|
code_requiredInvigorationUpgrade: `You must select both an offensive & utility upgrade.`,
|
||||||
login_description: `Login using your OpenWF account credentials (same as in-game when connecting to this server).`,
|
login_description: `Login using your OpenWF account credentials (same as in-game when connecting to this server).`,
|
||||||
login_emailLabel: `Email address`,
|
login_emailLabel: `Email address`,
|
||||||
login_passwordLabel: `Password`,
|
login_passwordLabel: `Password`,
|
||||||
@ -108,9 +112,10 @@ dict = {
|
|||||||
inventory_moaPets: `Moas`,
|
inventory_moaPets: `Moas`,
|
||||||
inventory_kubrowPets: `Beasts`,
|
inventory_kubrowPets: `Beasts`,
|
||||||
inventory_evolutionProgress: `Incarnon Evolution Progress`,
|
inventory_evolutionProgress: `Incarnon Evolution Progress`,
|
||||||
inventory_Boosters: `Boosters`,
|
inventory_boosters: `Boosters`,
|
||||||
inventory_flavourItems: `<abbr title="Animation Sets, Glyphs, Palettes, etc.">Flavour Items</abbr>`,
|
inventory_flavourItems: `<abbr title="Animation Sets, Glyphs, Palettes, etc.">Flavour Items</abbr>`,
|
||||||
inventory_shipDecorations: `Ship Decorations`,
|
inventory_shipDecorations: `Ship Decorations`,
|
||||||
|
inventory_weaponSkins: `Skins`,
|
||||||
inventory_bulkAddSuits: `Add Missing Warframes`,
|
inventory_bulkAddSuits: `Add Missing Warframes`,
|
||||||
inventory_bulkAddWeapons: `Add Missing Weapons`,
|
inventory_bulkAddWeapons: `Add Missing Weapons`,
|
||||||
inventory_bulkAddSpaceSuits: `Add Missing Archwings`,
|
inventory_bulkAddSpaceSuits: `Add Missing Archwings`,
|
||||||
@ -120,6 +125,7 @@ dict = {
|
|||||||
inventory_bulkAddFlavourItems: `Add Missing Flavour Items`,
|
inventory_bulkAddFlavourItems: `Add Missing Flavour Items`,
|
||||||
inventory_bulkAddShipDecorations: `Add Missing Ship Decorations`,
|
inventory_bulkAddShipDecorations: `Add Missing Ship Decorations`,
|
||||||
inventory_bulkAddEvolutionProgress: `Add Missing Incarnon Evolution Progress`,
|
inventory_bulkAddEvolutionProgress: `Add Missing Incarnon Evolution Progress`,
|
||||||
|
inventory_bulkAddWeaponSkins: `Add Missing Skins`,
|
||||||
inventory_bulkRankUpSuits: `Max Rank All Warframes`,
|
inventory_bulkRankUpSuits: `Max Rank All Warframes`,
|
||||||
inventory_bulkRankUpWeapons: `Max Rank All Weapons`,
|
inventory_bulkRankUpWeapons: `Max Rank All Weapons`,
|
||||||
inventory_bulkRankUpSpaceSuits: `Max Rank All Archwings`,
|
inventory_bulkRankUpSpaceSuits: `Max Rank All Archwings`,
|
||||||
@ -146,7 +152,7 @@ dict = {
|
|||||||
detailedView_valenceBonusLabel: `Valence Bonus`,
|
detailedView_valenceBonusLabel: `Valence Bonus`,
|
||||||
detailedView_valenceBonusDescription: `You can set or remove the Valence Bonus from your weapon.`,
|
detailedView_valenceBonusDescription: `You can set or remove the Valence Bonus from your weapon.`,
|
||||||
detailedView_modularPartsLabel: `Change Modular Parts`,
|
detailedView_modularPartsLabel: `Change Modular Parts`,
|
||||||
detailedView_suitInvigorationLabel: `Warframe Invigoration`,
|
detailedView_invigorationLabel: `Invigoration`,
|
||||||
detailedView_loadoutLabel: `Loadouts`,
|
detailedView_loadoutLabel: `Loadouts`,
|
||||||
|
|
||||||
invigorations_offensive_AbilityStrength: `+200% Ability Strength`,
|
invigorations_offensive_AbilityStrength: `+200% Ability Strength`,
|
||||||
@ -171,9 +177,9 @@ dict = {
|
|||||||
invigorations_utility_Jumps: `+5 Jump Resets`,
|
invigorations_utility_Jumps: `+5 Jump Resets`,
|
||||||
invigorations_utility_EnergyRegen: `+2 Energy Regen/s`,
|
invigorations_utility_EnergyRegen: `+2 Energy Regen/s`,
|
||||||
|
|
||||||
invigorations_offensiveLabel: `Offensive Upgrade`,
|
detailedView_invigorationOffensiveLabel: `Offensive Upgrade`,
|
||||||
invigorations_defensiveLabel: `Defensive Upgrade`,
|
detailedView_invigorationUtilityLabel: `Utility Upgrade`,
|
||||||
invigorations_expiryLabel: `Upgrades Expiry (optional)`,
|
detailedView_invigorationExpiryLabel: `Invigoration Expiry (optional)`,
|
||||||
|
|
||||||
abilityOverride_label: `Ability Override`,
|
abilityOverride_label: `Ability Override`,
|
||||||
abilityOverride_onSlot: `on slot`,
|
abilityOverride_onSlot: `on slot`,
|
||||||
@ -192,7 +198,7 @@ dict = {
|
|||||||
cheats_skipTutorial: `Skip Tutorial`,
|
cheats_skipTutorial: `Skip Tutorial`,
|
||||||
cheats_skipAllDialogue: `Skip All Dialogue`,
|
cheats_skipAllDialogue: `Skip All Dialogue`,
|
||||||
cheats_unlockAllScans: `Unlock All Scans`,
|
cheats_unlockAllScans: `Unlock All Scans`,
|
||||||
cheats_unlockSuccRelog: `Success. Please that you'll need to relog for the client to refresh this.`,
|
cheats_unlockSuccRelog: `Success. Please note that you'll need to relog for the client to refresh this.`,
|
||||||
cheats_unlockAllMissions: `Unlock All Missions`,
|
cheats_unlockAllMissions: `Unlock All Missions`,
|
||||||
cheats_unlockAllMissions_ok: `Success. Please note that you'll need to enter a dojo/relay or relog for the client to refresh the star chart.`,
|
cheats_unlockAllMissions_ok: `Success. Please note that you'll need to enter a dojo/relay or relog for the client to refresh the star chart.`,
|
||||||
cheats_infiniteCredits: `Infinite Credits`,
|
cheats_infiniteCredits: `Infinite Credits`,
|
||||||
@ -226,7 +232,7 @@ dict = {
|
|||||||
cheats_baroFullyStocked: `Baro Fully Stocked`,
|
cheats_baroFullyStocked: `Baro Fully Stocked`,
|
||||||
cheats_syndicateMissionsRepeatable: `Syndicate Missions Repeatable`,
|
cheats_syndicateMissionsRepeatable: `Syndicate Missions Repeatable`,
|
||||||
cheats_unlockAllProfitTakerStages: `Unlock All Profit Taker Stages`,
|
cheats_unlockAllProfitTakerStages: `Unlock All Profit Taker Stages`,
|
||||||
cheats_unlockSuccInventory: `Success. Please note that you'll need to resync your inventory, e.g. using the bootstrapper's /sync command, visiting a dojo/relay, or relogging..`,
|
cheats_unlockSuccInventory: `Success. Please note that you'll need to resync your inventory, e.g. using the bootstrapper's /sync command in game chat, visiting a dojo/relay, or relogging.`,
|
||||||
cheats_instantFinishRivenChallenge: `Instant Finish Riven Challenge`,
|
cheats_instantFinishRivenChallenge: `Instant Finish Riven Challenge`,
|
||||||
cheats_instantResourceExtractorDrones: `Instant Resource Extractor Drones`,
|
cheats_instantResourceExtractorDrones: `Instant Resource Extractor Drones`,
|
||||||
cheats_noResourceExtractorDronesDamage: `No Resource Extractor Drones Damage`,
|
cheats_noResourceExtractorDronesDamage: `No Resource Extractor Drones Damage`,
|
||||||
@ -256,6 +262,12 @@ dict = {
|
|||||||
cheats_changeButton: `Change`,
|
cheats_changeButton: `Change`,
|
||||||
cheats_markAllAsRead: `Mark Inbox As Read`,
|
cheats_markAllAsRead: `Mark Inbox As Read`,
|
||||||
cheats_finishInvasionsInOneMission: `Finish Invasions in One Mission`,
|
cheats_finishInvasionsInOneMission: `Finish Invasions in One Mission`,
|
||||||
|
cheats_nemesisHenchmenKillsMultiplierGrineer: `Rage Progess Multiplier (Grineer)`,
|
||||||
|
cheats_nemesisHenchmenKillsMultiplierCorpus: `Rage Progess Multiplier (Corpus)`,
|
||||||
|
cheats_nemesisAntivirusGainMultiplier: `Antivirus Progress Multiplier`,
|
||||||
|
cheats_nemesisHintProgressMultiplierGrineer: `Hint Progress Multiplier (Grineer)`,
|
||||||
|
cheats_nemesisHintProgressMultiplierCorpus: `Hint Progress Multiplier (Corpus)`,
|
||||||
|
cheats_nemesisExtraWeapon: `Extra Nemesis Weapon / Token On Vanquish (0 to disable)`,
|
||||||
|
|
||||||
worldState: `World State`,
|
worldState: `World State`,
|
||||||
worldState_creditBoost: `Credit Boost`,
|
worldState_creditBoost: `Credit Boost`,
|
||||||
@ -272,11 +284,13 @@ dict = {
|
|||||||
worldState_dogDays: `Dog Days`,
|
worldState_dogDays: `Dog Days`,
|
||||||
worldState_dogDaysRewards: `Dog Days Rewards`,
|
worldState_dogDaysRewards: `Dog Days Rewards`,
|
||||||
worldState_wolfHunt: `Wolf Hunt (2025)`,
|
worldState_wolfHunt: `Wolf Hunt (2025)`,
|
||||||
|
worldState_voidCorruption: `Void Corruption (|VAL|)`,
|
||||||
worldState_orphixVenom: `Orphix Venom`,
|
worldState_orphixVenom: `Orphix Venom`,
|
||||||
worldState_longShadow: `Long Shadow`,
|
worldState_longShadow: `Long Shadow`,
|
||||||
worldState_hallowedFlame: `Hallowed Flame`,
|
worldState_hallowedFlame: `Hallowed Flame`,
|
||||||
worldState_hallowedNightmares: `Hallowed Nightmares`,
|
worldState_hallowedNightmares: `Hallowed Nightmares`,
|
||||||
worldState_hallowedNightmaresRewards: `Hallowed Nightmares Rewards`,
|
worldState_hallowedNightmaresRewards: `Hallowed Nightmares Rewards`,
|
||||||
|
worldState_naberusNights: `Nights of Naberus`,
|
||||||
worldState_proxyRebellion: `Proxy Rebellion`,
|
worldState_proxyRebellion: `Proxy Rebellion`,
|
||||||
worldState_proxyRebellionRewards: `Proxy Rebellion Rewards`,
|
worldState_proxyRebellionRewards: `Proxy Rebellion Rewards`,
|
||||||
worldState_bellyOfTheBeast: `Belly of the Beast`,
|
worldState_bellyOfTheBeast: `Belly of the Beast`,
|
||||||
@ -285,6 +299,7 @@ dict = {
|
|||||||
worldState_eightClawProgressOverride: `Eight Claw Progress`,
|
worldState_eightClawProgressOverride: `Eight Claw Progress`,
|
||||||
worldState_thermiaFractures: `Thermia Fractures`,
|
worldState_thermiaFractures: `Thermia Fractures`,
|
||||||
worldState_thermiaFracturesProgressOverride: `Thermia Fractures Progress`,
|
worldState_thermiaFracturesProgressOverride: `Thermia Fractures Progress`,
|
||||||
|
worldState_qtccAlerts: `Quest to Conquer Cancer Alerts`,
|
||||||
worldState_from_year: `from |VAL|`,
|
worldState_from_year: `from |VAL|`,
|
||||||
worldState_pre_year: `pre |VAL|`,
|
worldState_pre_year: `pre |VAL|`,
|
||||||
worldState_week: `Week |VAL|`,
|
worldState_week: `Week |VAL|`,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// Spanish translation by hxedcl
|
// Spanish translation by hxedcl, Slayer55555
|
||||||
dict = {
|
dict = {
|
||||||
general_inventoryUpdateNote: `Para ver los cambios en el juego, necesitas volver a sincronizar tu inventario, por ejemplo, usando el comando /sync del bootstrapper, visitando un dojo o repetidor, o volviendo a iniciar sesión.`,
|
general_inventoryUpdateNote: `Para ver los cambios en el juego, necesitas volver a sincronizar tu inventario, por ejemplo, usando el comando /sync del bootstrapper, visitando un dojo o repetidor, o volviendo a iniciar sesión.`,
|
||||||
general_inventoryUpdateNoteGameWs: `[UNTRANSLATED] Note: You may need to reopen any menu you are on for changes to be reflected.`,
|
general_inventoryUpdateNoteGameWs: `Nota: Puede que necesites reabrir cualquier menú en el que te encuentres para que los cambios se reflejen.`,
|
||||||
general_addButton: `Agregar`,
|
general_addButton: `Agregar`,
|
||||||
general_setButton: `Establecer`,
|
general_setButton: `Establecer`,
|
||||||
general_none: `Ninguno`,
|
general_none: `Ninguno`,
|
||||||
@ -32,8 +32,8 @@ dict = {
|
|||||||
code_renamePrompt: `Escribe tu nuevo nombre personalizado:`,
|
code_renamePrompt: `Escribe tu nuevo nombre personalizado:`,
|
||||||
code_remove: `Quitar`,
|
code_remove: `Quitar`,
|
||||||
code_addItemsConfirm: `¿Estás seguro de que deseas agregar |COUNT| objetos a tu cuenta?`,
|
code_addItemsConfirm: `¿Estás seguro de que deseas agregar |COUNT| objetos a tu cuenta?`,
|
||||||
code_addTechProjectsConfirm: `[UNTRANSLATED] Are you sure you want to add |COUNT| research to your clan?`,
|
code_addTechProjectsConfirm: `¿Estás seguro de que quieres añadir |COUNT| proyectos de investigación a tu clan?`,
|
||||||
code_addDecoRecipesConfirm: `[UNTRANSLATED] Are you sure you want to add |COUNT| deco recipes to your clan?`,
|
code_addDecoRecipesConfirm: `¿Estás seguro de que quieres añadir |COUNT| planos de decoración a tu clan?`,
|
||||||
code_succRankUp: `Ascenso exitoso.`,
|
code_succRankUp: `Ascenso exitoso.`,
|
||||||
code_noEquipmentToRankUp: `No hay equipo para ascender.`,
|
code_noEquipmentToRankUp: `No hay equipo para ascender.`,
|
||||||
code_succAdded: `Agregado exitosamente.`,
|
code_succAdded: `Agregado exitosamente.`,
|
||||||
@ -45,7 +45,7 @@ dict = {
|
|||||||
code_rank: `Rango`,
|
code_rank: `Rango`,
|
||||||
code_rankUp: `Subir de rango`,
|
code_rankUp: `Subir de rango`,
|
||||||
code_rankDown: `Bajar de rango`,
|
code_rankDown: `Bajar de rango`,
|
||||||
code_unlockLevelCap: `[UNTRANSLATED] Unlock level cap`,
|
code_unlockLevelCap: `Desbloquear level cap`,
|
||||||
code_count: `Cantidad`,
|
code_count: `Cantidad`,
|
||||||
code_focusAllUnlocked: `Todas las escuelas de enfoque ya están desbloqueadas.`,
|
code_focusAllUnlocked: `Todas las escuelas de enfoque ya están desbloqueadas.`,
|
||||||
code_focusUnlocked: `¡Desbloqueadas |COUNT| nuevas escuelas de enfoque! Se necesita una actualización del inventario para reflejar los cambios en el juego. Visitar la navegación debería ser la forma más sencilla de activarlo.`,
|
code_focusUnlocked: `¡Desbloqueadas |COUNT| nuevas escuelas de enfoque! Se necesita una actualización del inventario para reflejar los cambios en el juego. Visitar la navegación debería ser la forma más sencilla de activarlo.`,
|
||||||
@ -65,18 +65,22 @@ dict = {
|
|||||||
code_completed: `Completada`,
|
code_completed: `Completada`,
|
||||||
code_active: `Activa`,
|
code_active: `Activa`,
|
||||||
code_pigment: `Pigmento`,
|
code_pigment: `Pigmento`,
|
||||||
code_controller: `[UNTRANSLATED] Controller cursor`,
|
code_controller: `Cursor de Mando`,
|
||||||
code_mouseLine: `[UNTRANSLATED] Line cursor`,
|
code_mouseLine: `Cursor de línea`,
|
||||||
code_mouse: `[UNTRANSLATED] Cursor`,
|
code_mouse: `Cursor`,
|
||||||
code_itemColorPalette: `Paleta de colores |ITEM|`,
|
code_itemColorPalette: `Paleta de colores |ITEM|`,
|
||||||
code_mature: `Listo para el combate`,
|
code_mature: `Listo para el combate`,
|
||||||
code_unmature: `Regresar el envejecimiento genético`,
|
code_unmature: `Regresar el envejecimiento genético`,
|
||||||
code_fund: `[UNTRANSLATED] Fund`,
|
code_fund: `Financiar`,
|
||||||
code_funded: `[UNTRANSLATED] Funded`,
|
code_funded: `Financiado`,
|
||||||
code_replays: `[UNTRANSLATED] Replays`,
|
code_replays: `Repeticiones`,
|
||||||
code_stalker: `Stalker`,
|
code_stalker: `Stalker`,
|
||||||
|
code_cutName: `[UNTRANSLATED] Cut |INDEX|`,
|
||||||
|
code_drifterBeardName: `Barba del Viajero: |INDEX|`,
|
||||||
|
code_drifterFaceName: `Rostro del Viajero |INDEX|`,
|
||||||
|
code_operatorFaceName: `Rostro del operador |INDEX|`,
|
||||||
code_succChange: `Cambiado correctamente`,
|
code_succChange: `Cambiado correctamente`,
|
||||||
code_requiredInvigorationUpgrade: `Debes seleccionar una mejora ofensiva y una defensiva.`,
|
code_requiredInvigorationUpgrade: `Debes seleccionar una mejora ofensiva y una mejora de utilidad.`,
|
||||||
login_description: `Inicia sesión con las credenciales de tu cuenta OpenWF (las mismas que usas en el juego al conectarte a este servidor).`,
|
login_description: `Inicia sesión con las credenciales de tu cuenta OpenWF (las mismas que usas en el juego al conectarte a este servidor).`,
|
||||||
login_emailLabel: `Dirección de correo electrónico`,
|
login_emailLabel: `Dirección de correo electrónico`,
|
||||||
login_passwordLabel: `Contraseña`,
|
login_passwordLabel: `Contraseña`,
|
||||||
@ -109,18 +113,20 @@ dict = {
|
|||||||
inventory_moaPets: `Moas`,
|
inventory_moaPets: `Moas`,
|
||||||
inventory_kubrowPets: `Bestias`,
|
inventory_kubrowPets: `Bestias`,
|
||||||
inventory_evolutionProgress: `Progreso de evolución Incarnon`,
|
inventory_evolutionProgress: `Progreso de evolución Incarnon`,
|
||||||
inventory_Boosters: `Potenciadores`,
|
inventory_boosters: `Potenciadores`,
|
||||||
inventory_flavourItems: `<abbr title="Conjuntos de animaciones, glifos, paletas, etc.">Ítems estéticos</abbr>`,
|
inventory_flavourItems: `<abbr title="Conjuntos de animaciones, glifos, paletas, etc.">Ítems estéticos</abbr>`,
|
||||||
inventory_shipDecorations: `Decoraciones de nave`,
|
inventory_shipDecorations: `Decoraciones de nave`,
|
||||||
|
inventory_weaponSkins: `Diseños`,
|
||||||
inventory_bulkAddSuits: `Agregar Warframes faltantes`,
|
inventory_bulkAddSuits: `Agregar Warframes faltantes`,
|
||||||
inventory_bulkAddWeapons: `Agregar armas faltantes`,
|
inventory_bulkAddWeapons: `Agregar armas faltantes`,
|
||||||
inventory_bulkAddSpaceSuits: `Agregar Archwings faltantes`,
|
inventory_bulkAddSpaceSuits: `Agregar Archwings faltantes`,
|
||||||
inventory_bulkAddSpaceWeapons: `Agregar armas Archwing faltantes`,
|
inventory_bulkAddSpaceWeapons: `Agregar armas Archwing faltantes`,
|
||||||
inventory_bulkAddSentinels: `Agregar centinelas faltantes`,
|
inventory_bulkAddSentinels: `Agregar centinelas faltantes`,
|
||||||
inventory_bulkAddSentinelWeapons: `Agregar armas de centinela faltantes`,
|
inventory_bulkAddSentinelWeapons: `Agregar armas de centinela faltantes`,
|
||||||
inventory_bulkAddFlavourItems: `[UNTRANSLATED] Add Missing Flavour Items`,
|
inventory_bulkAddFlavourItems: `Añadir items estéticos faltantes`,
|
||||||
inventory_bulkAddShipDecorations: `[UNTRANSLATED] Add Missing Ship Decorations`,
|
inventory_bulkAddShipDecorations: `Añadir decoraciones de Nave Faltantes`,
|
||||||
inventory_bulkAddEvolutionProgress: `Completar el progreso de evolución Incarnon faltante`,
|
inventory_bulkAddEvolutionProgress: `Completar el progreso de evolución Incarnon faltante`,
|
||||||
|
inventory_bulkAddWeaponSkins: `[UNTRANSLATED] Add Missing Skins`,
|
||||||
inventory_bulkRankUpSuits: `Maximizar rango de todos los Warframes`,
|
inventory_bulkRankUpSuits: `Maximizar rango de todos los Warframes`,
|
||||||
inventory_bulkRankUpWeapons: `Maximizar rango de todas las armas`,
|
inventory_bulkRankUpWeapons: `Maximizar rango de todas las armas`,
|
||||||
inventory_bulkRankUpSpaceSuits: `Maximizar rango de todos los Archwings`,
|
inventory_bulkRankUpSpaceSuits: `Maximizar rango de todos los Archwings`,
|
||||||
@ -147,7 +153,7 @@ dict = {
|
|||||||
detailedView_valenceBonusLabel: `Bonus de Valéncia`,
|
detailedView_valenceBonusLabel: `Bonus de Valéncia`,
|
||||||
detailedView_valenceBonusDescription: `Puedes establecer o quitar el bonus de valencia de tu arma.`,
|
detailedView_valenceBonusDescription: `Puedes establecer o quitar el bonus de valencia de tu arma.`,
|
||||||
detailedView_modularPartsLabel: `Cambiar partes modulares`,
|
detailedView_modularPartsLabel: `Cambiar partes modulares`,
|
||||||
detailedView_suitInvigorationLabel: `Vigorización de Warframe`,
|
detailedView_invigorationLabel: `Fortalecimiento`,
|
||||||
detailedView_loadoutLabel: `Equipamientos`,
|
detailedView_loadoutLabel: `Equipamientos`,
|
||||||
|
|
||||||
invigorations_offensive_AbilityStrength: `+200% Fuerza de Habilidad`,
|
invigorations_offensive_AbilityStrength: `+200% Fuerza de Habilidad`,
|
||||||
@ -172,9 +178,9 @@ dict = {
|
|||||||
invigorations_utility_Jumps: `+5 Restablecimientos de Salto`,
|
invigorations_utility_Jumps: `+5 Restablecimientos de Salto`,
|
||||||
invigorations_utility_EnergyRegen: `+2 Regeneración de Energía/s`,
|
invigorations_utility_EnergyRegen: `+2 Regeneración de Energía/s`,
|
||||||
|
|
||||||
invigorations_offensiveLabel: `Mejora Ofensiva`,
|
detailedView_invigorationOffensiveLabel: `Mejora Ofensiva`,
|
||||||
invigorations_defensiveLabel: `Mejora Defensiva`,
|
detailedView_invigorationUtilityLabel: `Mejora de Utilidad`,
|
||||||
invigorations_expiryLabel: `Caducidad de Mejoras (opcional)`,
|
detailedView_invigorationExpiryLabel: `Caducidad del Fortalecimiento (opcional)`,
|
||||||
|
|
||||||
abilityOverride_label: `Intercambio de Habilidad`,
|
abilityOverride_label: `Intercambio de Habilidad`,
|
||||||
abilityOverride_onSlot: `en el espacio`,
|
abilityOverride_onSlot: `en el espacio`,
|
||||||
@ -257,6 +263,12 @@ dict = {
|
|||||||
cheats_changeButton: `Cambiar`,
|
cheats_changeButton: `Cambiar`,
|
||||||
cheats_markAllAsRead: `Marcar bandeja de entrada como leída`,
|
cheats_markAllAsRead: `Marcar bandeja de entrada como leída`,
|
||||||
cheats_finishInvasionsInOneMission: `Finaliza Invasión en una mision`,
|
cheats_finishInvasionsInOneMission: `Finaliza Invasión en una mision`,
|
||||||
|
cheats_nemesisHenchmenKillsMultiplierGrineer: `[UNTRANSLATED] Rage Progess Multiplier (Grineer)`,
|
||||||
|
cheats_nemesisHenchmenKillsMultiplierCorpus: `[UNTRANSLATED] Rage Progess Multiplier (Corpus)`,
|
||||||
|
cheats_nemesisAntivirusGainMultiplier: `[UNTRANSLATED] Antivirus Progress Multiplier`,
|
||||||
|
cheats_nemesisHintProgressMultiplierGrineer: `[UNTRANSLATED] Hint Progress Multiplier (Grineer)`,
|
||||||
|
cheats_nemesisHintProgressMultiplierCorpus: `[UNTRANSLATED] Hint Progress Multiplier (Corpus)`,
|
||||||
|
cheats_nemesisExtraWeapon: `[UNTRANSLATED] Extra Nemesis Weapon / Token On Vanquish (0 to disable)`,
|
||||||
|
|
||||||
worldState: `Estado del mundo`,
|
worldState: `Estado del mundo`,
|
||||||
worldState_creditBoost: `Potenciador de Créditos`,
|
worldState_creditBoost: `Potenciador de Créditos`,
|
||||||
@ -273,11 +285,13 @@ dict = {
|
|||||||
worldState_dogDays: `Canícula`,
|
worldState_dogDays: `Canícula`,
|
||||||
worldState_dogDaysRewards: `Recompensas de Canícula`,
|
worldState_dogDaysRewards: `Recompensas de Canícula`,
|
||||||
worldState_wolfHunt: `Cacería del Lobo (2025)`,
|
worldState_wolfHunt: `Cacería del Lobo (2025)`,
|
||||||
|
worldState_voidCorruption: `Corrupción del Vacío (|VAL|)`,
|
||||||
worldState_orphixVenom: `Veneno de Orphix`,
|
worldState_orphixVenom: `Veneno de Orphix`,
|
||||||
worldState_longShadow: `Sombra Prolongada`,
|
worldState_longShadow: `Sombra Prolongada`,
|
||||||
worldState_hallowedFlame: `Llama Sagrada`,
|
worldState_hallowedFlame: `Llama Sagrada`,
|
||||||
worldState_hallowedNightmares: `Pesadillas Sagradas`,
|
worldState_hallowedNightmares: `Pesadillas Sagradas`,
|
||||||
worldState_hallowedNightmaresRewards: `Recompensas de Pesadillas Sagradas`,
|
worldState_hallowedNightmaresRewards: `Recompensas de Pesadillas Sagradas`,
|
||||||
|
worldState_naberusNights: `Noches de Naberus`,
|
||||||
worldState_proxyRebellion: `Rebelión Proxy`,
|
worldState_proxyRebellion: `Rebelión Proxy`,
|
||||||
worldState_proxyRebellionRewards: `Recompensas de Rebelión Proxy`,
|
worldState_proxyRebellionRewards: `Recompensas de Rebelión Proxy`,
|
||||||
worldState_bellyOfTheBeast: `Vientre de la Bestia`,
|
worldState_bellyOfTheBeast: `Vientre de la Bestia`,
|
||||||
@ -286,6 +300,7 @@ dict = {
|
|||||||
worldState_eightClawProgressOverride: `Progreso de Octava Garra`,
|
worldState_eightClawProgressOverride: `Progreso de Octava Garra`,
|
||||||
worldState_thermiaFractures: `Fracturas Thermia`,
|
worldState_thermiaFractures: `Fracturas Thermia`,
|
||||||
worldState_thermiaFracturesProgressOverride: `Progreso de Fracturas Thermia`,
|
worldState_thermiaFracturesProgressOverride: `Progreso de Fracturas Thermia`,
|
||||||
|
worldState_qtccAlerts: `[UNTRANSLATED] Quest to Conquer Cancer Alerts`,
|
||||||
worldState_from_year: `de |VAL|`,
|
worldState_from_year: `de |VAL|`,
|
||||||
worldState_pre_year: `antes de |VAL|`,
|
worldState_pre_year: `antes de |VAL|`,
|
||||||
worldState_week: `Semana |VAL|`,
|
worldState_week: `Semana |VAL|`,
|
||||||
@ -401,9 +416,9 @@ dict = {
|
|||||||
theme_dark: `Tema Oscuro`,
|
theme_dark: `Tema Oscuro`,
|
||||||
theme_light: `Tema Claro`,
|
theme_light: `Tema Claro`,
|
||||||
|
|
||||||
guildView_cheats: `[UNTRANSLATED] Clan Cheats`,
|
guildView_cheats: `Trucos de Clan`,
|
||||||
guildView_techProjects: `Investigación`,
|
guildView_techProjects: `Investigación`,
|
||||||
guildView_vaultDecoRecipes: `[UNTRANSLATED] Dojo Deco Recipes`,
|
guildView_vaultDecoRecipes: `Planos de Decoración de Dojo`,
|
||||||
guildView_alliance: `Alianza`,
|
guildView_alliance: `Alianza`,
|
||||||
guildView_members: `Miembros`,
|
guildView_members: `Miembros`,
|
||||||
guildView_pending: `Pendiente`,
|
guildView_pending: `Pendiente`,
|
||||||
@ -423,11 +438,11 @@ dict = {
|
|||||||
guildView_rank_soldier: `Soldado`,
|
guildView_rank_soldier: `Soldado`,
|
||||||
guildView_rank_utility: `Utilitario`,
|
guildView_rank_utility: `Utilitario`,
|
||||||
guildView_rank_warlord: `Señor de la guerra`,
|
guildView_rank_warlord: `Señor de la guerra`,
|
||||||
guildView_currency_owned: `[UNTRANSLATED] |COUNT| in Vault.`,
|
guildView_currency_owned: `|COUNT| en la Bóveda.`,
|
||||||
guildView_bulkAddTechProjects: `[UNTRANSLATED] Add Missing Research`,
|
guildView_bulkAddTechProjects: `Añadir proyectos de Investigación Faltantes`,
|
||||||
guildView_bulkAddVaultDecoRecipes: `[UNTRANSLATED] Add Missing Dojo Deco Recipes`,
|
guildView_bulkAddVaultDecoRecipes: `Añadir planos de Decoración de Dojo Faltantes`,
|
||||||
guildView_bulkFundTechProjects: `[UNTRANSLATED] Fund All Research`,
|
guildView_bulkFundTechProjects: `Financiar toda la Investigación`,
|
||||||
guildView_bulkCompleteTechProjects: `[UNTRANSLATED] Complete All Research`,
|
guildView_bulkCompleteTechProjects: `Completar toda la Investigación`,
|
||||||
guildView_promote: `Promover`,
|
guildView_promote: `Promover`,
|
||||||
guildView_demote: `Degradar`,
|
guildView_demote: `Degradar`,
|
||||||
|
|
||||||
|
|||||||
@ -75,8 +75,12 @@ dict = {
|
|||||||
code_funded: `Complété`,
|
code_funded: `Complété`,
|
||||||
code_replays: `[UNTRANSLATED] Replays`,
|
code_replays: `[UNTRANSLATED] Replays`,
|
||||||
code_stalker: `Stalker`,
|
code_stalker: `Stalker`,
|
||||||
|
code_cutName: `[UNTRANSLATED] Cut |INDEX|`,
|
||||||
|
code_drifterBeardName: `Barbe du Voyageur |INDEX|`,
|
||||||
|
code_drifterFaceName: `Visage du Voyageur |INDEX|`,
|
||||||
|
code_operatorFaceName: `Visage de l'Opérateur |INDEX|`,
|
||||||
code_succChange: `Changement effectué.`,
|
code_succChange: `Changement effectué.`,
|
||||||
code_requiredInvigorationUpgrade: `Augmentation offensive et défensive requises.`,
|
code_requiredInvigorationUpgrade: `[UNTRANSLATED] You must select both an offensive & utility upgrade.`,
|
||||||
login_description: `Connexion avec les informations de connexion OpenWF.`,
|
login_description: `Connexion avec les informations de connexion OpenWF.`,
|
||||||
login_emailLabel: `Email`,
|
login_emailLabel: `Email`,
|
||||||
login_passwordLabel: `Mot de passe`,
|
login_passwordLabel: `Mot de passe`,
|
||||||
@ -109,9 +113,10 @@ dict = {
|
|||||||
inventory_moaPets: `Moas`,
|
inventory_moaPets: `Moas`,
|
||||||
inventory_kubrowPets: `Bêtes`,
|
inventory_kubrowPets: `Bêtes`,
|
||||||
inventory_evolutionProgress: `Progrès de l'évolution Incarnon`,
|
inventory_evolutionProgress: `Progrès de l'évolution Incarnon`,
|
||||||
inventory_Boosters: `Boosters`,
|
inventory_boosters: `Boosters`,
|
||||||
inventory_flavourItems: `[UNTRANSLATED] <abbr title="Animation Sets, Glyphs, Palettes, etc.">Flavour Items</abbr>`,
|
inventory_flavourItems: `[UNTRANSLATED] <abbr title="Animation Sets, Glyphs, Palettes, etc.">Flavour Items</abbr>`,
|
||||||
inventory_shipDecorations: `Décorations du vaisseau`,
|
inventory_shipDecorations: `Décorations du vaisseau`,
|
||||||
|
inventory_weaponSkins: `Aspects`,
|
||||||
inventory_bulkAddSuits: `Ajouter les Warframes manquantes`,
|
inventory_bulkAddSuits: `Ajouter les Warframes manquantes`,
|
||||||
inventory_bulkAddWeapons: `Ajouter les armes manquantes`,
|
inventory_bulkAddWeapons: `Ajouter les armes manquantes`,
|
||||||
inventory_bulkAddSpaceSuits: `Ajouter les Archwings manquants`,
|
inventory_bulkAddSpaceSuits: `Ajouter les Archwings manquants`,
|
||||||
@ -121,6 +126,7 @@ dict = {
|
|||||||
inventory_bulkAddFlavourItems: `[UNTRANSLATED] Add Missing Flavour Items`,
|
inventory_bulkAddFlavourItems: `[UNTRANSLATED] Add Missing Flavour Items`,
|
||||||
inventory_bulkAddShipDecorations: `[UNTRANSLATED] Add Missing Ship Decorations`,
|
inventory_bulkAddShipDecorations: `[UNTRANSLATED] Add Missing Ship Decorations`,
|
||||||
inventory_bulkAddEvolutionProgress: `Ajouter les évolutions Incarnon manquantes`,
|
inventory_bulkAddEvolutionProgress: `Ajouter les évolutions Incarnon manquantes`,
|
||||||
|
inventory_bulkAddWeaponSkins: `[UNTRANSLATED] Add Missing Skins`,
|
||||||
inventory_bulkRankUpSuits: `Toutes les Warframes au rang max`,
|
inventory_bulkRankUpSuits: `Toutes les Warframes au rang max`,
|
||||||
inventory_bulkRankUpWeapons: `Toutes les armes au rang max`,
|
inventory_bulkRankUpWeapons: `Toutes les armes au rang max`,
|
||||||
inventory_bulkRankUpSpaceSuits: `Tous les Archwings au rang max`,
|
inventory_bulkRankUpSpaceSuits: `Tous les Archwings au rang max`,
|
||||||
@ -147,7 +153,7 @@ dict = {
|
|||||||
detailedView_valenceBonusLabel: `Bonus de Valence`,
|
detailedView_valenceBonusLabel: `Bonus de Valence`,
|
||||||
detailedView_valenceBonusDescription: `Définir le Bonus Valence de l'arme.`,
|
detailedView_valenceBonusDescription: `Définir le Bonus Valence de l'arme.`,
|
||||||
detailedView_modularPartsLabel: `Changer l'équipement modulaire`,
|
detailedView_modularPartsLabel: `Changer l'équipement modulaire`,
|
||||||
detailedView_suitInvigorationLabel: `Invigoration de Warframe`,
|
detailedView_invigorationLabel: `Dynamisation`,
|
||||||
detailedView_loadoutLabel: `Équipements`,
|
detailedView_loadoutLabel: `Équipements`,
|
||||||
|
|
||||||
invigorations_offensive_AbilityStrength: `+200% de puissance de pouvoir`,
|
invigorations_offensive_AbilityStrength: `+200% de puissance de pouvoir`,
|
||||||
@ -172,9 +178,9 @@ dict = {
|
|||||||
invigorations_utility_Jumps: `+5 réinitialisations de saut`,
|
invigorations_utility_Jumps: `+5 réinitialisations de saut`,
|
||||||
invigorations_utility_EnergyRegen: `+2 d'énergie régénérés/s`,
|
invigorations_utility_EnergyRegen: `+2 d'énergie régénérés/s`,
|
||||||
|
|
||||||
invigorations_offensiveLabel: `Amélioration offensive`,
|
detailedView_invigorationOffensiveLabel: `Amélioration offensive`,
|
||||||
invigorations_defensiveLabel: `Amélioration défensive`,
|
detailedView_invigorationUtilityLabel: `[UNTRANSLATED] Utility Upgrade`,
|
||||||
invigorations_expiryLabel: `Expiration de l'invigoration (optionnel)`,
|
detailedView_invigorationExpiryLabel: `[UNTRANSLATED] Invigoration Expiry (optional)`,
|
||||||
|
|
||||||
abilityOverride_label: `Remplacement de pouvoir`,
|
abilityOverride_label: `Remplacement de pouvoir`,
|
||||||
abilityOverride_onSlot: `Sur l'emplacement`,
|
abilityOverride_onSlot: `Sur l'emplacement`,
|
||||||
@ -257,6 +263,12 @@ dict = {
|
|||||||
cheats_changeButton: `Changer`,
|
cheats_changeButton: `Changer`,
|
||||||
cheats_markAllAsRead: `Marquer la boîte de réception comme lue`,
|
cheats_markAllAsRead: `Marquer la boîte de réception comme lue`,
|
||||||
cheats_finishInvasionsInOneMission: `Compléter les invasions en une mission.`,
|
cheats_finishInvasionsInOneMission: `Compléter les invasions en une mission.`,
|
||||||
|
cheats_nemesisHenchmenKillsMultiplierGrineer: `[UNTRANSLATED] Rage Progess Multiplier (Grineer)`,
|
||||||
|
cheats_nemesisHenchmenKillsMultiplierCorpus: `[UNTRANSLATED] Rage Progess Multiplier (Corpus)`,
|
||||||
|
cheats_nemesisAntivirusGainMultiplier: `[UNTRANSLATED] Antivirus Progress Multiplier`,
|
||||||
|
cheats_nemesisHintProgressMultiplierGrineer: `[UNTRANSLATED] Hint Progress Multiplier (Grineer)`,
|
||||||
|
cheats_nemesisHintProgressMultiplierCorpus: `[UNTRANSLATED] Hint Progress Multiplier (Corpus)`,
|
||||||
|
cheats_nemesisExtraWeapon: `[UNTRANSLATED] Extra Nemesis Weapon / Token On Vanquish (0 to disable)`,
|
||||||
|
|
||||||
worldState: `Carte Solaire`,
|
worldState: `Carte Solaire`,
|
||||||
worldState_creditBoost: `Booster de Crédit`,
|
worldState_creditBoost: `Booster de Crédit`,
|
||||||
@ -273,11 +285,13 @@ dict = {
|
|||||||
worldState_dogDays: `Bataille d'Eau`,
|
worldState_dogDays: `Bataille d'Eau`,
|
||||||
worldState_dogDaysRewards: `Récompenses de la Bataille d'Eau`,
|
worldState_dogDaysRewards: `Récompenses de la Bataille d'Eau`,
|
||||||
worldState_wolfHunt: `Chasse au Loup (2025)`,
|
worldState_wolfHunt: `Chasse au Loup (2025)`,
|
||||||
|
worldState_voidCorruption: `Corruption du Néant (|VAL|)`,
|
||||||
worldState_orphixVenom: `Venin Orphix`,
|
worldState_orphixVenom: `Venin Orphix`,
|
||||||
worldState_longShadow: `La Propagation des Ombres`,
|
worldState_longShadow: `La Propagation des Ombres`,
|
||||||
worldState_hallowedFlame: `Flamme Hantée`,
|
worldState_hallowedFlame: `Flamme Hantée`,
|
||||||
worldState_hallowedNightmares: `Cauchemars Hantés`,
|
worldState_hallowedNightmares: `Cauchemars Hantés`,
|
||||||
worldState_hallowedNightmaresRewards: `Récompenses Flamme Hantée Cauchemar`,
|
worldState_hallowedNightmaresRewards: `Récompenses Flamme Hantée Cauchemar`,
|
||||||
|
worldState_naberusNights: `[UNTRANSLATED] Nights of Naberus`,
|
||||||
worldState_proxyRebellion: `Rébellion Proxy`,
|
worldState_proxyRebellion: `Rébellion Proxy`,
|
||||||
worldState_proxyRebellionRewards: `Récompenses Rébellion Proxy`,
|
worldState_proxyRebellionRewards: `Récompenses Rébellion Proxy`,
|
||||||
worldState_bellyOfTheBeast: `Ventre de la Bête`,
|
worldState_bellyOfTheBeast: `Ventre de la Bête`,
|
||||||
@ -286,6 +300,7 @@ dict = {
|
|||||||
worldState_eightClawProgressOverride: `Progrès de la Huitième Griffe`,
|
worldState_eightClawProgressOverride: `Progrès de la Huitième Griffe`,
|
||||||
worldState_thermiaFractures: `Crevasses Thermia`,
|
worldState_thermiaFractures: `Crevasses Thermia`,
|
||||||
worldState_thermiaFracturesProgressOverride: `Progrès des Fractures Thermia`,
|
worldState_thermiaFracturesProgressOverride: `Progrès des Fractures Thermia`,
|
||||||
|
worldState_qtccAlerts: `[UNTRANSLATED] Quest to Conquer Cancer Alerts`,
|
||||||
worldState_from_year: `de |VAL|`,
|
worldState_from_year: `de |VAL|`,
|
||||||
worldState_pre_year: `pre-|VAL|`,
|
worldState_pre_year: `pre-|VAL|`,
|
||||||
worldState_week: `Semaine |VAL|`,
|
worldState_week: `Semaine |VAL|`,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// Russian translation by AMelonInsideLemon, LoseFace
|
// Russian translation by AMelonInsideLemon, LoseFace
|
||||||
dict = {
|
dict = {
|
||||||
general_inventoryUpdateNote: `Примечание: Чтобы увидеть изменения в игре, вам нужно повторно синхронизировать свой инвентарь, например, используя команду /sync в программе bootstrapper, посетив Додзё/Реле или перезагрузив игру.`,
|
general_inventoryUpdateNote: `Примечание: Чтобы увидеть изменения в игре, вам нужно повторно синхронизировать свой инвентарь, например, используя команду загрузчика /sync в чате игры, посетив Додзё/Реле или перезагрузив игру.`,
|
||||||
general_inventoryUpdateNoteGameWs: `Примечание: для того, чтобы изменения вступили в силу, может потребоваться повторно открыть меню, в котором вы находитесь.`,
|
general_inventoryUpdateNoteGameWs: `Примечание: для того, чтобы изменения вступили в силу, может потребоваться повторно открыть меню, в котором вы находитесь.`,
|
||||||
general_addButton: `Добавить`,
|
general_addButton: `Добавить`,
|
||||||
general_setButton: `Установить`,
|
general_setButton: `Установить`,
|
||||||
@ -45,7 +45,7 @@ dict = {
|
|||||||
code_rank: `Ранг`,
|
code_rank: `Ранг`,
|
||||||
code_rankUp: `Повысить ранг`,
|
code_rankUp: `Повысить ранг`,
|
||||||
code_rankDown: `Понизить ранг`,
|
code_rankDown: `Понизить ранг`,
|
||||||
code_unlockLevelCap: `[UNTRANSLATED] Unlock level cap`,
|
code_unlockLevelCap: `Разблокировать ограничение уровня`,
|
||||||
code_count: `Количество`,
|
code_count: `Количество`,
|
||||||
code_focusAllUnlocked: `Все школы Фокуса уже разблокированы.`,
|
code_focusAllUnlocked: `Все школы Фокуса уже разблокированы.`,
|
||||||
code_focusUnlocked: `Разблокировано |COUNT| новых школ Фокуса! Для отображения изменений в игре потребуется обновление инвентаря. Посещение навигации — самый простой способ этого добиться.`,
|
code_focusUnlocked: `Разблокировано |COUNT| новых школ Фокуса! Для отображения изменений в игре потребуется обновление инвентаря. Посещение навигации — самый простой способ этого добиться.`,
|
||||||
@ -75,6 +75,10 @@ dict = {
|
|||||||
code_funded: `Профинансировано`,
|
code_funded: `Профинансировано`,
|
||||||
code_replays: `Повторов`,
|
code_replays: `Повторов`,
|
||||||
code_stalker: `Сталкер`,
|
code_stalker: `Сталкер`,
|
||||||
|
code_cutName: `Причёска: |INDEX|`,
|
||||||
|
code_drifterBeardName: `Борода скитальца: |INDEX|`,
|
||||||
|
code_drifterFaceName: `Внешность скитальца: |INDEX|`,
|
||||||
|
code_operatorFaceName: `Внешность оператора: |INDEX|`,
|
||||||
code_succChange: `Успешно изменено.`,
|
code_succChange: `Успешно изменено.`,
|
||||||
code_requiredInvigorationUpgrade: `Вы должны выбрать как атакующее, так и вспомогательное улучшение.`,
|
code_requiredInvigorationUpgrade: `Вы должны выбрать как атакующее, так и вспомогательное улучшение.`,
|
||||||
login_description: `Войдите, используя учетные данные OpenWF (те же, что и в игре при подключении к этому серверу).`,
|
login_description: `Войдите, используя учетные данные OpenWF (те же, что и в игре при подключении к этому серверу).`,
|
||||||
@ -109,9 +113,10 @@ dict = {
|
|||||||
inventory_moaPets: `МОА`,
|
inventory_moaPets: `МОА`,
|
||||||
inventory_kubrowPets: `Звери`,
|
inventory_kubrowPets: `Звери`,
|
||||||
inventory_evolutionProgress: `Прогресс эволюции Инкарнонов`,
|
inventory_evolutionProgress: `Прогресс эволюции Инкарнонов`,
|
||||||
inventory_Boosters: `Бустеры`,
|
inventory_boosters: `Бустеры`,
|
||||||
inventory_flavourItems: `<abbr title="Наборы анимаций, глифы, палитры и т. д.">Уникальные предметы</abbr>`,
|
inventory_flavourItems: `<abbr title="Наборы анимаций, глифы, палитры и т. д.">Уникальные предметы</abbr>`,
|
||||||
inventory_shipDecorations: `Украшения корабля`,
|
inventory_shipDecorations: `Украшения корабля`,
|
||||||
|
inventory_weaponSkins: `Скины`,
|
||||||
inventory_bulkAddSuits: `Добавить отсутствующие Варфреймы`,
|
inventory_bulkAddSuits: `Добавить отсутствующие Варфреймы`,
|
||||||
inventory_bulkAddWeapons: `Добавить отсутствующее оружие`,
|
inventory_bulkAddWeapons: `Добавить отсутствующее оружие`,
|
||||||
inventory_bulkAddSpaceSuits: `Добавить отсутствующие Арчвинги`,
|
inventory_bulkAddSpaceSuits: `Добавить отсутствующие Арчвинги`,
|
||||||
@ -121,6 +126,7 @@ dict = {
|
|||||||
inventory_bulkAddFlavourItems: `Добавить отсутствующие уникальные предметы`,
|
inventory_bulkAddFlavourItems: `Добавить отсутствующие уникальные предметы`,
|
||||||
inventory_bulkAddShipDecorations: `Добавить отсутствующие украшения корабля`,
|
inventory_bulkAddShipDecorations: `Добавить отсутствующие украшения корабля`,
|
||||||
inventory_bulkAddEvolutionProgress: `Добавить отсутствующий прогресс эволюции Инкарнонов`,
|
inventory_bulkAddEvolutionProgress: `Добавить отсутствующий прогресс эволюции Инкарнонов`,
|
||||||
|
inventory_bulkAddWeaponSkins: `Добавить отсутствующие скины`,
|
||||||
inventory_bulkRankUpSuits: `Макс. ранг всех Варфреймов`,
|
inventory_bulkRankUpSuits: `Макс. ранг всех Варфреймов`,
|
||||||
inventory_bulkRankUpWeapons: `Макс. ранг всего оружия`,
|
inventory_bulkRankUpWeapons: `Макс. ранг всего оружия`,
|
||||||
inventory_bulkRankUpSpaceSuits: `Макс. ранг всех Арчвингов`,
|
inventory_bulkRankUpSpaceSuits: `Макс. ранг всех Арчвингов`,
|
||||||
@ -147,7 +153,7 @@ dict = {
|
|||||||
detailedView_valenceBonusLabel: `Бонус Валентности`,
|
detailedView_valenceBonusLabel: `Бонус Валентности`,
|
||||||
detailedView_valenceBonusDescription: `Вы можете установить или убрать бонус Валентности с вашего оружия.`,
|
detailedView_valenceBonusDescription: `Вы можете установить или убрать бонус Валентности с вашего оружия.`,
|
||||||
detailedView_modularPartsLabel: `Изменить модульные части`,
|
detailedView_modularPartsLabel: `Изменить модульные части`,
|
||||||
detailedView_suitInvigorationLabel: `Воодушевление Варфрейма`,
|
detailedView_invigorationLabel: `Воодушевление`,
|
||||||
detailedView_loadoutLabel: `Конфигурации`,
|
detailedView_loadoutLabel: `Конфигурации`,
|
||||||
|
|
||||||
invigorations_offensive_AbilityStrength: `+200% к силе способностей.`,
|
invigorations_offensive_AbilityStrength: `+200% к силе способностей.`,
|
||||||
@ -172,9 +178,9 @@ dict = {
|
|||||||
invigorations_utility_Jumps: `+5 сбросов прыжка.`,
|
invigorations_utility_Jumps: `+5 сбросов прыжка.`,
|
||||||
invigorations_utility_EnergyRegen: `+2 к регенерации энергии в секунду.`,
|
invigorations_utility_EnergyRegen: `+2 к регенерации энергии в секунду.`,
|
||||||
|
|
||||||
invigorations_offensiveLabel: `Атакующее улучшение`,
|
detailedView_invigorationOffensiveLabel: `Атакующее улучшение`,
|
||||||
invigorations_defensiveLabel: `Вспомогательное улучшение`,
|
detailedView_invigorationUtilityLabel: `Вспомогательное улучшение`,
|
||||||
invigorations_expiryLabel: `Срок действия Воодушевления (необязательно)`,
|
detailedView_invigorationExpiryLabel: `Срок действия Воодушевления (необязательно)`,
|
||||||
|
|
||||||
abilityOverride_label: `Переопределение способности`,
|
abilityOverride_label: `Переопределение способности`,
|
||||||
abilityOverride_onSlot: `в ячейке`,
|
abilityOverride_onSlot: `в ячейке`,
|
||||||
@ -227,7 +233,7 @@ dict = {
|
|||||||
cheats_baroFullyStocked: `Баро полностью укомплектован`,
|
cheats_baroFullyStocked: `Баро полностью укомплектован`,
|
||||||
cheats_syndicateMissionsRepeatable: `Повторять миссии синдиката`,
|
cheats_syndicateMissionsRepeatable: `Повторять миссии синдиката`,
|
||||||
cheats_unlockAllProfitTakerStages: `Разблокировать все этапы Сферы извлечения прибыли`,
|
cheats_unlockAllProfitTakerStages: `Разблокировать все этапы Сферы извлечения прибыли`,
|
||||||
cheats_unlockSuccInventory: `Успех. Обратите внимание, что вам необходимо будет повторно синхронизировать свой инвентарь, например, с помощью команды /sync в программе bootstrapper, посетив Додзё/Реле или повторно войдя в игру.`,
|
cheats_unlockSuccInventory: `Успех. Обратите внимание, что вам необходимо будет повторно синхронизировать свой инвентарь, например, с помощью команды загрузчика /sync в чате игры, посетив Додзё/Реле или повторно войдя в игру.`,
|
||||||
cheats_instantFinishRivenChallenge: `Мгновенное завершение испытания мода Разлома`,
|
cheats_instantFinishRivenChallenge: `Мгновенное завершение испытания мода Разлома`,
|
||||||
cheats_instantResourceExtractorDrones: `Мгновенно добывающие Дроны-сборщики`,
|
cheats_instantResourceExtractorDrones: `Мгновенно добывающие Дроны-сборщики`,
|
||||||
cheats_noResourceExtractorDronesDamage: `Без урона по Дронам-сборщикам`,
|
cheats_noResourceExtractorDronesDamage: `Без урона по Дронам-сборщикам`,
|
||||||
@ -257,6 +263,12 @@ dict = {
|
|||||||
cheats_changeButton: `Изменить`,
|
cheats_changeButton: `Изменить`,
|
||||||
cheats_markAllAsRead: `Пометить все входящие как прочитанные`,
|
cheats_markAllAsRead: `Пометить все входящие как прочитанные`,
|
||||||
cheats_finishInvasionsInOneMission: `Завершать вторжение за одну миссию`,
|
cheats_finishInvasionsInOneMission: `Завершать вторжение за одну миссию`,
|
||||||
|
cheats_nemesisHenchmenKillsMultiplierGrineer: `Мультипликатор прогресса ярости (Гринир)`,
|
||||||
|
cheats_nemesisHenchmenKillsMultiplierCorpus: `Мультипликатор прогресса ярости (Корпус)`,
|
||||||
|
cheats_nemesisAntivirusGainMultiplier: `Мультипликатор прогресса антивируса`,
|
||||||
|
cheats_nemesisHintProgressMultiplierGrineer: `Мультипликатор прогресса подсказки (Гринир)`,
|
||||||
|
cheats_nemesisHintProgressMultiplierCorpus: `Мультипликатор прогресса подсказки (Корпус)`,
|
||||||
|
cheats_nemesisExtraWeapon: `Дополнительное оружие/активный Кардиомиоцит за победу над Противником (0 для отключения)`,
|
||||||
|
|
||||||
worldState: `Состояние мира`,
|
worldState: `Состояние мира`,
|
||||||
worldState_creditBoost: `Глобальный бустер Кредитов`,
|
worldState_creditBoost: `Глобальный бустер Кредитов`,
|
||||||
@ -273,11 +285,13 @@ dict = {
|
|||||||
worldState_dogDays: `Знойные дни`,
|
worldState_dogDays: `Знойные дни`,
|
||||||
worldState_dogDaysRewards: `Награды Знойных дней`,
|
worldState_dogDaysRewards: `Награды Знойных дней`,
|
||||||
worldState_wolfHunt: `Волчья Охота (2025)`,
|
worldState_wolfHunt: `Волчья Охота (2025)`,
|
||||||
|
worldState_voidCorruption: `Искажение Бездны (|VAL|)`,
|
||||||
worldState_orphixVenom: `Яд Орфикса`,
|
worldState_orphixVenom: `Яд Орфикса`,
|
||||||
worldState_longShadow: `Длинная Тень`,
|
worldState_longShadow: `Длинная Тень`,
|
||||||
worldState_hallowedFlame: `Священное пламя`,
|
worldState_hallowedFlame: `Священное пламя`,
|
||||||
worldState_hallowedNightmares: `Священные кошмары`,
|
worldState_hallowedNightmares: `Священные кошмары`,
|
||||||
worldState_hallowedNightmaresRewards: `Награды Священных кошмаров`,
|
worldState_hallowedNightmaresRewards: `Награды Священных кошмаров`,
|
||||||
|
worldState_naberusNights: `Ночи Наберуса`,
|
||||||
worldState_proxyRebellion: `Восстание роботов`,
|
worldState_proxyRebellion: `Восстание роботов`,
|
||||||
worldState_proxyRebellionRewards: `Награды Восстания роботов`,
|
worldState_proxyRebellionRewards: `Награды Восстания роботов`,
|
||||||
worldState_bellyOfTheBeast: `Чрево зверя`,
|
worldState_bellyOfTheBeast: `Чрево зверя`,
|
||||||
@ -286,6 +300,7 @@ dict = {
|
|||||||
worldState_eightClawProgressOverride: `Прогресс Восьми когтей`,
|
worldState_eightClawProgressOverride: `Прогресс Восьми когтей`,
|
||||||
worldState_thermiaFractures: `Разломы Термии`,
|
worldState_thermiaFractures: `Разломы Термии`,
|
||||||
worldState_thermiaFracturesProgressOverride: `Прогресс Разломов Термии`,
|
worldState_thermiaFracturesProgressOverride: `Прогресс Разломов Термии`,
|
||||||
|
worldState_qtccAlerts: `Тревоги Quest to Conquer Cancer`,
|
||||||
worldState_from_year: `из |VAL|`,
|
worldState_from_year: `из |VAL|`,
|
||||||
worldState_pre_year: `до |VAL|`,
|
worldState_pre_year: `до |VAL|`,
|
||||||
worldState_week: `Неделя |VAL|`,
|
worldState_week: `Неделя |VAL|`,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// Ukrainian translation by LoseFace
|
// Ukrainian translation by LoseFace
|
||||||
dict = {
|
dict = {
|
||||||
general_inventoryUpdateNote: `Пам'ятка: Щоб побачити зміни в грі, вам потрібно повторно синхронізувати своє спорядження, наприклад, використовуючи команду /sync в програмі bootstrapper, відвідавши Доджьо/Реле або перезавантаживши гру.`,
|
general_inventoryUpdateNote: `Пам'ятка: Щоб побачити зміни в грі, вам потрібно повторно синхронізувати своє спорядження, наприклад, використовуючи команду завантажувача /sync у чаті гри, відвідавши Доджьо/Реле або перезавантаживши гру.`,
|
||||||
general_inventoryUpdateNoteGameWs: `Примітка: для відображення змін може знадобитися повторно відкрити меню, в якому ви перебуваєте.`,
|
general_inventoryUpdateNoteGameWs: `Примітка: для відображення змін може знадобитися повторно відкрити меню, в якому ви перебуваєте.`,
|
||||||
general_addButton: `Добавити`,
|
general_addButton: `Добавити`,
|
||||||
general_setButton: `Встановити`,
|
general_setButton: `Встановити`,
|
||||||
@ -45,7 +45,7 @@ dict = {
|
|||||||
code_rank: `Рівень`,
|
code_rank: `Рівень`,
|
||||||
code_rankUp: `Підвищити рівень`,
|
code_rankUp: `Підвищити рівень`,
|
||||||
code_rankDown: `Понизити рівень`,
|
code_rankDown: `Понизити рівень`,
|
||||||
code_unlockLevelCap: `[UNTRANSLATED] Unlock level cap`,
|
code_unlockLevelCap: `Розблокувати обмеження рівня`,
|
||||||
code_count: `Кількість`,
|
code_count: `Кількість`,
|
||||||
code_focusAllUnlocked: `Всі школи Фокусу вже розблоковані.`,
|
code_focusAllUnlocked: `Всі школи Фокусу вже розблоковані.`,
|
||||||
code_focusUnlocked: `Розблоковано |COUNT| нових шкіл Фокусу! Для відображення змін в грі знадобиться оновлення спорядження. Відвідування навігації — найпростіший спосіб цього досягти.`,
|
code_focusUnlocked: `Розблоковано |COUNT| нових шкіл Фокусу! Для відображення змін в грі знадобиться оновлення спорядження. Відвідування навігації — найпростіший спосіб цього досягти.`,
|
||||||
@ -75,6 +75,10 @@ dict = {
|
|||||||
code_funded: `Профінансовано`,
|
code_funded: `Профінансовано`,
|
||||||
code_replays: `Повтори`,
|
code_replays: `Повтори`,
|
||||||
code_stalker: `Сталкер`,
|
code_stalker: `Сталкер`,
|
||||||
|
code_cutName: `Зачіска: |INDEX|`,
|
||||||
|
code_drifterBeardName: `Борода мандрівника: |INDEX|`,
|
||||||
|
code_drifterFaceName: `Зовнішність мандрівника: |INDEX|`,
|
||||||
|
code_operatorFaceName: `Зовнішність оператора: |INDEX|`,
|
||||||
code_succChange: `Успішно змінено.`,
|
code_succChange: `Успішно змінено.`,
|
||||||
code_requiredInvigorationUpgrade: `Ви повинні вибрати як атакуюче, так і допоміжне вдосконалення.`,
|
code_requiredInvigorationUpgrade: `Ви повинні вибрати як атакуюче, так і допоміжне вдосконалення.`,
|
||||||
login_description: `Увійдіть, використовуючи облікові дані OpenWF (ті ж, що й у грі при підключенні до цього серверу).`,
|
login_description: `Увійдіть, використовуючи облікові дані OpenWF (ті ж, що й у грі при підключенні до цього серверу).`,
|
||||||
@ -109,9 +113,10 @@ dict = {
|
|||||||
inventory_moaPets: `МОА`,
|
inventory_moaPets: `МОА`,
|
||||||
inventory_kubrowPets: `Тварини`,
|
inventory_kubrowPets: `Тварини`,
|
||||||
inventory_evolutionProgress: `Прогрес еволюції Інкарнонів`,
|
inventory_evolutionProgress: `Прогрес еволюції Інкарнонів`,
|
||||||
inventory_Boosters: `Посилення`,
|
inventory_boosters: `Посилення`,
|
||||||
inventory_flavourItems: `<abbr title="Набори анімацій, гліфи, палітри і т. д.">Унікальні предмети</abbr>`,
|
inventory_flavourItems: `<abbr title="Набори анімацій, гліфи, палітри і т. д.">Унікальні предмети</abbr>`,
|
||||||
inventory_shipDecorations: `Прикраси судна`,
|
inventory_shipDecorations: `Прикраси судна`,
|
||||||
|
inventory_weaponSkins: `Вигляди`,
|
||||||
inventory_bulkAddSuits: `Додати відсутні Ворфрейми`,
|
inventory_bulkAddSuits: `Додати відсутні Ворфрейми`,
|
||||||
inventory_bulkAddWeapons: `Додати відсутню зброю`,
|
inventory_bulkAddWeapons: `Додати відсутню зброю`,
|
||||||
inventory_bulkAddSpaceSuits: `Додати відсутні Арквінґи`,
|
inventory_bulkAddSpaceSuits: `Додати відсутні Арквінґи`,
|
||||||
@ -121,6 +126,7 @@ dict = {
|
|||||||
inventory_bulkAddFlavourItems: `Додати відсутні унікальні предмети`,
|
inventory_bulkAddFlavourItems: `Додати відсутні унікальні предмети`,
|
||||||
inventory_bulkAddShipDecorations: `Додати відсутні оздоби корабля`,
|
inventory_bulkAddShipDecorations: `Додати відсутні оздоби корабля`,
|
||||||
inventory_bulkAddEvolutionProgress: `Додати відсутній прогрес еволюції Інкарнонів`,
|
inventory_bulkAddEvolutionProgress: `Додати відсутній прогрес еволюції Інкарнонів`,
|
||||||
|
inventory_bulkAddWeaponSkins: `[UNTRANSLATED] Add Missing Skins`,
|
||||||
inventory_bulkRankUpSuits: `Макс. рівень всіх Ворфреймів`,
|
inventory_bulkRankUpSuits: `Макс. рівень всіх Ворфреймів`,
|
||||||
inventory_bulkRankUpWeapons: `Макс. рівень всієї зброї`,
|
inventory_bulkRankUpWeapons: `Макс. рівень всієї зброї`,
|
||||||
inventory_bulkRankUpSpaceSuits: `Макс. рівень всіх Арквінґів`,
|
inventory_bulkRankUpSpaceSuits: `Макс. рівень всіх Арквінґів`,
|
||||||
@ -147,7 +153,7 @@ dict = {
|
|||||||
detailedView_valenceBonusLabel: `Ознака Валентності`,
|
detailedView_valenceBonusLabel: `Ознака Валентності`,
|
||||||
detailedView_valenceBonusDescription: `Ви можете встановити або прибрати ознаку Валентності з вашої зброї.`,
|
detailedView_valenceBonusDescription: `Ви можете встановити або прибрати ознаку Валентності з вашої зброї.`,
|
||||||
detailedView_modularPartsLabel: `Змінити модульні частини`,
|
detailedView_modularPartsLabel: `Змінити модульні частини`,
|
||||||
detailedView_suitInvigorationLabel: `Зміцнення Ворфрейма`,
|
detailedView_invigorationLabel: `Зміцнення`,
|
||||||
detailedView_loadoutLabel: `Конфігурації`,
|
detailedView_loadoutLabel: `Конфігурації`,
|
||||||
|
|
||||||
invigorations_offensive_AbilityStrength: `+200% до потужності здібностей.`,
|
invigorations_offensive_AbilityStrength: `+200% до потужності здібностей.`,
|
||||||
@ -172,9 +178,9 @@ dict = {
|
|||||||
invigorations_utility_Jumps: `+5 Оновлень стрибків.`,
|
invigorations_utility_Jumps: `+5 Оновлень стрибків.`,
|
||||||
invigorations_utility_EnergyRegen: `+2 до відновлення енергії на секунду.`,
|
invigorations_utility_EnergyRegen: `+2 до відновлення енергії на секунду.`,
|
||||||
|
|
||||||
invigorations_offensiveLabel: `Атакуюче вдосконалення`,
|
detailedView_invigorationOffensiveLabel: `Атакуюче вдосконалення`,
|
||||||
invigorations_defensiveLabel: `Допоміжне вдосконалення`,
|
detailedView_invigorationUtilityLabel: `Допоміжне вдосконалення`,
|
||||||
invigorations_expiryLabel: `Термін дії Зміцнення (необов'язково)`,
|
detailedView_invigorationExpiryLabel: `Термін дії Зміцнення (необов'язково)`,
|
||||||
|
|
||||||
abilityOverride_label: `Перевизначення здібностей`,
|
abilityOverride_label: `Перевизначення здібностей`,
|
||||||
abilityOverride_onSlot: `у комірці`,
|
abilityOverride_onSlot: `у комірці`,
|
||||||
@ -227,7 +233,7 @@ dict = {
|
|||||||
cheats_baroFullyStocked: `Баро повністю укомплектований`,
|
cheats_baroFullyStocked: `Баро повністю укомплектований`,
|
||||||
cheats_syndicateMissionsRepeatable: `Повторювати місії синдиката`,
|
cheats_syndicateMissionsRepeatable: `Повторювати місії синдиката`,
|
||||||
cheats_unlockAllProfitTakerStages: `Розблокувати всі етапи Привласнювачки`,
|
cheats_unlockAllProfitTakerStages: `Розблокувати всі етапи Привласнювачки`,
|
||||||
cheats_unlockSuccInventory: `Успішно. Зверніть увагу, що вам потрібно буде повторно синхронізувати своє спорядження, наприклад, за допомогою команди /sync в програмі bootstrapper, відвідавши Доджьо/Реле або повторно увійшовши в гру.`,
|
cheats_unlockSuccInventory: `Успішно. Зверніть увагу, що вам потрібно буде повторно синхронізувати своє спорядження, наприклад, за допомогою команди завантажувача /sync у чаті гри, відвідавши Доджьо/Реле або повторно увійшовши в гру.`,
|
||||||
cheats_instantFinishRivenChallenge: `Миттєве завершення випробування модифікатора Розколу`,
|
cheats_instantFinishRivenChallenge: `Миттєве завершення випробування модифікатора Розколу`,
|
||||||
cheats_instantResourceExtractorDrones: `Миттєво добуваючі Дрони-видобувачі`,
|
cheats_instantResourceExtractorDrones: `Миттєво добуваючі Дрони-видобувачі`,
|
||||||
cheats_noResourceExtractorDronesDamage: `Без шкоди по Дронам-видобувачам`,
|
cheats_noResourceExtractorDronesDamage: `Без шкоди по Дронам-видобувачам`,
|
||||||
@ -257,6 +263,12 @@ dict = {
|
|||||||
cheats_changeButton: `Змінити`,
|
cheats_changeButton: `Змінити`,
|
||||||
cheats_markAllAsRead: `Помітити всі вхідні як прочитані`,
|
cheats_markAllAsRead: `Помітити всі вхідні як прочитані`,
|
||||||
cheats_finishInvasionsInOneMission: `Завершувати вторгнення за одну місію`,
|
cheats_finishInvasionsInOneMission: `Завершувати вторгнення за одну місію`,
|
||||||
|
cheats_nemesisHenchmenKillsMultiplierGrineer: `Множник прогресу люті (Ґрінери)`,
|
||||||
|
cheats_nemesisHenchmenKillsMultiplierCorpus: `Множник прогресу люті (Корпус)`,
|
||||||
|
cheats_nemesisAntivirusGainMultiplier: `Мультиплікатор прогресу антивіруса`,
|
||||||
|
cheats_nemesisHintProgressMultiplierGrineer: `Множник прогресу підсказки (Ґрінери)`,
|
||||||
|
cheats_nemesisHintProgressMultiplierCorpus: `Множник прогресу підсказки (Корпус)`,
|
||||||
|
cheats_nemesisExtraWeapon: `Додаткова зброя/Жива сердцевина за перемогу над Недругом (0 для вимкнення)`,
|
||||||
|
|
||||||
worldState: `Стан світу`,
|
worldState: `Стан світу`,
|
||||||
worldState_creditBoost: `Глобальне посилення Кредитів`,
|
worldState_creditBoost: `Глобальне посилення Кредитів`,
|
||||||
@ -273,11 +285,13 @@ dict = {
|
|||||||
worldState_dogDays: `Спекотні дні`,
|
worldState_dogDays: `Спекотні дні`,
|
||||||
worldState_dogDaysRewards: `Нагороди Спекотних днів`,
|
worldState_dogDaysRewards: `Нагороди Спекотних днів`,
|
||||||
worldState_wolfHunt: `Полювання на Вовка (2025)`,
|
worldState_wolfHunt: `Полювання на Вовка (2025)`,
|
||||||
|
worldState_voidCorruption: `Викривлення Порожнечі (|VAL|)`,
|
||||||
worldState_orphixVenom: `Орфіксова отрута`,
|
worldState_orphixVenom: `Орфіксова отрута`,
|
||||||
worldState_longShadow: `Довга тінь`,
|
worldState_longShadow: `Довга тінь`,
|
||||||
worldState_hallowedFlame: `Священне полум'я`,
|
worldState_hallowedFlame: `Священне полум'я`,
|
||||||
worldState_hallowedNightmares: `Священні жахіття`,
|
worldState_hallowedNightmares: `Священні жахіття`,
|
||||||
worldState_hallowedNightmaresRewards: `Нагороди Священних жахіть`,
|
worldState_hallowedNightmaresRewards: `Нагороди Священних жахіть`,
|
||||||
|
worldState_naberusNights: `Наберові ночі`,
|
||||||
worldState_proxyRebellion: `Повстання роботів`,
|
worldState_proxyRebellion: `Повстання роботів`,
|
||||||
worldState_proxyRebellionRewards: `Нагороди Повстання роботів`,
|
worldState_proxyRebellionRewards: `Нагороди Повстання роботів`,
|
||||||
worldState_bellyOfTheBeast: `У лігві звіра`,
|
worldState_bellyOfTheBeast: `У лігві звіра`,
|
||||||
@ -286,6 +300,7 @@ dict = {
|
|||||||
worldState_eightClawProgressOverride: `Прогрес Восьми кігтів`,
|
worldState_eightClawProgressOverride: `Прогрес Восьми кігтів`,
|
||||||
worldState_thermiaFractures: `Розломи термії`,
|
worldState_thermiaFractures: `Розломи термії`,
|
||||||
worldState_thermiaFracturesProgressOverride: `Прогрес Розломів термії`,
|
worldState_thermiaFracturesProgressOverride: `Прогрес Розломів термії`,
|
||||||
|
worldState_qtccAlerts: `[UNTRANSLATED] Quest to Conquer Cancer Alerts`,
|
||||||
worldState_from_year: `з |VAL|`,
|
worldState_from_year: `з |VAL|`,
|
||||||
worldState_pre_year: `до |VAL|`,
|
worldState_pre_year: `до |VAL|`,
|
||||||
worldState_week: `Тиждень |VAL|`,
|
worldState_week: `Тиждень |VAL|`,
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// Chinese translation by meb154, bishan178, nyaoouo, qianlishun, CrazyZhang, Corvus, & qingchun
|
// Chinese translation by meb154, bishan178, nyaoouo, qianlishun, CrazyZhang, Corvus, qingchun
|
||||||
dict = {
|
dict = {
|
||||||
general_inventoryUpdateNote: `注意: 要在游戏中查看更改,您需要重新同步库存,例如使用客户端的 /sync 命令,访问道场/中继站或重新登录.`,
|
general_inventoryUpdateNote: `注意: 要在游戏中查看更改,您需要重新同步库存,例如使用客户端的 /sync 命令,访问道场/中继站或重新登录.`,
|
||||||
general_inventoryUpdateNoteGameWs: `[UNTRANSLATED] Note: You may need to reopen any menu you are on for changes to be reflected.`,
|
general_inventoryUpdateNoteGameWs: `[UNTRANSLATED] Note: You may need to reopen any menu you are on for changes to be reflected.`,
|
||||||
@ -75,8 +75,12 @@ dict = {
|
|||||||
code_funded: `[UNTRANSLATED] Funded`,
|
code_funded: `[UNTRANSLATED] Funded`,
|
||||||
code_replays: `[UNTRANSLATED] Replays`,
|
code_replays: `[UNTRANSLATED] Replays`,
|
||||||
code_stalker: `追猎者`,
|
code_stalker: `追猎者`,
|
||||||
|
code_cutName: `[UNTRANSLATED] Cut |INDEX|`,
|
||||||
|
code_drifterBeardName: `漂泊者胡须 |INDEX|`,
|
||||||
|
code_drifterFaceName: `漂泊者面部 |INDEX|`,
|
||||||
|
code_operatorFaceName: `指挥官面部 |INDEX|`,
|
||||||
code_succChange: `更改成功`,
|
code_succChange: `更改成功`,
|
||||||
code_requiredInvigorationUpgrade: `您必须同时选择一个进攻型和一个功能型活化属性.`,
|
code_requiredInvigorationUpgrade: `[UNTRANSLATED] You must select both an offensive & utility upgrade.`,
|
||||||
login_description: `使用您的 OpenWF 账户凭证登录(与游戏内连接本服务器时使用的昵称相同)`,
|
login_description: `使用您的 OpenWF 账户凭证登录(与游戏内连接本服务器时使用的昵称相同)`,
|
||||||
login_emailLabel: `电子邮箱`,
|
login_emailLabel: `电子邮箱`,
|
||||||
login_passwordLabel: `密码`,
|
login_passwordLabel: `密码`,
|
||||||
@ -109,9 +113,10 @@ dict = {
|
|||||||
inventory_moaPets: `恐鸟`,
|
inventory_moaPets: `恐鸟`,
|
||||||
inventory_kubrowPets: `动物同伴`,
|
inventory_kubrowPets: `动物同伴`,
|
||||||
inventory_evolutionProgress: `灵化之源进度`,
|
inventory_evolutionProgress: `灵化之源进度`,
|
||||||
inventory_Boosters: `加成器`,
|
inventory_boosters: `加成器`,
|
||||||
inventory_flavourItems: `<abbr title="动作表情、浮印、调色板等">装饰物品</abbr>`,
|
inventory_flavourItems: `<abbr title="动作表情、浮印、调色板等">装饰物品</abbr>`,
|
||||||
inventory_shipDecorations: `飞船装饰`,
|
inventory_shipDecorations: `飞船装饰`,
|
||||||
|
inventory_weaponSkins: `外观`,
|
||||||
inventory_bulkAddSuits: `添加缺失战甲`,
|
inventory_bulkAddSuits: `添加缺失战甲`,
|
||||||
inventory_bulkAddWeapons: `添加缺失武器`,
|
inventory_bulkAddWeapons: `添加缺失武器`,
|
||||||
inventory_bulkAddSpaceSuits: `添加缺失载具`,
|
inventory_bulkAddSpaceSuits: `添加缺失载具`,
|
||||||
@ -121,6 +126,7 @@ dict = {
|
|||||||
inventory_bulkAddFlavourItems: `[UNTRANSLATED] Add Missing Flavour Items`,
|
inventory_bulkAddFlavourItems: `[UNTRANSLATED] Add Missing Flavour Items`,
|
||||||
inventory_bulkAddShipDecorations: `[UNTRANSLATED] Add Missing Ship Decorations`,
|
inventory_bulkAddShipDecorations: `[UNTRANSLATED] Add Missing Ship Decorations`,
|
||||||
inventory_bulkAddEvolutionProgress: `添加缺失的灵化之源进度`,
|
inventory_bulkAddEvolutionProgress: `添加缺失的灵化之源进度`,
|
||||||
|
inventory_bulkAddWeaponSkins: `[UNTRANSLATED] Add Missing Skins`,
|
||||||
inventory_bulkRankUpSuits: `所有战甲升满级`,
|
inventory_bulkRankUpSuits: `所有战甲升满级`,
|
||||||
inventory_bulkRankUpWeapons: `所有武器升满级`,
|
inventory_bulkRankUpWeapons: `所有武器升满级`,
|
||||||
inventory_bulkRankUpSpaceSuits: `所有载具升满级`,
|
inventory_bulkRankUpSpaceSuits: `所有载具升满级`,
|
||||||
@ -147,7 +153,7 @@ dict = {
|
|||||||
detailedView_valenceBonusLabel: `效价加成`,
|
detailedView_valenceBonusLabel: `效价加成`,
|
||||||
detailedView_valenceBonusDescription: `您可以设置或移除武器上的效价加成.`,
|
detailedView_valenceBonusDescription: `您可以设置或移除武器上的效价加成.`,
|
||||||
detailedView_modularPartsLabel: `更换部件`,
|
detailedView_modularPartsLabel: `更换部件`,
|
||||||
detailedView_suitInvigorationLabel: `编辑战甲活化属性`,
|
detailedView_invigorationLabel: `活化`,
|
||||||
detailedView_loadoutLabel: `配置`,
|
detailedView_loadoutLabel: `配置`,
|
||||||
|
|
||||||
invigorations_offensive_AbilityStrength: `+200%技能强度`,
|
invigorations_offensive_AbilityStrength: `+200%技能强度`,
|
||||||
@ -172,9 +178,9 @@ dict = {
|
|||||||
invigorations_utility_Jumps: `+5跳跃次数`,
|
invigorations_utility_Jumps: `+5跳跃次数`,
|
||||||
invigorations_utility_EnergyRegen: `+2/秒能量恢复`,
|
invigorations_utility_EnergyRegen: `+2/秒能量恢复`,
|
||||||
|
|
||||||
invigorations_offensiveLabel: `进攻型属性`,
|
detailedView_invigorationOffensiveLabel: `进攻型属性`,
|
||||||
invigorations_defensiveLabel: `功能型属性`,
|
detailedView_invigorationUtilityLabel: `[UNTRANSLATED] Utility Upgrade`,
|
||||||
invigorations_expiryLabel: `活化时效(可选)`,
|
detailedView_invigorationExpiryLabel: `活化时效(可选)`,
|
||||||
|
|
||||||
abilityOverride_label: `技能替换`,
|
abilityOverride_label: `技能替换`,
|
||||||
abilityOverride_onSlot: `槽位`,
|
abilityOverride_onSlot: `槽位`,
|
||||||
@ -193,7 +199,7 @@ dict = {
|
|||||||
cheats_skipTutorial: `跳过教程`,
|
cheats_skipTutorial: `跳过教程`,
|
||||||
cheats_skipAllDialogue: `跳过所有对话`,
|
cheats_skipAllDialogue: `跳过所有对话`,
|
||||||
cheats_unlockAllScans: `解锁所有扫描`,
|
cheats_unlockAllScans: `解锁所有扫描`,
|
||||||
cheats_unlockSuccRelog: `[UNTRANSLATED] Success. Please that you'll need to relog for the client to refresh this.`,
|
cheats_unlockSuccRelog: `[UNTRANSLATED] Success. Please note that you'll need to relog for the client to refresh this.`,
|
||||||
cheats_unlockAllMissions: `解锁所有星图`,
|
cheats_unlockAllMissions: `解锁所有星图`,
|
||||||
cheats_unlockAllMissions_ok: `操作成功.请注意,您需要进入道场/中继站或重新登录以刷新星图数据.`,
|
cheats_unlockAllMissions_ok: `操作成功.请注意,您需要进入道场/中继站或重新登录以刷新星图数据.`,
|
||||||
cheats_infiniteCredits: `无限现金`,
|
cheats_infiniteCredits: `无限现金`,
|
||||||
@ -227,7 +233,7 @@ dict = {
|
|||||||
cheats_baroFullyStocked: `虚空商人贩卖所有商品`,
|
cheats_baroFullyStocked: `虚空商人贩卖所有商品`,
|
||||||
cheats_syndicateMissionsRepeatable: `集团任务可重复完成`,
|
cheats_syndicateMissionsRepeatable: `集团任务可重复完成`,
|
||||||
cheats_unlockAllProfitTakerStages: `解锁利润收割者圆蛛所有阶段`,
|
cheats_unlockAllProfitTakerStages: `解锁利润收割者圆蛛所有阶段`,
|
||||||
cheats_unlockSuccInventory: `[UNTRANSLATED] Success. Please note that you'll need to resync your inventory, e.g. using the bootstrapper's /sync command, visiting a dojo/relay, or relogging..`,
|
cheats_unlockSuccInventory: `[UNTRANSLATED] Success. Please note that you'll need to resync your inventory, e.g. using the bootstrapper's /sync command in game chat, visiting a dojo/relay, or relogging.`,
|
||||||
cheats_instantFinishRivenChallenge: `立即完成裂罅挑战`,
|
cheats_instantFinishRivenChallenge: `立即完成裂罅挑战`,
|
||||||
cheats_instantResourceExtractorDrones: `资源无人机即时完成`,
|
cheats_instantResourceExtractorDrones: `资源无人机即时完成`,
|
||||||
cheats_noResourceExtractorDronesDamage: `资源无人机不会损毁`,
|
cheats_noResourceExtractorDronesDamage: `资源无人机不会损毁`,
|
||||||
@ -257,6 +263,12 @@ dict = {
|
|||||||
cheats_changeButton: `更改`,
|
cheats_changeButton: `更改`,
|
||||||
cheats_markAllAsRead: `收件箱全部标记为已读`,
|
cheats_markAllAsRead: `收件箱全部标记为已读`,
|
||||||
cheats_finishInvasionsInOneMission: `一场任务完成整场入侵`,
|
cheats_finishInvasionsInOneMission: `一场任务完成整场入侵`,
|
||||||
|
cheats_nemesisHenchmenKillsMultiplierGrineer: `玄骸怒气倍率 (Grineer)`,
|
||||||
|
cheats_nemesisHenchmenKillsMultiplierCorpus: `玄骸怒气倍率 (Corpus)`,
|
||||||
|
cheats_nemesisAntivirusGainMultiplier: `杀毒进度倍率 (科腐者)`,
|
||||||
|
cheats_nemesisHintProgressMultiplierGrineer: `解密进度倍率 (Grineer)`,
|
||||||
|
cheats_nemesisHintProgressMultiplierCorpus: `解密进度倍率 (Corpus)`,
|
||||||
|
cheats_nemesisExtraWeapon: `额外玄骸武器/代币 (0为禁用)`,
|
||||||
|
|
||||||
worldState: `世界状态配置`,
|
worldState: `世界状态配置`,
|
||||||
worldState_creditBoost: `现金加成`,
|
worldState_creditBoost: `现金加成`,
|
||||||
@ -273,11 +285,13 @@ dict = {
|
|||||||
worldState_dogDays: `三伏天`,
|
worldState_dogDays: `三伏天`,
|
||||||
worldState_dogDaysRewards: `三伏天奖励设置`,
|
worldState_dogDaysRewards: `三伏天奖励设置`,
|
||||||
worldState_wolfHunt: `恶狼狩猎 (2025)`,
|
worldState_wolfHunt: `恶狼狩猎 (2025)`,
|
||||||
|
worldState_voidCorruption: `虚空堕落 (|VAL|)`,
|
||||||
worldState_orphixVenom: `奥影之毒`,
|
worldState_orphixVenom: `奥影之毒`,
|
||||||
worldState_longShadow: `暗夜长影`,
|
worldState_longShadow: `暗夜长影`,
|
||||||
worldState_hallowedFlame: `万圣之焰`,
|
worldState_hallowedFlame: `万圣之焰`,
|
||||||
worldState_hallowedNightmares: `万圣噩梦`,
|
worldState_hallowedNightmares: `万圣噩梦`,
|
||||||
worldState_hallowedNightmaresRewards: `万圣噩梦奖励设置`,
|
worldState_hallowedNightmaresRewards: `万圣噩梦奖励设置`,
|
||||||
|
worldState_naberusNights: `[UNTRANSLATED] Nights of Naberus`,
|
||||||
worldState_proxyRebellion: `机械叛乱`,
|
worldState_proxyRebellion: `机械叛乱`,
|
||||||
worldState_proxyRebellionRewards: `机械叛乱奖励设置`,
|
worldState_proxyRebellionRewards: `机械叛乱奖励设置`,
|
||||||
worldState_bellyOfTheBeast: `兽之腹`,
|
worldState_bellyOfTheBeast: `兽之腹`,
|
||||||
@ -286,6 +300,7 @@ dict = {
|
|||||||
worldState_eightClawProgressOverride: `大帝金币收集进度(%)`,
|
worldState_eightClawProgressOverride: `大帝金币收集进度(%)`,
|
||||||
worldState_thermiaFractures: `热美亚裂缝`,
|
worldState_thermiaFractures: `热美亚裂缝`,
|
||||||
worldState_thermiaFracturesProgressOverride: `[UNTRANSLATED] Thermia Fractures Progress`,
|
worldState_thermiaFracturesProgressOverride: `[UNTRANSLATED] Thermia Fractures Progress`,
|
||||||
|
worldState_qtccAlerts: `[UNTRANSLATED] Quest to Conquer Cancer Alerts`,
|
||||||
worldState_from_year: `|VAL|`,
|
worldState_from_year: `|VAL|`,
|
||||||
worldState_pre_year: `|VAL|之前`,
|
worldState_pre_year: `|VAL|之前`,
|
||||||
worldState_week: `第|VAL|周`,
|
worldState_week: `第|VAL|周`,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user