Compare commits

...

14 Commits

Author SHA1 Message Date
61ac2f8b72 chore(webui): update Chinese translation (#2394)
Reviewed-on: OpenWF/SpaceNinjaServer#2394
Co-authored-by: Corvus <corvus@noreply.localhost>
Co-committed-by: Corvus <corvus@noreply.localhost>
2025-07-02 15:04:42 -07:00
d2ab894c01 fix(webui): assign labels for appropriate inputs (#2391)
Reviewed-on: OpenWF/SpaceNinjaServer#2391
Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
2025-07-02 14:29:41 -07:00
8c85cdcd1d feat(webui): "add maxed" for mods (#2387)
Closes #2382

Reviewed-on: OpenWF/SpaceNinjaServer#2387
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-07-02 14:18:24 -07:00
aa6191f033 feat: relic rng cheats (#2386)
Closes #2370

Reviewed-on: OpenWF/SpaceNinjaServer#2386
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-07-02 14:17:14 -07:00
e26d2635fb chore(webui): fix inconsistent % chance strings (#2385)
Closes #2381

Reviewed-on: OpenWF/SpaceNinjaServer#2385
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-07-02 14:15:50 -07:00
dd6ae8898f chore(webui): move max rank button before detailed view link (#2384)
Reviewed-on: OpenWF/SpaceNinjaServer#2384
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-07-02 14:14:19 -07:00
499ca23ffb chore(webui): update inventory when equipment was forma'd (#2383)
Reviewed-on: OpenWF/SpaceNinjaServer#2383
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-07-02 14:14:13 -07:00
d3102acb7c chore(webui): update Chinese translation (#2380)
Reviewed-on: OpenWF/SpaceNinjaServer#2380
Co-authored-by: Corvus <corvus@noreply.localhost>
Co-committed-by: Corvus <corvus@noreply.localhost>
2025-07-01 10:58:47 -07:00
363028c9ce chore: clarify log output related to saveLoadout (#2379)
Reviewed-on: OpenWF/SpaceNinjaServer#2379
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-07-01 07:48:03 -07:00
1d60745f18 feat: year rollover kiss emails (#2376)
Closes #2375

Reviewed-on: OpenWF/SpaceNinjaServer#2376
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-07-01 07:45:41 -07:00
a9b3b16d31 feat: dojo visitors (#2374)
Closes #2373

Reviewed-on: OpenWF/SpaceNinjaServer#2374
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-07-01 07:45:12 -07:00
fd1d72a1cf chore(webui): add inventory update note to quests tab (#2372)
Reviewed-on: OpenWF/SpaceNinjaServer#2372
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-07-01 07:44:30 -07:00
75832afdbe feat: relicRewardItemCountMultiplier cheat (#2369)
Reviewed-on: OpenWF/SpaceNinjaServer#2369
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-07-01 07:44:13 -07:00
aa916d2820 feat: sell genetic imprints (#2368)
Reviewed-on: OpenWF/SpaceNinjaServer#2368
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-07-01 07:44:05 -07:00
27 changed files with 298 additions and 83 deletions

View File

@ -60,6 +60,7 @@
"unlockAllSimarisResearchEntries": false, "unlockAllSimarisResearchEntries": false,
"disableDailyTribute": false, "disableDailyTribute": false,
"spoofMasteryRank": -1, "spoofMasteryRank": -1,
"relicRewardItemCountMultiplier": 1,
"nightwaveStandingMultiplier": 1, "nightwaveStandingMultiplier": 1,
"unfaithfulBugFixes": { "unfaithfulBugFixes": {
"ignore1999LastRegionPlayed": false, "ignore1999LastRegionPlayed": false,

8
package-lock.json generated
View File

@ -23,7 +23,7 @@
"ncp": "^2.0.0", "ncp": "^2.0.0",
"typescript": "^5.5", "typescript": "^5.5",
"undici": "^7.10.0", "undici": "^7.10.0",
"warframe-public-export-plus": "^0.5.74", "warframe-public-export-plus": "^0.5.76",
"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",
@ -3386,9 +3386,9 @@
} }
}, },
"node_modules/warframe-public-export-plus": { "node_modules/warframe-public-export-plus": {
"version": "0.5.74", "version": "0.5.76",
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.74.tgz", "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.76.tgz",
"integrity": "sha512-pA7dxA0lKn9w/2Sc97oxnn+CEzL1SrT9XriNLTDF4Xp+2SBEpGcfbqbdR9ljPQJopIbrc9Zy02R+uBQVomcwyA==" "integrity": "sha512-0gX3NTWaxFyzUmqBSUHhPY8pMRX92iXQFqoBuMQlMG1+6uC6JMKtwP5t8cuXR3pvV2vkaCi/cDWjP1JUChkZ9g=="
}, },
"node_modules/warframe-riven-info": { "node_modules/warframe-riven-info": {
"version": "0.1.2", "version": "0.1.2",

View File

@ -37,7 +37,7 @@
"ncp": "^2.0.0", "ncp": "^2.0.0",
"typescript": "^5.5", "typescript": "^5.5",
"undici": "^7.10.0", "undici": "^7.10.0",
"warframe-public-export-plus": "^0.5.74", "warframe-public-export-plus": "^0.5.76",
"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",

View File

@ -31,7 +31,7 @@ fs.readdirSync("../static/webui/translations").forEach(file => {
const strings = extractStrings(line); const strings = extractStrings(line);
if (Object.keys(strings).length > 0) { if (Object.keys(strings).length > 0) {
Object.entries(strings).forEach(([key, value]) => { Object.entries(strings).forEach(([key, value]) => {
if (targetStrings.hasOwnProperty(key)) { if (targetStrings.hasOwnProperty(key) && !targetStrings[key].startsWith("[UNTRANSLATED] ")) {
fs.writeSync(fileHandle, ` ${key}: \`${targetStrings[key]}\`,\n`); fs.writeSync(fileHandle, ` ${key}: \`${targetStrings[key]}\`,\n`);
} else { } else {
fs.writeSync(fileHandle, ` ${key}: \`[UNTRANSLATED] ${value}\`,\n`); fs.writeSync(fileHandle, ` ${key}: \`[UNTRANSLATED] ${value}\`,\n`);

View File

@ -5,6 +5,7 @@ import {
getGuildVault, getGuildVault,
hasAccessToDojo, hasAccessToDojo,
hasGuildPermission, hasGuildPermission,
processCompletedGuildTechProject,
processFundedGuildTechProject, processFundedGuildTechProject,
processGuildTechProjectContributionsUpdate, processGuildTechProjectContributionsUpdate,
removePigmentsFromGuildMembers, removePigmentsFromGuildMembers,
@ -51,8 +52,12 @@ export const guildTechController: RequestHandler = async (req, res) => {
}; };
if (project.CompletionDate) { if (project.CompletionDate) {
techProject.CompletionDate = toMongoDate(project.CompletionDate); techProject.CompletionDate = toMongoDate(project.CompletionDate);
if (Date.now() >= project.CompletionDate.getTime()) { if (
needSave ||= setGuildTechLogState(guild, project.ItemType, 4, project.CompletionDate); Date.now() >= project.CompletionDate.getTime() &&
setGuildTechLogState(guild, project.ItemType, 4, project.CompletionDate)
) {
processCompletedGuildTechProject(guild, project.ItemType);
needSave = true;
} }
} }
techProjects.push(techProject); techProjects.push(techProject);

View File

@ -9,6 +9,7 @@ import { IPolarity, ArtifactPolarity, EquipmentFeatures } from "@/src/types/inve
import { ExportCustoms, ExportFlavour, ExportResources, ExportVirtuals } from "warframe-public-export-plus"; import { ExportCustoms, ExportFlavour, ExportResources, ExportVirtuals } from "warframe-public-export-plus";
import { applyCheatsToInfestedFoundry, handleSubsumeCompletion } from "@/src/services/infestedFoundryService"; import { applyCheatsToInfestedFoundry, handleSubsumeCompletion } from "@/src/services/infestedFoundryService";
import { import {
addEmailItem,
addMiscItems, addMiscItems,
allDailyAffiliationKeys, allDailyAffiliationKeys,
cleanupInventory, cleanupInventory,
@ -110,7 +111,58 @@ export const inventoryController: RequestHandler = async (request, response) =>
} }
if (inventory.CalendarProgress) { if (inventory.CalendarProgress) {
const previousYearIteration = inventory.CalendarProgress.Iteration;
getCalendarProgress(inventory); // handle year rollover; the client expects to receive an inventory with an up-to-date CalendarProgress getCalendarProgress(inventory); // handle year rollover; the client expects to receive an inventory with an up-to-date CalendarProgress
// also handle sending of kiss cinematic at year rollover
if (
inventory.CalendarProgress.Iteration != previousYearIteration &&
inventory.DialogueHistory &&
inventory.DialogueHistory.Dialogues
) {
let kalymos = false;
for (const { dialogueName, kissEmail } of [
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/ArthurDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/ArthurKissEmailItem"
},
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/EleanorDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/EleanorKissEmailItem"
},
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/LettieDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/LettieKissEmailItem"
},
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/JabirDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/AmirKissEmailItem"
},
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/AoiDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/AoiKissEmailItem"
},
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/QuincyDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/QuincyKissEmailItem"
}
]) {
const dialogue = inventory.DialogueHistory.Dialogues.find(x => x.DialogueName == dialogueName);
if (dialogue) {
if (dialogue.Rank == 7) {
await addEmailItem(inventory, kissEmail);
kalymos = false;
break;
}
if (dialogue.Rank == 6) {
kalymos = true;
}
}
}
if (kalymos) {
await addEmailItem(inventory, "/Lotus/Types/Items/EmailItems/KalymosKissEmailItem");
}
}
} }
cleanupInventory(inventory); cleanupInventory(inventory);

View File

@ -57,8 +57,12 @@ export const placeDecoInComponentController: RequestHandler = async (req, res) =
component.DecoCapacity -= meta.capacityCost; component.DecoCapacity -= meta.capacityCost;
} }
} else { } else {
const [itemType, meta] = Object.entries(ExportResources).find(arr => arr[1].deco == deco.Type)!; const entry = Object.entries(ExportResources).find(arr => arr[1].deco == deco.Type);
if (!itemType || meta.dojoCapacityCost === undefined) { if (!entry) {
throw new Error(`unknown deco type: ${deco.Type}`);
}
const [itemType, meta] = entry;
if (meta.dojoCapacityCost === undefined) {
throw new Error(`unknown deco type: ${deco.Type}`); throw new Error(`unknown deco type: ${deco.Type}`);
} }
component.DecoCapacity -= meta.dojoCapacityCost; component.DecoCapacity -= meta.dojoCapacityCost;
@ -75,7 +79,13 @@ export const placeDecoInComponentController: RequestHandler = async (req, res) =
if (meta) { if (meta) {
processDojoBuildMaterialsGathered(guild, meta); processDojoBuildMaterialsGathered(guild, meta);
} }
} else if (guild.AutoContributeFromVault && guild.VaultRegularCredits && guild.VaultMiscItems) { } else if (
deco.Type.startsWith("/Lotus/Objects/Tenno/Dojo/NpcPlaceables/") ||
(guild.AutoContributeFromVault && guild.VaultRegularCredits && guild.VaultMiscItems)
) {
if (!guild.VaultRegularCredits || !guild.VaultMiscItems) {
throw new Error(`dojo visitor placed without anything in vault?!`);
}
if (guild.VaultRegularCredits >= scaleRequiredCount(guild.Tier, meta.price)) { if (guild.VaultRegularCredits >= scaleRequiredCount(guild.Tier, meta.price)) {
let enoughMiscItems = true; let enoughMiscItems = true;
for (const ingredient of meta.ingredients) { for (const ingredient of meta.ingredients) {

View File

@ -19,6 +19,7 @@ import { sendWsBroadcastTo } from "@/src/services/webService";
export const sellController: RequestHandler = async (req, res) => { export const sellController: RequestHandler = async (req, res) => {
const payload = JSON.parse(String(req.body)) as ISellRequest; const payload = JSON.parse(String(req.body)) as ISellRequest;
//console.log(JSON.stringify(payload, null, 2));
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const requiredFields = new Set<keyof TInventoryDatabaseDocument>(); const requiredFields = new Set<keyof TInventoryDatabaseDocument>();
if (payload.SellCurrency == "SC_RegularCredits") { if (payload.SellCurrency == "SC_RegularCredits") {
@ -184,6 +185,11 @@ export const sellController: RequestHandler = async (req, res) => {
inventory.Drones.pull({ _id: sellItem.String }); inventory.Drones.pull({ _id: sellItem.String });
}); });
} }
if (payload.Items.KubrowPetPrints) {
payload.Items.KubrowPetPrints.forEach(sellItem => {
inventory.KubrowPetPrints.pull({ _id: sellItem.String });
});
}
if (payload.Items.CrewMembers) { if (payload.Items.CrewMembers) {
payload.Items.CrewMembers.forEach(sellItem => { payload.Items.CrewMembers.forEach(sellItem => {
inventory.CrewMembers.pull({ _id: sellItem.String }); inventory.CrewMembers.pull({ _id: sellItem.String });
@ -312,6 +318,7 @@ interface ISellRequest {
OperatorAmps?: ISellItem[]; OperatorAmps?: ISellItem[];
Hoverboards?: ISellItem[]; Hoverboards?: ISellItem[];
Drones?: ISellItem[]; Drones?: ISellItem[];
KubrowPetPrints?: ISellItem[];
CrewMembers?: ISellItem[]; CrewMembers?: ISellItem[];
CrewShipWeapons?: ISellItem[]; CrewShipWeapons?: ISellItem[];
CrewShipWeaponSkins?: ISellItem[]; CrewShipWeaponSkins?: ISellItem[];

View File

@ -13,6 +13,7 @@ import { getRecipeByResult } from "@/src/services/itemDataService";
import { IInventoryChanges } from "@/src/types/purchaseTypes"; import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { addInfestedFoundryXP, applyCheatsToInfestedFoundry } from "@/src/services/infestedFoundryService"; import { addInfestedFoundryXP, applyCheatsToInfestedFoundry } from "@/src/services/infestedFoundryService";
import { config } from "@/src/services/configService"; import { config } from "@/src/services/configService";
import { sendWsBroadcastTo } from "@/src/services/webService";
export const upgradesController: RequestHandler = async (req, res) => { export const upgradesController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
@ -120,6 +121,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
setSlotPolarity(item, operation.PolarizeSlot, operation.PolarizeValue); setSlotPolarity(item, operation.PolarizeSlot, operation.PolarizeValue);
item.Polarized ??= 0; item.Polarized ??= 0;
item.Polarized += 1; item.Polarized += 1;
sendWsBroadcastTo(accountId, { update_inventory: true }); // webui may need to to re-add "max rank" button
break; break;
} }
case "/Lotus/Types/Items/MiscItems/ModSlotUnlocker": { case "/Lotus/Types/Items/MiscItems/ModSlotUnlocker": {

View File

@ -7,7 +7,7 @@ export const addItemsController: RequestHandler = async (req, res) => {
const requests = req.body as IAddItemRequest[]; const requests = req.body as IAddItemRequest[];
const inventory = await getInventory(accountId); const inventory = await getInventory(accountId);
for (const request of requests) { for (const request of requests) {
await addItem(inventory, request.ItemType, request.ItemCount, true, undefined, undefined, true); await addItem(inventory, request.ItemType, request.ItemCount, true, undefined, request.Fingerprint, true);
} }
await inventory.save(); await inventory.save();
res.end(); res.end();
@ -16,4 +16,5 @@ export const addItemsController: RequestHandler = async (req, res) => {
interface IAddItemRequest { interface IAddItemRequest {
ItemType: string; ItemType: string;
ItemCount: number; ItemCount: number;
Fingerprint?: string;
} }

View File

@ -6,6 +6,7 @@ import { logger } from "@/src/utils/logger";
import { addMiscItems, combineInventoryChanges } from "@/src/services/inventoryService"; import { addMiscItems, combineInventoryChanges } from "@/src/services/inventoryService";
import { handleStoreItemAcquisition } from "@/src/services/purchaseService"; import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
import { IInventoryChanges } from "../types/purchaseTypes"; import { IInventoryChanges } from "../types/purchaseTypes";
import { config } from "../services/configService";
export const crackRelic = async ( export const crackRelic = async (
inventory: TInventoryDatabaseDocument, inventory: TInventoryDatabaseDocument,
@ -13,7 +14,14 @@ export const crackRelic = async (
inventoryChanges: IInventoryChanges = {} inventoryChanges: IInventoryChanges = {}
): Promise<IRngResult> => { ): Promise<IRngResult> => {
const relic = ExportRelics[participant.VoidProjection]; const relic = ExportRelics[participant.VoidProjection];
const weights = refinementToWeights[relic.quality]; let weights = refinementToWeights[relic.quality];
if (relic.quality == "VPQ_SILVER" && config.exceptionalRelicsAlwaysGiveBronzeReward) {
weights = { COMMON: 1, UNCOMMON: 0, RARE: 0, LEGENDARY: 0 };
} else if (relic.quality == "VPQ_GOLD" && config.flawlessRelicsAlwaysGiveSilverReward) {
weights = { COMMON: 0, UNCOMMON: 1, RARE: 0, LEGENDARY: 0 };
} else if (relic.quality == "VPQ_PLATINUM" && config.radiantRelicsAlwaysGiveGoldReward) {
weights = { COMMON: 0, UNCOMMON: 0, RARE: 1, LEGENDARY: 0 };
}
logger.debug(`opening a relic of quality ${relic.quality}; rarity weights are`, weights); logger.debug(`opening a relic of quality ${relic.quality}; rarity weights are`, weights);
const reward = getRandomWeightedReward( const reward = getRandomWeightedReward(
ExportRewards[relic.rewardManifest][0] as { type: string; itemCount: number; rarity: TRarity }[], // rarity is nullable in PE+ typings, but always present for relics ExportRewards[relic.rewardManifest][0] as { type: string; itemCount: number; rarity: TRarity }[], // rarity is nullable in PE+ typings, but always present for relics
@ -35,7 +43,13 @@ export const crackRelic = async (
// Give reward // Give reward
combineInventoryChanges( combineInventoryChanges(
inventoryChanges, inventoryChanges,
(await handleStoreItemAcquisition(reward.type, inventory, reward.itemCount)).InventoryChanges (
await handleStoreItemAcquisition(
reward.type,
inventory,
reward.itemCount * (config.relicRewardItemCountMultiplier ?? 1)
)
).InventoryChanges
); );
return reward; return reward;

View File

@ -23,7 +23,9 @@ export interface IMessageDatabase extends IMessage {
export interface IMessage { export interface IMessage {
sndr: string; sndr: string;
msg: string; msg: string;
cinematic?: string;
sub: string; sub: string;
customData?: string;
icon?: string; icon?: string;
highPriority?: boolean; highPriority?: boolean;
lowPrioNewPlayers?: boolean; lowPrioNewPlayers?: boolean;
@ -102,7 +104,9 @@ const messageSchema = new Schema<IMessageDatabase>(
ownerId: Schema.Types.ObjectId, ownerId: Schema.Types.ObjectId,
sndr: String, sndr: String,
msg: String, msg: String,
cinematic: String,
sub: String, sub: String,
customData: String,
icon: String, icon: String,
highPriority: Boolean, highPriority: Boolean,
lowPrioNewPlayers: Boolean, lowPrioNewPlayers: Boolean,

View File

@ -64,9 +64,13 @@ export interface IConfig {
noDojoResearchTime?: boolean; noDojoResearchTime?: boolean;
fastClanAscension?: boolean; fastClanAscension?: boolean;
missionsCanGiveAllRelics?: boolean; missionsCanGiveAllRelics?: boolean;
exceptionalRelicsAlwaysGiveBronzeReward?: boolean;
flawlessRelicsAlwaysGiveSilverReward?: boolean;
radiantRelicsAlwaysGiveGoldReward?: boolean;
unlockAllSimarisResearchEntries?: boolean; unlockAllSimarisResearchEntries?: boolean;
disableDailyTribute?: boolean; disableDailyTribute?: boolean;
spoofMasteryRank?: number; spoofMasteryRank?: number;
relicRewardItemCountMultiplier?: number;
nightwaveStandingMultiplier?: number; nightwaveStandingMultiplier?: number;
unfaithfulBugFixes?: { unfaithfulBugFixes?: {
ignore1999LastRegionPlayed?: boolean; ignore1999LastRegionPlayed?: boolean;

View File

@ -550,6 +550,19 @@ export const processFundedGuildTechProject = (
guild.XP += recipe.guildXpValue; guild.XP += recipe.guildXpValue;
} }
setGuildTechLogState(guild, techProject.ItemType, config.noDojoResearchTime ? 4 : 3, techProject.CompletionDate); setGuildTechLogState(guild, techProject.ItemType, config.noDojoResearchTime ? 4 : 3, techProject.CompletionDate);
if (config.noDojoResearchTime) {
processCompletedGuildTechProject(guild, techProject.ItemType);
}
};
export const processCompletedGuildTechProject = (guild: TGuildDatabaseDocument, type: string): void => {
if (type.startsWith("/Lotus/Levels/ClanDojo/ComponentPropRecipes/NpcPlaceables/")) {
guild.VaultDecoRecipes ??= [];
guild.VaultDecoRecipes.push({
ItemType: type,
ItemCount: 1
});
}
}; };
export const setGuildTechLogState = ( export const setGuildTechLogState = (

View File

@ -83,7 +83,7 @@ import { addQuestKey, completeQuest } from "@/src/services/questService";
import { handleBundleAcqusition } from "./purchaseService"; import { handleBundleAcqusition } from "./purchaseService";
import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json"; import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json";
import { getRandomElement, getRandomInt, getRandomWeightedReward, SRng } from "./rngService"; import { getRandomElement, getRandomInt, getRandomWeightedReward, SRng } from "./rngService";
import { createMessage } from "./inboxService"; import { createMessage, IMessageCreationTemplate } from "./inboxService";
import { getMaxStanding, getMinStanding } from "@/src/helpers/syndicateStandingHelper"; import { getMaxStanding, getMinStanding } from "@/src/helpers/syndicateStandingHelper";
import { getNightwaveSyndicateTag, getWorldState } from "./worldStateService"; import { getNightwaveSyndicateTag, getWorldState } from "./worldStateService";
import { ICalendarSeason } from "@/src/types/worldStateTypes"; import { ICalendarSeason } from "@/src/types/worldStateTypes";
@ -483,6 +483,16 @@ export const addItem = async (
return addCustomization(inventory, typeName); return addCustomization(inventory, typeName);
} }
if (typeName in ExportUpgrades || typeName in ExportArcanes) { if (typeName in ExportUpgrades || typeName in ExportArcanes) {
if (targetFingerprint) {
if (quantity != 1) {
logger.warn(`adding 1 of ${typeName} ${targetFingerprint} even tho quantity ${quantity} was requested`);
}
inventory.Upgrades.push({
ItemType: typeName,
UpgradeFingerprint: targetFingerprint
});
return {}; // there's not exactly a common "InventoryChanges" format for these
}
const changes = [ const changes = [
{ {
ItemType: typeName, ItemType: typeName,
@ -1563,7 +1573,22 @@ export const addEmailItem = async (
const meta = ExportEmailItems[typeName]; const meta = ExportEmailItems[typeName];
const emailItem = inventory.EmailItems.find(x => x.ItemType == typeName); const emailItem = inventory.EmailItems.find(x => x.ItemType == typeName);
if (!emailItem || !meta.sendOnlyOnce) { if (!emailItem || !meta.sendOnlyOnce) {
await createMessage(inventory.accountOwnerId, [convertInboxMessage(meta.message)]); const msg: IMessageCreationTemplate = convertInboxMessage(meta.message);
if (msg.cinematic == "/Lotus/Levels/1999/PlayerHomeBalconyCinematics.level") {
msg.customData = JSON.stringify({
Tag: msg.customData + "KissCin",
CinLoadout: {
Skins: inventory.AdultOperatorLoadOuts[0].Skins,
Upgrades: inventory.AdultOperatorLoadOuts[0].Upgrades,
attcol: inventory.AdultOperatorLoadOuts[0].attcol,
cloth: inventory.AdultOperatorLoadOuts[0].cloth,
eyecol: inventory.AdultOperatorLoadOuts[0].eyecol,
pricol: inventory.AdultOperatorLoadOuts[0].pricol,
syancol: inventory.AdultOperatorLoadOuts[0].syancol
}
});
}
await createMessage(inventory.accountOwnerId, [msg]);
if (emailItem) { if (emailItem) {
emailItem.ItemCount += 1; emailItem.ItemCount += 1;

View File

@ -251,7 +251,9 @@ export const convertInboxMessage = (message: IInboxMessage): IMessage => {
return { return {
sndr: message.sender, sndr: message.sender,
msg: message.body, msg: message.body,
cinematic: message.cinematic,
sub: message.title, sub: message.title,
customData: message.customData,
att: message.attachments.length > 0 ? message.attachments : undefined, att: message.attachments.length > 0 ? message.attachments : undefined,
countedAtt: message.countedAttachments.length > 0 ? message.countedAttachments : undefined, countedAtt: message.countedAttachments.length > 0 ? message.countedAttachments : undefined,
icon: message.icon ?? "", icon: message.icon ?? "",

View File

@ -167,8 +167,13 @@ export const handleInventoryItemConfigChange = async (
inventory.LotusCustomization = equipmentChanges.LotusCustomization; inventory.LotusCustomization = equipmentChanges.LotusCustomization;
break; break;
} }
case "ValidNewLoadoutId": {
logger.debug(`ignoring ValidNewLoadoutId (${equipmentChanges.ValidNewLoadoutId})`);
// seems always equal to the id of loadout config NORMAL[0], likely has no purpose and we're free to ignore it
break;
}
default: { default: {
if (equipmentKeys.includes(equipmentName as TEquipmentKey) && equipmentName != "ValidNewLoadoutId") { if (equipmentKeys.includes(equipmentName as TEquipmentKey)) {
logger.debug(`general Item config saved of type ${equipmentName}`, { logger.debug(`general Item config saved of type ${equipmentName}`, {
config: equipment config: equipment
}); });
@ -216,7 +221,7 @@ export const handleInventoryItemConfigChange = async (
} }
break; break;
} else { } else {
logger.warn(`loadout category not implemented, changes may be lost: ${equipmentName}`, { logger.error(`loadout category not implemented, changes will be lost: ${equipmentName}`, {
config: equipment config: equipment
}); });
} }

View File

@ -64,8 +64,12 @@ export const handleSetShipDecorations = async (
throw new Error(`unknown room: ${placedDecoration.Room}`); throw new Error(`unknown room: ${placedDecoration.Room}`);
} }
const [itemType, meta] = Object.entries(ExportResources).find(arr => arr[1].deco == placedDecoration.Type)!; const entry = Object.entries(ExportResources).find(arr => arr[1].deco == placedDecoration.Type);
if (!itemType || meta.capacityCost === undefined) { if (!entry) {
throw new Error(`unknown deco type: ${placedDecoration.Type}`);
}
const [itemType, meta] = entry;
if (meta.capacityCost === undefined) {
throw new Error(`unknown deco type: ${placedDecoration.Type}`); throw new Error(`unknown deco type: ${placedDecoration.Type}`);
} }

View File

@ -92,5 +92,13 @@
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/ThumperTrophySilverRecipe", "/Lotus/Levels/ClanDojo/ComponentPropRecipes/ThumperTrophySilverRecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/CorpusPlaceables/GasTurbineConeRecipe", "/Lotus/Levels/ClanDojo/ComponentPropRecipes/CorpusPlaceables/GasTurbineConeRecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/NaturalPlaceables/CoralChunkARecipe", "/Lotus/Levels/ClanDojo/ComponentPropRecipes/NaturalPlaceables/CoralChunkARecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/TennoPlaceables/TnoBeaconEmitterRecipe" "/Lotus/Levels/ClanDojo/ComponentPropRecipes/TennoPlaceables/TnoBeaconEmitterRecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/NpcPlaceables/OstronFemaleSitting",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/NpcPlaceables/OstronFemaleStanding",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/NpcPlaceables/OstronMaleStanding",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/NpcPlaceables/OstronMaleStandingTwo",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/NpcPlaceables/SolarisForeman",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/NpcPlaceables/SolarisHazard",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/NpcPlaceables/SolarisStrikerOne",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/NpcPlaceables/SolarisStrikerThree"
] ]

View File

@ -527,6 +527,7 @@
<form class="input-group mb-3" onsubmit="doAcquireMod();return false;"> <form class="input-group mb-3" onsubmit="doAcquireMod();return false;">
<input class="form-control" id="mod-count" type="number" value="1"/> <input class="form-control" id="mod-count" type="number" value="1"/>
<input class="form-control w-50" id="mod-to-acquire" list="datalist-mods" /> <input class="form-control w-50" id="mod-to-acquire" list="datalist-mods" />
<button class="btn btn-success" onclick="window.maxed=true" type="submit" data-loc="mods_addMax"></button>
<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>
<table class="table table-hover w-100"> <table class="table table-hover w-100">
@ -546,6 +547,7 @@
</div> </div>
</div> </div>
<div data-route="/webui/quests" data-title="Quests | OpenWF WebUI"> <div data-route="/webui/quests" data-title="Quests | OpenWF WebUI">
<p class="mb-3" data-loc="general_inventoryUpdateNote"></p>
<div class="row g-3"> <div class="row g-3">
<div class="col-md-6"> <div class="col-md-6">
<div class="card"> <div class="card">
@ -777,6 +779,18 @@
<input class="form-check-input" type="checkbox" id="missionsCanGiveAllRelics" /> <input class="form-check-input" type="checkbox" id="missionsCanGiveAllRelics" />
<label class="form-check-label" for="missionsCanGiveAllRelics" data-loc="cheats_missionsCanGiveAllRelics"></label> <label class="form-check-label" for="missionsCanGiveAllRelics" data-loc="cheats_missionsCanGiveAllRelics"></label>
</div> </div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="exceptionalRelicsAlwaysGiveBronzeReward" />
<label class="form-check-label" for="exceptionalRelicsAlwaysGiveBronzeReward" data-loc="cheats_exceptionalRelicsAlwaysGiveBronzeReward"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="flawlessRelicsAlwaysGiveSilverReward" />
<label class="form-check-label" for="flawlessRelicsAlwaysGiveSilverReward" data-loc="cheats_flawlessRelicsAlwaysGiveSilverReward"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="radiantRelicsAlwaysGiveGoldReward" />
<label class="form-check-label" for="radiantRelicsAlwaysGiveGoldReward" data-loc="cheats_radiantRelicsAlwaysGiveGoldReward"></label>
</div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" id="unlockAllSimarisResearchEntries" /> <input class="form-check-input" type="checkbox" id="unlockAllSimarisResearchEntries" />
<label class="form-check-label" for="unlockAllSimarisResearchEntries" data-loc="cheats_unlockAllSimarisResearchEntries"></label> <label class="form-check-label" for="unlockAllSimarisResearchEntries" data-loc="cheats_unlockAllSimarisResearchEntries"></label>
@ -788,14 +802,21 @@
<form class="form-group mt-2" onsubmit="doSaveConfigInt('spoofMasteryRank'); return false;"> <form class="form-group mt-2" onsubmit="doSaveConfigInt('spoofMasteryRank'); return false;">
<label class="form-label" for="spoofMasteryRank" data-loc="cheats_spoofMasteryRank"></label> <label class="form-label" for="spoofMasteryRank" data-loc="cheats_spoofMasteryRank"></label>
<div class="input-group"> <div class="input-group">
<input class="form-control" id="spoofMasteryRank" type="number" min="-1" max="65535" /> <input class="form-control" id="spoofMasteryRank" type="number" min="-1" max="65535" data-default="-1" />
<button class="btn btn-primary" type="submit" data-loc="cheats_save"></button>
</div>
</form>
<form class="form-group mt-2" onsubmit="doSaveConfigInt('relicRewardItemCountMultiplier'); return false;">
<label class="form-label" for="relicRewardItemCountMultiplier" data-loc="cheats_relicRewardItemCountMultiplier"></label>
<div class="input-group">
<input class="form-control" id="relicRewardItemCountMultiplier" type="number" min="1" max="1000000" data-default="1" />
<button class="btn btn-primary" type="submit" data-loc="cheats_save"></button> <button class="btn btn-primary" type="submit" data-loc="cheats_save"></button>
</div> </div>
</form> </form>
<form class="form-group mt-2" onsubmit="doSaveConfigInt('nightwaveStandingMultiplier'); return false;"> <form class="form-group mt-2" onsubmit="doSaveConfigInt('nightwaveStandingMultiplier'); return false;">
<label class="form-label" for="nightwaveStandingMultiplier" data-loc="cheats_nightwaveStandingMultiplier"></label> <label class="form-label" for="nightwaveStandingMultiplier" data-loc="cheats_nightwaveStandingMultiplier"></label>
<div class="input-group"> <div class="input-group">
<input class="form-control" id="nightwaveStandingMultiplier" type="number" min="1" max="1000000" value="1" /> <input class="form-control" id="nightwaveStandingMultiplier" type="number" min="1" max="1000000" data-default="1" />
<button class="btn btn-primary" type="submit" data-loc="cheats_save"></button> <button class="btn btn-primary" type="submit" data-loc="cheats_save"></button>
</div> </div>
</form> </form>
@ -844,7 +865,7 @@
<label class="form-check-label" for="worldState.starDays" data-loc="worldState_starDays"></label> <label class="form-check-label" for="worldState.starDays" data-loc="worldState_starDays"></label>
</div> </div>
<div class="form-group mt-2"> <div class="form-group mt-2">
<label class="form-label" for="changeSyndicate" data-loc="worldState_galleonOfGhouls"></label> <label class="form-label" for="worldState.galleonOfGhouls" data-loc="worldState_galleonOfGhouls"></label>
<select class="form-control" id="worldState.galleonOfGhouls"> <select class="form-control" id="worldState.galleonOfGhouls">
<option value="0" data-loc="disabled"></option> <option value="0" data-loc="disabled"></option>
<option value="1" data-loc="worldState_we1"></option> <option value="1" data-loc="worldState_we1"></option>
@ -853,7 +874,7 @@
</select> </select>
</div> </div>
<div class="form-group mt-2"> <div class="form-group mt-2">
<label class="form-label" for="changeSyndicate" data-loc="worldState_eidolonOverride"></label> <label class="form-label" for="worldState.eidolonOverride" data-loc="worldState_eidolonOverride"></label>
<select class="form-control" id="worldState.eidolonOverride"> <select class="form-control" id="worldState.eidolonOverride">
<option value="" data-loc="disabled"></option> <option value="" data-loc="disabled"></option>
<option value="day" data-loc="worldState_day"></option> <option value="day" data-loc="worldState_day"></option>
@ -861,7 +882,7 @@
</select> </select>
</div> </div>
<div class="form-group mt-2"> <div class="form-group mt-2">
<label class="form-label" for="changeSyndicate" data-loc="worldState_vallisOverride"></label> <label class="form-label" for="worldState.vallisOverride" data-loc="worldState_vallisOverride"></label>
<select class="form-control" id="worldState.vallisOverride"> <select class="form-control" id="worldState.vallisOverride">
<option value="" data-loc="disabled"></option> <option value="" data-loc="disabled"></option>
<option value="warm" data-loc="worldState_warm"></option> <option value="warm" data-loc="worldState_warm"></option>
@ -869,7 +890,7 @@
</select> </select>
</div> </div>
<div class="form-group mt-2"> <div class="form-group mt-2">
<label class="form-label" for="changeSyndicate" data-loc="worldState_duviriOverride"></label> <label class="form-label" for="worldState.duviriOverride" data-loc="worldState_duviriOverride"></label>
<select class="form-control" id="worldState.duviriOverride"> <select class="form-control" id="worldState.duviriOverride">
<option value="" data-loc="disabled"></option> <option value="" data-loc="disabled"></option>
<option value="joy" data-loc="worldState_joy"></option> <option value="joy" data-loc="worldState_joy"></option>
@ -880,7 +901,7 @@
</select> </select>
</div> </div>
<div class="form-group mt-2"> <div class="form-group mt-2">
<label class="form-label" for="changeSyndicate" data-loc="worldState_nightwaveOverride"></label> <label class="form-label" for="worldState.nightwaveOverride" data-loc="worldState_nightwaveOverride"></label>
<select class="form-control" id="worldState.nightwaveOverride"> <select class="form-control" id="worldState.nightwaveOverride">
<option value="" data-loc="disabled"></option> <option value="" data-loc="disabled"></option>
<option value="RadioLegionIntermission13Syndicate" data-loc="worldState_RadioLegionIntermission13Syndicate"></option> <option value="RadioLegionIntermission13Syndicate" data-loc="worldState_RadioLegionIntermission13Syndicate"></option>
@ -902,7 +923,7 @@
</select> </select>
</div> </div>
<div class="form-group mt-2"> <div class="form-group mt-2">
<label class="form-label" for="changeSyndicate" data-loc="worldState_fissures"></label> <label class="form-label" for="worldState.allTheFissures" data-loc="worldState_fissures"></label>
<select class="form-control" id="worldState.allTheFissures"> <select class="form-control" id="worldState.allTheFissures">
<option value="" data-loc="normal"></option> <option value="" data-loc="normal"></option>
<option value="normal" data-loc="worldState_allAtOnceNormal"></option> <option value="normal" data-loc="worldState_allAtOnceNormal"></option>
@ -917,9 +938,9 @@
</div> </div>
</form> </form>
<form class="form-group mt-2" onsubmit="doSaveConfigFloat('worldState.darvoStockMultiplier'); return false;"> <form class="form-group mt-2" onsubmit="doSaveConfigFloat('worldState.darvoStockMultiplier'); return false;">
<label class="form-label" for="worldState.circuitGameModes" data-loc="worldState_darvoStockMultiplier"></label> <label class="form-label" for="worldState.darvoStockMultiplier" data-loc="worldState_darvoStockMultiplier"></label>
<div class="input-group"> <div class="input-group">
<input id="worldState.darvoStockMultiplier" class="form-control" type="number" step="0.01" placeholder="1" /> <input id="worldState.darvoStockMultiplier" class="form-control" type="number" step="0.01" data-default="1" />
<button class="btn btn-primary" type="submit" data-loc="cheats_save"></button> <button class="btn btn-primary" type="submit" data-loc="cheats_save"></button>
</div> </div>
</form> </form>

View File

@ -651,6 +651,7 @@ function updateInventory() {
{ {
const td = document.createElement("td"); const td = document.createElement("td");
td.classList = "text-end text-nowrap"; td.classList = "text-end text-nowrap";
let maxXP = Math.pow(uniqueLevelCaps[item.ItemType] ?? 30, 2) * 1000; let maxXP = Math.pow(uniqueLevelCaps[item.ItemType] ?? 30, 2) * 1000;
if ( if (
category != "Suits" && category != "Suits" &&
@ -663,7 +664,6 @@ function updateInventory() {
) { ) {
maxXP /= 2; maxXP /= 2;
} }
let anyExaltedMissingXP = false; let anyExaltedMissingXP = false;
if (item.XP >= maxXP && item.ItemType in itemMap && "exalted" in itemMap[item.ItemType]) { if (item.XP >= maxXP && item.ItemType in itemMap && "exalted" in itemMap[item.ItemType]) {
for (const exaltedType of itemMap[item.ItemType].exalted) { for (const exaltedType of itemMap[item.ItemType].exalted) {
@ -677,13 +677,6 @@ function updateInventory() {
} }
} }
} }
if (["Suits", "LongGuns", "Pistols", "Melee", "SpaceGuns", "SpaceMelee"].includes(category)) {
const a = document.createElement("a");
a.href = "/webui/detailedView?productCategory=" + category + "&itemId=" + item.ItemId.$oid;
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M278.5 215.6L23 471c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l57-57h68c49.7 0 97.9-14.4 139-41c11.1-7.2 5.5-23-7.8-23c-5.1 0-9.2-4.1-9.2-9.2c0-4.1 2.7-7.6 6.5-8.8l81-24.3c2.5-.8 4.8-2.1 6.7-4l22.4-22.4c10.1-10.1 2.9-27.3-11.3-27.3l-32.2 0c-5.1 0-9.2-4.1-9.2-9.2c0-4.1 2.7-7.6 6.5-8.8l112-33.6c4-1.2 7.4-3.9 9.3-7.7C506.4 207.6 512 184.1 512 160c0-41-16.3-80.3-45.3-109.3l-5.5-5.5C432.3 16.3 393 0 352 0s-80.3 16.3-109.3 45.3L139 149C91 197 64 262.1 64 330v55.3L253.6 195.8c6.2-6.2 16.4-6.2 22.6 0c5.4 5.4 6.1 13.6 2.2 19.8z"/></svg>`;
td.appendChild(a);
}
if (item.XP < maxXP || anyExaltedMissingXP) { if (item.XP < maxXP || anyExaltedMissingXP) {
const a = document.createElement("a"); const a = document.createElement("a");
a.href = "#"; a.href = "#";
@ -721,6 +714,14 @@ function updateInventory() {
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M214.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-160 160c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 141.2V448c0 17.7 14.3 32 32 32s32-14.3 32-32V141.2L329.4 246.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z"/></svg>`; a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M214.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-160 160c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 141.2V448c0 17.7 14.3 32 32 32s32-14.3 32-32V141.2L329.4 246.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z"/></svg>`;
td.appendChild(a); td.appendChild(a);
} }
if (["Suits", "LongGuns", "Pistols", "Melee", "SpaceGuns", "SpaceMelee"].includes(category)) {
const a = document.createElement("a");
a.href = "/webui/detailedView?productCategory=" + category + "&itemId=" + item.ItemId.$oid;
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M278.5 215.6L23 471c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l57-57h68c49.7 0 97.9-14.4 139-41c11.1-7.2 5.5-23-7.8-23c-5.1 0-9.2-4.1-9.2-9.2c0-4.1 2.7-7.6 6.5-8.8l81-24.3c2.5-.8 4.8-2.1 6.7-4l22.4-22.4c10.1-10.1 2.9-27.3-11.3-27.3l-32.2 0c-5.1 0-9.2-4.1-9.2-9.2c0-4.1 2.7-7.6 6.5-8.8l112-33.6c4-1.2 7.4-3.9 9.3-7.7C506.4 207.6 512 184.1 512 160c0-41-16.3-80.3-45.3-109.3l-5.5-5.5C432.3 16.3 393 0 352 0s-80.3 16.3-109.3 45.3L139 149C91 197 64 262.1 64 330v55.3L253.6 195.8c6.2-6.2 16.4-6.2 22.6 0c5.4 5.4 6.1 13.6 2.2 19.8z"/></svg>`;
td.appendChild(a);
}
if (!(item.Features & 8) && modularWeapons.includes(item.ItemType)) { if (!(item.Features & 8) && modularWeapons.includes(item.ItemType)) {
const a = document.createElement("a"); const a = document.createElement("a");
a.href = "#"; a.href = "#";
@ -1872,6 +1873,8 @@ function setFingerprint(ItemType, ItemId, fingerprint) {
} }
function doAcquireMod() { function doAcquireMod() {
const maxed = !!window.maxed;
window.maxed = false;
const uniqueName = getKey(document.getElementById("mod-to-acquire")); const uniqueName = getKey(document.getElementById("mod-to-acquire"));
if (!uniqueName) { if (!uniqueName) {
$("#mod-to-acquire").addClass("is-invalid").focus(); $("#mod-to-acquire").addClass("is-invalid").focus();
@ -1879,14 +1882,15 @@ function doAcquireMod() {
} }
const count = parseInt($("#mod-count").val()); const count = parseInt($("#mod-count").val());
if (count != 0) { if (count != 0) {
revalidateAuthz().then(() => { Promise.all([window.itemListPromise, revalidateAuthz()]).then(([itemList]) => {
$.post({ $.post({
url: "/custom/addItems?" + window.authz, url: "/custom/addItems?" + window.authz,
contentType: "application/json", contentType: "application/json",
data: JSON.stringify([ data: JSON.stringify([
{ {
ItemType: uniqueName, ItemType: uniqueName,
ItemCount: count ItemCount: count,
Fingerprint: maxed ? JSON.stringify({ lvl: itemList[uniqueName].fusionLimit ?? 5 }) : undefined
} }
]) ])
}).done(function () { }).done(function () {
@ -1901,6 +1905,11 @@ function doAcquireMod() {
} }
} }
function doAcquireModMax() {
const uniqueName = getKey(document.getElementById("mod-to-acquire"));
alert("doAcquireModMax: " + uniqueName);
}
const uiConfigs = [...$(".config-form input[id], .config-form select[id]")].map(x => x.id); const uiConfigs = [...$(".config-form input[id], .config-form select[id]")].map(x => x.id);
for (const id of uiConfigs) { for (const id of uiConfigs) {
@ -1984,16 +1993,14 @@ single.getRoute("/webui/cheats").on("beforeload", function () {
$(".config-admin-show").removeClass("d-none"); $(".config-admin-show").removeClass("d-none");
Object.entries(json).forEach(entry => { Object.entries(json).forEach(entry => {
const [key, value] = entry; const [key, value] = entry;
var x = document.getElementById(`${key}`); const elm = document.getElementById(key);
if (x != null) { if (elm.type == "checkbox") {
if (x.type == "checkbox") { elm.checked = value;
x.checked = value; } else if (elm.classList.contains("tags-input")) {
} else if (x.classList.contains("tags-input")) { elm.value = value.join(", ");
x.value = value.join(", "); elm.oninput();
x.oninput(); } else {
} else { elm.value = value ?? elm.getAttribute("data-default");
x.value = value;
}
} }
}); });
}) })

View File

@ -127,6 +127,7 @@ dict = {
mods_fingerprintHelp: `Benötigst du Hilfe mit dem Fingerabdruck?`, mods_fingerprintHelp: `Benötigst du Hilfe mit dem Fingerabdruck?`,
mods_rivens: `Rivens`, mods_rivens: `Rivens`,
mods_mods: `Mods`, mods_mods: `Mods`,
mods_addMax: `[UNTRANSLATED] Add Maxed`,
mods_addMissingUnrankedMods: `Fehlende Mods ohne Rang hinzufügen`, mods_addMissingUnrankedMods: `Fehlende Mods ohne Rang hinzufügen`,
mods_removeUnranked: `Mods ohne Rang entfernen`, mods_removeUnranked: `Mods ohne Rang entfernen`,
mods_addMissingMaxRankMods: `Fehlende Mods mit Max. Rang hinzufügen`, mods_addMissingMaxRankMods: `Fehlende Mods mit Max. Rang hinzufügen`,
@ -182,9 +183,13 @@ dict = {
cheats_noDojoResearchTime: `Keine Dojo-Forschungszeit`, cheats_noDojoResearchTime: `Keine Dojo-Forschungszeit`,
cheats_fastClanAscension: `Schneller Clan-Aufstieg`, cheats_fastClanAscension: `Schneller Clan-Aufstieg`,
cheats_missionsCanGiveAllRelics: `[UNTRANSLATED] Missions Can Give All Relics`, cheats_missionsCanGiveAllRelics: `[UNTRANSLATED] Missions Can Give All Relics`,
cheats_exceptionalRelicsAlwaysGiveBronzeReward: `[UNTRANSLATED] Exceptional Relics Always Give Bronze Reward`,
cheats_flawlessRelicsAlwaysGiveSilverReward: `[UNTRANSLATED] Flawless Relics Always Give Silver Reward`,
cheats_radiantRelicsAlwaysGiveGoldReward: `[UNTRANSLATED] Radiant Relics Always Give Gold Reward`,
cheats_unlockAllSimarisResearchEntries: `[UNTRANSLATED] Unlock All Simaris Research Entries`, cheats_unlockAllSimarisResearchEntries: `[UNTRANSLATED] Unlock All Simaris Research Entries`,
cheats_disableDailyTribute: `[UNTRANSLATED] Disable Daily Tribute`, cheats_disableDailyTribute: `[UNTRANSLATED] Disable Daily Tribute`,
cheats_spoofMasteryRank: `Gefälschter Meisterschaftsrang (-1 zum deaktivieren)`, cheats_spoofMasteryRank: `Gefälschter Meisterschaftsrang (-1 zum deaktivieren)`,
cheats_relicRewardItemCountMultiplier: `[UNTRANSLATED] Relic Reward Item Count Multiplier`,
cheats_nightwaveStandingMultiplier: `[UNTRANSLATED] Nightwave Standing Multiplier`, cheats_nightwaveStandingMultiplier: `[UNTRANSLATED] Nightwave Standing Multiplier`,
cheats_save: `[UNTRANSLATED] Save`, cheats_save: `[UNTRANSLATED] Save`,
cheats_account: `Account`, cheats_account: `Account`,
@ -281,19 +286,19 @@ dict = {
upgrade_AvatarLootRadar: `[UNTRANSLATED] +7m Loot Radar`, upgrade_AvatarLootRadar: `[UNTRANSLATED] +7m Loot Radar`,
upgrade_WeaponAmmoMax: `[UNTRANSLATED] +15% Ammo Max`, upgrade_WeaponAmmoMax: `[UNTRANSLATED] +15% Ammo Max`,
upgrade_EnemyArmorReductionAura: `[UNTRANSLATED] -3% Enemy Armor`, upgrade_EnemyArmorReductionAura: `[UNTRANSLATED] -3% Enemy Armor`,
upgrade_OnExecutionAmmo: `[UNTRANSLATED] 100% Primary and Secondary Magazine Refill on Mercy`, upgrade_OnExecutionAmmo: `[UNTRANSLATED] +100% Primary and Secondary Magazine Refill on Mercy`,
upgrade_OnExecutionHealthDrop: `[UNTRANSLATED] 100% chance to drop a Health Orb on Mercy`, upgrade_OnExecutionHealthDrop: `[UNTRANSLATED] +100% Health Orb Chance on Mercy`,
upgrade_OnExecutionEnergyDrop: `[UNTRANSLATED] 50% chance to drop an Energy Orb on Mercy`, upgrade_OnExecutionEnergyDrop: `[UNTRANSLATED] +50% Energy Orb Chance on Mercy`,
upgrade_OnFailHackReset: `[UNTRANSLATED] +50% to retry on Hacking failure`, upgrade_OnFailHackReset: `[UNTRANSLATED] +50% Hacking Retry Chance`,
upgrade_DamageReductionOnHack: `[UNTRANSLATED] 75% Damage Reduction while Hacking`, upgrade_DamageReductionOnHack: `[UNTRANSLATED] +75% Damage Reduction while Hacking`,
upgrade_OnExecutionReviveCompanion: `[UNTRANSLATED] Mercy Kills reduce Companion Recovery by 15s`, upgrade_OnExecutionReviveCompanion: `[UNTRANSLATED] Mercy Kills reduce Companion Recovery by 15s`,
upgrade_OnExecutionParkourSpeed: `[UNTRANSLATED] +60% Parkour Speed after a Mercy for 15s`, upgrade_OnExecutionParkourSpeed: `[UNTRANSLATED] +60% Parkour Speed after a Mercy for 15s`,
upgrade_AvatarTimeLimitIncrease: `[UNTRANSLATED] +8s to Hacking`, upgrade_AvatarTimeLimitIncrease: `[UNTRANSLATED] +8s to Hacking`,
upgrade_ElectrifyOnHack: `[UNTRANSLATED] Shock enemies within 20m while Hacking`, upgrade_ElectrifyOnHack: `[UNTRANSLATED] Shock enemies within 20m while Hacking`,
upgrade_OnExecutionTerrify: `[UNTRANSLATED] 50% chance for enemies within 15m to cower in fear for 8 seconds on Mercy`, upgrade_OnExecutionTerrify: `[UNTRANSLATED] +50% chance for enemies within 15m to cower in fear for 8 seconds on Mercy`,
upgrade_OnHackLockers: `[UNTRANSLATED] Unlock 5 lockers within 20m after Hacking`, upgrade_OnHackLockers: `[UNTRANSLATED] Unlock 5 lockers within 20m after Hacking`,
upgrade_OnExecutionBlind: `[UNTRANSLATED] Blind enemies within 18m on Mercy`, upgrade_OnExecutionBlind: `[UNTRANSLATED] Blind enemies within 18m on Mercy`,
upgrade_OnExecutionDrainPower: `[UNTRANSLATED] 100% chance for next ability cast to gain +50% Ability Strength on Mercy`, upgrade_OnExecutionDrainPower: `[UNTRANSLATED] +100% chance for next ability cast to gain +50% Ability Strength on Mercy`,
upgrade_OnHackSprintSpeed: `[UNTRANSLATED] +75% Sprint Speed for 15s after Hacking`, upgrade_OnHackSprintSpeed: `[UNTRANSLATED] +75% Sprint Speed for 15s after Hacking`,
upgrade_SwiftExecute: `[UNTRANSLATED] Speed of Mercy Kills increased by 50%`, upgrade_SwiftExecute: `[UNTRANSLATED] Speed of Mercy Kills increased by 50%`,
upgrade_OnHackInvis: `[UNTRANSLATED] Invisible for 15 seconds after hacking`, upgrade_OnHackInvis: `[UNTRANSLATED] Invisible for 15 seconds after hacking`,

View File

@ -126,6 +126,7 @@ dict = {
mods_fingerprintHelp: `Need help with the fingerprint?`, mods_fingerprintHelp: `Need help with the fingerprint?`,
mods_rivens: `Rivens`, mods_rivens: `Rivens`,
mods_mods: `Mods`, mods_mods: `Mods`,
mods_addMax: `Add Maxed`,
mods_addMissingUnrankedMods: `Add Missing Unranked Mods`, mods_addMissingUnrankedMods: `Add Missing Unranked Mods`,
mods_removeUnranked: `Remove Unranked Mods`, mods_removeUnranked: `Remove Unranked Mods`,
mods_addMissingMaxRankMods: `Add Missing Max Rank Mods`, mods_addMissingMaxRankMods: `Add Missing Max Rank Mods`,
@ -181,9 +182,13 @@ dict = {
cheats_noDojoResearchTime: `No Dojo Research Time`, cheats_noDojoResearchTime: `No Dojo Research Time`,
cheats_fastClanAscension: `Fast Clan Ascension`, cheats_fastClanAscension: `Fast Clan Ascension`,
cheats_missionsCanGiveAllRelics: `Missions Can Give All Relics`, cheats_missionsCanGiveAllRelics: `Missions Can Give All Relics`,
cheats_exceptionalRelicsAlwaysGiveBronzeReward: `Exceptional Relics Always Give Bronze Reward`,
cheats_flawlessRelicsAlwaysGiveSilverReward: `Flawless Relics Always Give Silver Reward`,
cheats_radiantRelicsAlwaysGiveGoldReward: `Radiant Relics Always Give Gold Reward`,
cheats_unlockAllSimarisResearchEntries: `Unlock All Simaris Research Entries`, cheats_unlockAllSimarisResearchEntries: `Unlock All Simaris Research Entries`,
cheats_disableDailyTribute: `Disable Daily Tribute`, cheats_disableDailyTribute: `Disable Daily Tribute`,
cheats_spoofMasteryRank: `Spoofed Mastery Rank (-1 to disable)`, cheats_spoofMasteryRank: `Spoofed Mastery Rank (-1 to disable)`,
cheats_relicRewardItemCountMultiplier: `Relic Reward Item Count Multiplier`,
cheats_nightwaveStandingMultiplier: `Nightwave Standing Multiplier`, cheats_nightwaveStandingMultiplier: `Nightwave Standing Multiplier`,
cheats_save: `Save`, cheats_save: `Save`,
cheats_account: `Account`, cheats_account: `Account`,
@ -280,19 +285,19 @@ dict = {
upgrade_AvatarLootRadar: `+7m Loot Radar`, upgrade_AvatarLootRadar: `+7m Loot Radar`,
upgrade_WeaponAmmoMax: `+15% Ammo Max`, upgrade_WeaponAmmoMax: `+15% Ammo Max`,
upgrade_EnemyArmorReductionAura: `-3% Enemy Armor`, upgrade_EnemyArmorReductionAura: `-3% Enemy Armor`,
upgrade_OnExecutionAmmo: `100% Primary and Secondary Magazine Refill on Mercy`, upgrade_OnExecutionAmmo: `+100% Primary and Secondary Magazine Refill on Mercy`,
upgrade_OnExecutionHealthDrop: `100% chance to drop a Health Orb on Mercy`, upgrade_OnExecutionHealthDrop: `+100% Health Orb Chance on Mercy`,
upgrade_OnExecutionEnergyDrop: `50% chance to drop an Energy Orb on Mercy`, upgrade_OnExecutionEnergyDrop: `+50% Energy Orb Chance on Mercy`,
upgrade_OnFailHackReset: `+50% to retry on Hacking failure`, upgrade_OnFailHackReset: `+50% Hacking Retry Chance`,
upgrade_DamageReductionOnHack: `75% Damage Reduction while Hacking`, upgrade_DamageReductionOnHack: `+75% Damage Reduction while Hacking`,
upgrade_OnExecutionReviveCompanion: `Mercy Kills reduce Companion Recovery by 15s`, upgrade_OnExecutionReviveCompanion: `Mercy Kills reduce Companion Recovery by 15s`,
upgrade_OnExecutionParkourSpeed: `+60% Parkour Speed after a Mercy for 15s`, upgrade_OnExecutionParkourSpeed: `+60% Parkour Speed after a Mercy for 15s`,
upgrade_AvatarTimeLimitIncrease: `+8s to Hacking`, upgrade_AvatarTimeLimitIncrease: `+8s to Hacking`,
upgrade_ElectrifyOnHack: `Shock enemies within 20m while Hacking`, upgrade_ElectrifyOnHack: `Shock enemies within 20m while Hacking`,
upgrade_OnExecutionTerrify: `50% chance for enemies within 15m to cower in fear for 8 seconds on Mercy`, upgrade_OnExecutionTerrify: `+50% chance for enemies within 15m to cower in fear for 8 seconds on Mercy`,
upgrade_OnHackLockers: `Unlock 5 lockers within 20m after Hacking`, upgrade_OnHackLockers: `Unlock 5 lockers within 20m after Hacking`,
upgrade_OnExecutionBlind: `Blind enemies within 18m on Mercy`, upgrade_OnExecutionBlind: `Blind enemies within 18m on Mercy`,
upgrade_OnExecutionDrainPower: `100% chance for next ability cast to gain +50% Ability Strength on Mercy`, upgrade_OnExecutionDrainPower: `+100% chance for next ability cast to gain +50% Ability Strength on Mercy`,
upgrade_OnHackSprintSpeed: `+75% Sprint Speed for 15s after Hacking`, upgrade_OnHackSprintSpeed: `+75% Sprint Speed for 15s after Hacking`,
upgrade_SwiftExecute: `Speed of Mercy Kills increased by 50%`, upgrade_SwiftExecute: `Speed of Mercy Kills increased by 50%`,
upgrade_OnHackInvis: `Invisible for 15 seconds after hacking`, upgrade_OnHackInvis: `Invisible for 15 seconds after hacking`,

View File

@ -127,6 +127,7 @@ dict = {
mods_fingerprintHelp: `¿Necesitas ayuda con la huella digital?`, mods_fingerprintHelp: `¿Necesitas ayuda con la huella digital?`,
mods_rivens: `Agrietados`, mods_rivens: `Agrietados`,
mods_mods: `Mods`, mods_mods: `Mods`,
mods_addMax: `[UNTRANSLATED] Add Maxed`,
mods_addMissingUnrankedMods: `Agregar mods sin rango faltantes`, mods_addMissingUnrankedMods: `Agregar mods sin rango faltantes`,
mods_removeUnranked: `Quitar mods sin rango`, mods_removeUnranked: `Quitar mods sin rango`,
mods_addMissingMaxRankMods: `Agregar mods de rango máximo faltantes`, mods_addMissingMaxRankMods: `Agregar mods de rango máximo faltantes`,
@ -182,9 +183,13 @@ dict = {
cheats_noDojoResearchTime: `Sin tiempo de investigación del dojo`, cheats_noDojoResearchTime: `Sin tiempo de investigación del dojo`,
cheats_fastClanAscension: `Ascenso rápido del clan`, cheats_fastClanAscension: `Ascenso rápido del clan`,
cheats_missionsCanGiveAllRelics: `Las misiones pueden otorgar todas las reliquias`, cheats_missionsCanGiveAllRelics: `Las misiones pueden otorgar todas las reliquias`,
cheats_exceptionalRelicsAlwaysGiveBronzeReward: `[UNTRANSLATED] Exceptional Relics Always Give Bronze Reward`,
cheats_flawlessRelicsAlwaysGiveSilverReward: `[UNTRANSLATED] Flawless Relics Always Give Silver Reward`,
cheats_radiantRelicsAlwaysGiveGoldReward: `[UNTRANSLATED] Radiant Relics Always Give Gold Reward`,
cheats_unlockAllSimarisResearchEntries: `Desbloquear todas las entradas de investigación de Simaris`, cheats_unlockAllSimarisResearchEntries: `Desbloquear todas las entradas de investigación de Simaris`,
cheats_disableDailyTribute: `Desactivar tributo diario`, cheats_disableDailyTribute: `Desactivar tributo diario`,
cheats_spoofMasteryRank: `Rango de maestría simulado (-1 para desactivar)`, cheats_spoofMasteryRank: `Rango de maestría simulado (-1 para desactivar)`,
cheats_relicRewardItemCountMultiplier: `[UNTRANSLATED] Relic Reward Item Count Multiplier`,
cheats_nightwaveStandingMultiplier: `Multiplicador de Reputación de Onda Nocturna`, cheats_nightwaveStandingMultiplier: `Multiplicador de Reputación de Onda Nocturna`,
cheats_save: `Guardar`, cheats_save: `Guardar`,
cheats_account: `Cuenta`, cheats_account: `Cuenta`,

View File

@ -127,6 +127,7 @@ dict = {
mods_fingerprintHelp: `Besoin d'aide pour l'empreinte ?`, mods_fingerprintHelp: `Besoin d'aide pour l'empreinte ?`,
mods_rivens: `Rivens`, mods_rivens: `Rivens`,
mods_mods: `Mods`, mods_mods: `Mods`,
mods_addMax: `[UNTRANSLATED] Add Maxed`,
mods_addMissingUnrankedMods: `Ajouter les mods sans rang manquants`, mods_addMissingUnrankedMods: `Ajouter les mods sans rang manquants`,
mods_removeUnranked: `Retirer les mods sans rang`, mods_removeUnranked: `Retirer les mods sans rang`,
mods_addMissingMaxRankMods: `Ajouter les mods niveau max manquants`, mods_addMissingMaxRankMods: `Ajouter les mods niveau max manquants`,
@ -182,9 +183,13 @@ dict = {
cheats_noDojoResearchTime: `Aucun temps de recherche (Dojo)`, cheats_noDojoResearchTime: `Aucun temps de recherche (Dojo)`,
cheats_fastClanAscension: `Ascension de clan rapide`, cheats_fastClanAscension: `Ascension de clan rapide`,
cheats_missionsCanGiveAllRelics: `Les missions donnent toutes les reliques`, cheats_missionsCanGiveAllRelics: `Les missions donnent toutes les reliques`,
cheats_exceptionalRelicsAlwaysGiveBronzeReward: `[UNTRANSLATED] Exceptional Relics Always Give Bronze Reward`,
cheats_flawlessRelicsAlwaysGiveSilverReward: `[UNTRANSLATED] Flawless Relics Always Give Silver Reward`,
cheats_radiantRelicsAlwaysGiveGoldReward: `[UNTRANSLATED] Radiant Relics Always Give Gold Reward`,
cheats_unlockAllSimarisResearchEntries: `Débloquer toute les recherches chez Simaris`, cheats_unlockAllSimarisResearchEntries: `Débloquer toute les recherches chez Simaris`,
cheats_disableDailyTribute: `[UNTRANSLATED] Disable Daily Tribute`, cheats_disableDailyTribute: `[UNTRANSLATED] Disable Daily Tribute`,
cheats_spoofMasteryRank: `Rang de maîtrise personnalisé (-1 pour désactiver)`, cheats_spoofMasteryRank: `Rang de maîtrise personnalisé (-1 pour désactiver)`,
cheats_relicRewardItemCountMultiplier: `[UNTRANSLATED] Relic Reward Item Count Multiplier`,
cheats_nightwaveStandingMultiplier: `Multiplicateur de réputation d'Ondes Nocturnes`, cheats_nightwaveStandingMultiplier: `Multiplicateur de réputation d'Ondes Nocturnes`,
cheats_save: `Sauvegarder`, cheats_save: `Sauvegarder`,
cheats_account: `Compte`, cheats_account: `Compte`,
@ -284,7 +289,7 @@ dict = {
upgrade_OnExecutionAmmo: `100% de rechargement des armes primaires et secondaires sur une une miséricorde`, upgrade_OnExecutionAmmo: `100% de rechargement des armes primaires et secondaires sur une une miséricorde`,
upgrade_OnExecutionHealthDrop: `100% de chance de drop une orbe de santé sur une miséricorde`, upgrade_OnExecutionHealthDrop: `100% de chance de drop une orbe de santé sur une miséricorde`,
upgrade_OnExecutionEnergyDrop: `50% de chance de drop une orbe d'énergie sur une miséricorde`, upgrade_OnExecutionEnergyDrop: `50% de chance de drop une orbe d'énergie sur une miséricorde`,
upgrade_OnFailHackReset: `[UNTRANSLATED] +50% to retry on Hacking failure`, upgrade_OnFailHackReset: `[UNTRANSLATED] +50% Hacking Retry Chance`,
upgrade_DamageReductionOnHack: `75% de réduction de dégâts pendant un piratage`, upgrade_DamageReductionOnHack: `75% de réduction de dégâts pendant un piratage`,
upgrade_OnExecutionReviveCompanion: `Les miséricordes réduisent le temps de récupération du compagnon de 15s`, upgrade_OnExecutionReviveCompanion: `Les miséricordes réduisent le temps de récupération du compagnon de 15s`,
upgrade_OnExecutionParkourSpeed: `+60% de vitesse de parkour pendant 15s après une miséricorde`, upgrade_OnExecutionParkourSpeed: `+60% de vitesse de parkour pendant 15s après une miséricorde`,

View File

@ -127,6 +127,7 @@ dict = {
mods_fingerprintHelp: `Нужна помощь с отпечатком?`, mods_fingerprintHelp: `Нужна помощь с отпечатком?`,
mods_rivens: `Моды Разлома`, mods_rivens: `Моды Разлома`,
mods_mods: `Моды`, mods_mods: `Моды`,
mods_addMax: `[UNTRANSLATED] Add Maxed`,
mods_addMissingUnrankedMods: `Добавить недостающие моды без ранга`, mods_addMissingUnrankedMods: `Добавить недостающие моды без ранга`,
mods_removeUnranked: `Удалить моды без ранга`, mods_removeUnranked: `Удалить моды без ранга`,
mods_addMissingMaxRankMods: `Добавить недостающие моды максимального ранга`, mods_addMissingMaxRankMods: `Добавить недостающие моды максимального ранга`,
@ -182,9 +183,13 @@ dict = {
cheats_noDojoResearchTime: `Мгновенные Исследование Додзё`, cheats_noDojoResearchTime: `Мгновенные Исследование Додзё`,
cheats_fastClanAscension: `Мгновенное Вознесение Клана`, cheats_fastClanAscension: `Мгновенное Вознесение Клана`,
cheats_missionsCanGiveAllRelics: `[UNTRANSLATED] Missions Can Give All Relics`, cheats_missionsCanGiveAllRelics: `[UNTRANSLATED] Missions Can Give All Relics`,
cheats_exceptionalRelicsAlwaysGiveBronzeReward: `[UNTRANSLATED] Exceptional Relics Always Give Bronze Reward`,
cheats_flawlessRelicsAlwaysGiveSilverReward: `[UNTRANSLATED] Flawless Relics Always Give Silver Reward`,
cheats_radiantRelicsAlwaysGiveGoldReward: `[UNTRANSLATED] Radiant Relics Always Give Gold Reward`,
cheats_unlockAllSimarisResearchEntries: `[UNTRANSLATED] Unlock All Simaris Research Entries`, cheats_unlockAllSimarisResearchEntries: `[UNTRANSLATED] Unlock All Simaris Research Entries`,
cheats_disableDailyTribute: `[UNTRANSLATED] Disable Daily Tribute`, cheats_disableDailyTribute: `[UNTRANSLATED] Disable Daily Tribute`,
cheats_spoofMasteryRank: `Подделанный ранг мастерства (-1 для отключения)`, cheats_spoofMasteryRank: `Подделанный ранг мастерства (-1 для отключения)`,
cheats_relicRewardItemCountMultiplier: `[UNTRANSLATED] Relic Reward Item Count Multiplier`,
cheats_nightwaveStandingMultiplier: `[UNTRANSLATED] Nightwave Standing Multiplier`, cheats_nightwaveStandingMultiplier: `[UNTRANSLATED] Nightwave Standing Multiplier`,
cheats_save: `[UNTRANSLATED] Save`, cheats_save: `[UNTRANSLATED] Save`,
cheats_account: `Аккаунт`, cheats_account: `Аккаунт`,
@ -281,19 +286,19 @@ dict = {
upgrade_AvatarLootRadar: `[UNTRANSLATED] +7m Loot Radar`, upgrade_AvatarLootRadar: `[UNTRANSLATED] +7m Loot Radar`,
upgrade_WeaponAmmoMax: `[UNTRANSLATED] +15% Ammo Max`, upgrade_WeaponAmmoMax: `[UNTRANSLATED] +15% Ammo Max`,
upgrade_EnemyArmorReductionAura: `[UNTRANSLATED] -3% Enemy Armor`, upgrade_EnemyArmorReductionAura: `[UNTRANSLATED] -3% Enemy Armor`,
upgrade_OnExecutionAmmo: `[UNTRANSLATED] 100% Primary and Secondary Magazine Refill on Mercy`, upgrade_OnExecutionAmmo: `[UNTRANSLATED] +100% Primary and Secondary Magazine Refill on Mercy`,
upgrade_OnExecutionHealthDrop: `[UNTRANSLATED] 100% chance to drop a Health Orb on Mercy`, upgrade_OnExecutionHealthDrop: `[UNTRANSLATED] +100% Health Orb Chance on Mercy`,
upgrade_OnExecutionEnergyDrop: `[UNTRANSLATED] 50% chance to drop an Energy Orb on Mercy`, upgrade_OnExecutionEnergyDrop: `[UNTRANSLATED] +50% Energy Orb Chance on Mercy`,
upgrade_OnFailHackReset: `[UNTRANSLATED] +50% to retry on Hacking failure`, upgrade_OnFailHackReset: `[UNTRANSLATED] +50% Hacking Retry Chance`,
upgrade_DamageReductionOnHack: `[UNTRANSLATED] 75% Damage Reduction while Hacking`, upgrade_DamageReductionOnHack: `[UNTRANSLATED] +75% Damage Reduction while Hacking`,
upgrade_OnExecutionReviveCompanion: `[UNTRANSLATED] Mercy Kills reduce Companion Recovery by 15s`, upgrade_OnExecutionReviveCompanion: `[UNTRANSLATED] Mercy Kills reduce Companion Recovery by 15s`,
upgrade_OnExecutionParkourSpeed: `[UNTRANSLATED] +60% Parkour Speed after a Mercy for 15s`, upgrade_OnExecutionParkourSpeed: `[UNTRANSLATED] +60% Parkour Speed after a Mercy for 15s`,
upgrade_AvatarTimeLimitIncrease: `[UNTRANSLATED] +8s to Hacking`, upgrade_AvatarTimeLimitIncrease: `[UNTRANSLATED] +8s to Hacking`,
upgrade_ElectrifyOnHack: `[UNTRANSLATED] Shock enemies within 20m while Hacking`, upgrade_ElectrifyOnHack: `[UNTRANSLATED] Shock enemies within 20m while Hacking`,
upgrade_OnExecutionTerrify: `[UNTRANSLATED] 50% chance for enemies within 15m to cower in fear for 8 seconds on Mercy`, upgrade_OnExecutionTerrify: `[UNTRANSLATED] +50% chance for enemies within 15m to cower in fear for 8 seconds on Mercy`,
upgrade_OnHackLockers: `[UNTRANSLATED] Unlock 5 lockers within 20m after Hacking`, upgrade_OnHackLockers: `[UNTRANSLATED] Unlock 5 lockers within 20m after Hacking`,
upgrade_OnExecutionBlind: `[UNTRANSLATED] Blind enemies within 18m on Mercy`, upgrade_OnExecutionBlind: `[UNTRANSLATED] Blind enemies within 18m on Mercy`,
upgrade_OnExecutionDrainPower: `[UNTRANSLATED] 100% chance for next ability cast to gain +50% Ability Strength on Mercy`, upgrade_OnExecutionDrainPower: `[UNTRANSLATED] +100% chance for next ability cast to gain +50% Ability Strength on Mercy`,
upgrade_OnHackSprintSpeed: `[UNTRANSLATED] +75% Sprint Speed for 15s after Hacking`, upgrade_OnHackSprintSpeed: `[UNTRANSLATED] +75% Sprint Speed for 15s after Hacking`,
upgrade_SwiftExecute: `[UNTRANSLATED] Speed of Mercy Kills increased by 50%`, upgrade_SwiftExecute: `[UNTRANSLATED] Speed of Mercy Kills increased by 50%`,
upgrade_OnHackInvis: `[UNTRANSLATED] Invisible for 15 seconds after hacking`, upgrade_OnHackInvis: `[UNTRANSLATED] Invisible for 15 seconds after hacking`,

View File

@ -2,8 +2,8 @@
dict = { dict = {
general_inventoryUpdateNote: `注意:要在游戏中查看更改,您需要重新同步库存,例如使用引导程序的 /sync 命令、访问道场 / 中继站或重新登录`, general_inventoryUpdateNote: `注意:要在游戏中查看更改,您需要重新同步库存,例如使用引导程序的 /sync 命令、访问道场 / 中继站或重新登录`,
general_addButton: `添加`, general_addButton: `添加`,
general_setButton: `[UNTRANSLATED] Set`, general_setButton: `设置`,
general_removeButton: `[UNTRANSLATED] Remove`, general_removeButton: `移除`,
general_bulkActions: `批量操作`, general_bulkActions: `批量操作`,
code_loginFail: `登录失败。请检查邮箱和密码。`, code_loginFail: `登录失败。请检查邮箱和密码。`,
@ -120,13 +120,14 @@ dict = {
detailedView_archonShardsDescription: `您可以使用这些无限插槽应用各种强化效果`, detailedView_archonShardsDescription: `您可以使用这些无限插槽应用各种强化效果`,
detailedView_archonShardsDescription2: `请注意, 在加载时, 每个执政官源力石都需要一定的时间来生效。`, detailedView_archonShardsDescription2: `请注意, 在加载时, 每个执政官源力石都需要一定的时间来生效。`,
detailedView_valenceBonusLabel: `效价加成`, detailedView_valenceBonusLabel: `效价加成`,
detailedView_valenceBonusDescription: `[UNTRANSLATED] You can set or remove the Valence Bonus from your weapon.`, detailedView_valenceBonusDescription: `您可以设置或移除武器上的效价加成。`,
mods_addRiven: `添加裂罅MOD`, mods_addRiven: `添加裂罅MOD`,
mods_fingerprint: `印记`, mods_fingerprint: `印记`,
mods_fingerprintHelp: `需要印记相关的帮助?`, mods_fingerprintHelp: `需要印记相关的帮助?`,
mods_rivens: `裂罅MOD`, mods_rivens: `裂罅MOD`,
mods_mods: `Mods`, mods_mods: `Mods`,
mods_addMax: `设为满级`,
mods_addMissingUnrankedMods: `添加所有缺失的Mods`, mods_addMissingUnrankedMods: `添加所有缺失的Mods`,
mods_removeUnranked: `删除所有未升级的Mods`, mods_removeUnranked: `删除所有未升级的Mods`,
mods_addMissingMaxRankMods: `添加所有缺失的满级Mods`, mods_addMissingMaxRankMods: `添加所有缺失的满级Mods`,
@ -136,17 +137,17 @@ dict = {
cheats_skipAllDialogue: `跳过所有对话`, cheats_skipAllDialogue: `跳过所有对话`,
cheats_unlockAllScans: `解锁所有扫描`, cheats_unlockAllScans: `解锁所有扫描`,
cheats_unlockAllMissions: `解锁所有任务`, cheats_unlockAllMissions: `解锁所有任务`,
cheats_unlockAllMissions_ok: `[UNTRANSLATED] Success. Please note that you'll need to enter a dojo/relay or relog for the client to refresh the star chart.`, cheats_unlockAllMissions_ok: `操作成功。请注意,您需要进入道场 / 中继站或重新登录客户端以刷新星图数据。`,
cheats_infiniteCredits: `无限现金`, cheats_infiniteCredits: `无限现金`,
cheats_infinitePlatinum: `无限白金`, cheats_infinitePlatinum: `无限白金`,
cheats_infiniteEndo: `无限内融核心`, cheats_infiniteEndo: `无限内融核心`,
cheats_infiniteRegalAya: `无限御品阿耶`, cheats_infiniteRegalAya: `无限御品阿耶`,
cheats_infiniteHelminthMaterials: `无限Helminth材料`, cheats_infiniteHelminthMaterials: `无限Helminth材料`,
cheats_claimingBlueprintRefundsIngredients: `取消蓝图制造时返还材料`, cheats_claimingBlueprintRefundsIngredients: `取消蓝图制造时返还材料`,
cheats_dontSubtractPurchaseCreditCost: `不减少现金花费`, cheats_dontSubtractPurchaseCreditCost: `购物时不减少现金花费`,
cheats_dontSubtractPurchasePlatinumCost: `不减少白金花费`, cheats_dontSubtractPurchasePlatinumCost: `购物时不减少白金花费`,
cheats_dontSubtractPurchaseItemCost: `不减少物品花费`, cheats_dontSubtractPurchaseItemCost: `购物时不减少物品花费`,
cheats_dontSubtractPurchaseStandingCost: `不减少声望花费`, cheats_dontSubtractPurchaseStandingCost: `购物时不减少声望花费`,
cheats_dontSubtractVoidTraces: `虚空光体无消耗`, cheats_dontSubtractVoidTraces: `虚空光体无消耗`,
cheats_dontSubtractConsumables: `消耗物品使用时无损耗`, cheats_dontSubtractConsumables: `消耗物品使用时无损耗`,
cheats_unlockAllShipFeatures: `解锁所有飞船功能`, cheats_unlockAllShipFeatures: `解锁所有飞船功能`,
@ -182,9 +183,13 @@ dict = {
cheats_noDojoResearchTime: `无视道场研究时间`, cheats_noDojoResearchTime: `无视道场研究时间`,
cheats_fastClanAscension: `快速升级氏族`, cheats_fastClanAscension: `快速升级氏族`,
cheats_missionsCanGiveAllRelics: `任务可获取所有遗物`, cheats_missionsCanGiveAllRelics: `任务可获取所有遗物`,
cheats_exceptionalRelicsAlwaysGiveBronzeReward: `卓越遗物必定掉落青铜奖励`,
cheats_flawlessRelicsAlwaysGiveSilverReward: `无瑕遗物必定掉落白银奖励`,
cheats_radiantRelicsAlwaysGiveGoldReward: `光辉遗物必定掉落黄金奖励`,
cheats_unlockAllSimarisResearchEntries: `解锁所有Simaris研究条目`, cheats_unlockAllSimarisResearchEntries: `解锁所有Simaris研究条目`,
cheats_disableDailyTribute: `禁用每日登录奖励`, cheats_disableDailyTribute: `禁用每日登录奖励`,
cheats_spoofMasteryRank: `伪造精通段位(-1为禁用)`, cheats_spoofMasteryRank: `伪造精通段位(-1为禁用)`,
cheats_relicRewardItemCountMultiplier: `虚空遗物奖励物品数量倍率`,
cheats_nightwaveStandingMultiplier: `午夜电波声望倍率`, cheats_nightwaveStandingMultiplier: `午夜电波声望倍率`,
cheats_save: `保存`, cheats_save: `保存`,
cheats_account: `账户`, cheats_account: `账户`,
@ -306,8 +311,8 @@ dict = {
damageType_Poison: `毒素`, damageType_Poison: `毒素`,
damageType_Radiation: `辐射`, damageType_Radiation: `辐射`,
theme_dark: `[UNTRANSLATED] Dark Theme`, theme_dark: `暗色主题`,
theme_light: `[UNTRANSLATED] Light Theme`, theme_light: `亮色主题`,
prettier_sucks_ass: `` prettier_sucks_ass: ``
}; };