forked from OpenWF/SpaceNinjaServer
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			main
			...
			sell-impri
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 91c421b884 | 
@ -60,7 +60,6 @@
 | 
				
			|||||||
  "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
									
									
									
								
							
							
						
						
									
										8
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -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.76",
 | 
					        "warframe-public-export-plus": "^0.5.74",
 | 
				
			||||||
        "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.76",
 | 
					      "version": "0.5.74",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.76.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.74.tgz",
 | 
				
			||||||
      "integrity": "sha512-0gX3NTWaxFyzUmqBSUHhPY8pMRX92iXQFqoBuMQlMG1+6uC6JMKtwP5t8cuXR3pvV2vkaCi/cDWjP1JUChkZ9g=="
 | 
					      "integrity": "sha512-pA7dxA0lKn9w/2Sc97oxnn+CEzL1SrT9XriNLTDF4Xp+2SBEpGcfbqbdR9ljPQJopIbrc9Zy02R+uBQVomcwyA=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/warframe-riven-info": {
 | 
					    "node_modules/warframe-riven-info": {
 | 
				
			||||||
      "version": "0.1.2",
 | 
					      "version": "0.1.2",
 | 
				
			||||||
 | 
				
			|||||||
@ -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.76",
 | 
					    "warframe-public-export-plus": "^0.5.74",
 | 
				
			||||||
    "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",
 | 
				
			||||||
 | 
				
			|||||||
@ -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) && !targetStrings[key].startsWith("[UNTRANSLATED] ")) {
 | 
					                    if (targetStrings.hasOwnProperty(key)) {
 | 
				
			||||||
                        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`);
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,6 @@ import {
 | 
				
			|||||||
    getGuildVault,
 | 
					    getGuildVault,
 | 
				
			||||||
    hasAccessToDojo,
 | 
					    hasAccessToDojo,
 | 
				
			||||||
    hasGuildPermission,
 | 
					    hasGuildPermission,
 | 
				
			||||||
    processCompletedGuildTechProject,
 | 
					 | 
				
			||||||
    processFundedGuildTechProject,
 | 
					    processFundedGuildTechProject,
 | 
				
			||||||
    processGuildTechProjectContributionsUpdate,
 | 
					    processGuildTechProjectContributionsUpdate,
 | 
				
			||||||
    removePigmentsFromGuildMembers,
 | 
					    removePigmentsFromGuildMembers,
 | 
				
			||||||
@ -52,12 +51,8 @@ export const guildTechController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
                };
 | 
					                };
 | 
				
			||||||
                if (project.CompletionDate) {
 | 
					                if (project.CompletionDate) {
 | 
				
			||||||
                    techProject.CompletionDate = toMongoDate(project.CompletionDate);
 | 
					                    techProject.CompletionDate = toMongoDate(project.CompletionDate);
 | 
				
			||||||
                    if (
 | 
					                    if (Date.now() >= project.CompletionDate.getTime()) {
 | 
				
			||||||
                        Date.now() >= project.CompletionDate.getTime() &&
 | 
					                        needSave ||= setGuildTechLogState(guild, project.ItemType, 4, project.CompletionDate);
 | 
				
			||||||
                        setGuildTechLogState(guild, project.ItemType, 4, project.CompletionDate)
 | 
					 | 
				
			||||||
                    ) {
 | 
					 | 
				
			||||||
                        processCompletedGuildTechProject(guild, project.ItemType);
 | 
					 | 
				
			||||||
                        needSave = true;
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                techProjects.push(techProject);
 | 
					                techProjects.push(techProject);
 | 
				
			||||||
 | 
				
			|||||||
@ -9,13 +9,11 @@ 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,
 | 
				
			||||||
    createLibraryDailyTask,
 | 
					    createLibraryDailyTask,
 | 
				
			||||||
    generateRewardSeed,
 | 
					    generateRewardSeed
 | 
				
			||||||
    getCalendarProgress
 | 
					 | 
				
			||||||
} from "@/src/services/inventoryService";
 | 
					} from "@/src/services/inventoryService";
 | 
				
			||||||
import { logger } from "@/src/utils/logger";
 | 
					import { logger } from "@/src/utils/logger";
 | 
				
			||||||
import { addString, catBreadHash } from "@/src/helpers/stringHelpers";
 | 
					import { addString, catBreadHash } from "@/src/helpers/stringHelpers";
 | 
				
			||||||
@ -110,61 +108,6 @@ export const inventoryController: RequestHandler = async (request, response) =>
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inventory.NextRefill = new Date((today + 1) * 86400000); // tomorrow at 0 UTC
 | 
					        inventory.NextRefill = new Date((today + 1) * 86400000); // tomorrow at 0 UTC
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,6 @@ import {
 | 
				
			|||||||
} from "@/src/services/loginRewardService";
 | 
					} from "@/src/services/loginRewardService";
 | 
				
			||||||
import { getInventory } from "@/src/services/inventoryService";
 | 
					import { getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
import { config } from "@/src/services/configService";
 | 
					import { config } from "@/src/services/configService";
 | 
				
			||||||
import { sendWsBroadcastTo } from "@/src/services/webService";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const loginRewardsController: RequestHandler = async (req, res) => {
 | 
					export const loginRewardsController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const account = await getAccountForRequest(req);
 | 
					    const account = await getAccountForRequest(req);
 | 
				
			||||||
@ -48,10 +47,10 @@ export const loginRewardsController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
        response.DailyTributeInfo.HasChosenReward = true;
 | 
					        response.DailyTributeInfo.HasChosenReward = true;
 | 
				
			||||||
        response.DailyTributeInfo.ChosenReward = randomRewards[0];
 | 
					        response.DailyTributeInfo.ChosenReward = randomRewards[0];
 | 
				
			||||||
        response.DailyTributeInfo.NewInventory = await claimLoginReward(inventory, randomRewards[0]);
 | 
					        response.DailyTributeInfo.NewInventory = await claimLoginReward(inventory, randomRewards[0]);
 | 
				
			||||||
        setAccountGotLoginRewardToday(account);
 | 
					        await inventory.save();
 | 
				
			||||||
        await Promise.all([inventory.save(), account.save()]);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sendWsBroadcastTo(account._id.toString(), { update_inventory: true });
 | 
					        setAccountGotLoginRewardToday(account);
 | 
				
			||||||
 | 
					        await account.save();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    res.json(response);
 | 
					    res.json(response);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,6 @@ import {
 | 
				
			|||||||
} from "@/src/services/loginRewardService";
 | 
					} from "@/src/services/loginRewardService";
 | 
				
			||||||
import { getAccountForRequest } from "@/src/services/loginService";
 | 
					import { getAccountForRequest } from "@/src/services/loginService";
 | 
				
			||||||
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
 | 
					import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
 | 
				
			||||||
import { sendWsBroadcastTo } from "@/src/services/webService";
 | 
					 | 
				
			||||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
					import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
				
			||||||
import { logger } from "@/src/utils/logger";
 | 
					import { logger } from "@/src/utils/logger";
 | 
				
			||||||
import { RequestHandler } from "express";
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
@ -35,10 +34,11 @@ export const loginRewardsSelectionController: RequestHandler = async (req, res)
 | 
				
			|||||||
        chosenReward = randomRewards.find(x => x.StoreItemType == body.ChosenReward)!;
 | 
					        chosenReward = randomRewards.find(x => x.StoreItemType == body.ChosenReward)!;
 | 
				
			||||||
        inventoryChanges = await claimLoginReward(inventory, chosenReward);
 | 
					        inventoryChanges = await claimLoginReward(inventory, chosenReward);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    setAccountGotLoginRewardToday(account);
 | 
					    await inventory.save();
 | 
				
			||||||
    await Promise.all([inventory.save(), account.save()]);
 | 
					
 | 
				
			||||||
 | 
					    setAccountGotLoginRewardToday(account);
 | 
				
			||||||
 | 
					    await account.save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sendWsBroadcastTo(account._id.toString(), { update_inventory: true });
 | 
					 | 
				
			||||||
    res.json({
 | 
					    res.json({
 | 
				
			||||||
        DailyTributeInfo: {
 | 
					        DailyTributeInfo: {
 | 
				
			||||||
            NewInventory: inventoryChanges,
 | 
					            NewInventory: inventoryChanges,
 | 
				
			||||||
 | 
				
			|||||||
@ -57,12 +57,8 @@ export const placeDecoInComponentController: RequestHandler = async (req, res) =
 | 
				
			|||||||
                component.DecoCapacity -= meta.capacityCost;
 | 
					                component.DecoCapacity -= meta.capacityCost;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            const entry = Object.entries(ExportResources).find(arr => arr[1].deco == deco.Type);
 | 
					            const [itemType, meta] = Object.entries(ExportResources).find(arr => arr[1].deco == deco.Type)!;
 | 
				
			||||||
            if (!entry) {
 | 
					            if (!itemType || meta.dojoCapacityCost === undefined) {
 | 
				
			||||||
                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;
 | 
				
			||||||
@ -79,13 +75,7 @@ export const placeDecoInComponentController: RequestHandler = async (req, res) =
 | 
				
			|||||||
                if (meta) {
 | 
					                if (meta) {
 | 
				
			||||||
                    processDojoBuildMaterialsGathered(guild, meta);
 | 
					                    processDojoBuildMaterialsGathered(guild, meta);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } else if (
 | 
					            } else if (guild.AutoContributeFromVault && guild.VaultRegularCredits && guild.VaultMiscItems) {
 | 
				
			||||||
                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) {
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,6 @@ 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);
 | 
				
			||||||
@ -121,7 +120,6 @@ 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": {
 | 
				
			||||||
 | 
				
			|||||||
@ -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, request.Fingerprint, true);
 | 
					        await addItem(inventory, request.ItemType, request.ItemCount, true, undefined, undefined, true);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    await inventory.save();
 | 
					    await inventory.save();
 | 
				
			||||||
    res.end();
 | 
					    res.end();
 | 
				
			||||||
@ -16,5 +16,4 @@ export const addItemsController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
interface IAddItemRequest {
 | 
					interface IAddItemRequest {
 | 
				
			||||||
    ItemType: string;
 | 
					    ItemType: string;
 | 
				
			||||||
    ItemCount: number;
 | 
					    ItemCount: number;
 | 
				
			||||||
    Fingerprint?: string;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,6 @@ 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,
 | 
				
			||||||
@ -14,14 +13,7 @@ export const crackRelic = async (
 | 
				
			|||||||
    inventoryChanges: IInventoryChanges = {}
 | 
					    inventoryChanges: IInventoryChanges = {}
 | 
				
			||||||
): Promise<IRngResult> => {
 | 
					): Promise<IRngResult> => {
 | 
				
			||||||
    const relic = ExportRelics[participant.VoidProjection];
 | 
					    const relic = ExportRelics[participant.VoidProjection];
 | 
				
			||||||
    let weights = refinementToWeights[relic.quality];
 | 
					    const 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
 | 
				
			||||||
@ -43,13 +35,7 @@ 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;
 | 
				
			||||||
 | 
				
			|||||||
@ -23,9 +23,7 @@ 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;
 | 
				
			||||||
@ -104,9 +102,7 @@ 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,
 | 
				
			||||||
 | 
				
			|||||||
@ -64,13 +64,9 @@ 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;
 | 
				
			||||||
 | 
				
			|||||||
@ -550,19 +550,6 @@ 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 = (
 | 
				
			||||||
 | 
				
			|||||||
@ -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, IMessageCreationTemplate } from "./inboxService";
 | 
					import { createMessage } 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,16 +483,6 @@ 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,
 | 
				
			||||||
@ -1573,22 +1563,7 @@ 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) {
 | 
				
			||||||
        const msg: IMessageCreationTemplate = convertInboxMessage(meta.message);
 | 
					        await createMessage(inventory.accountOwnerId, [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;
 | 
				
			||||||
 | 
				
			|||||||
@ -251,9 +251,7 @@ 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 ?? "",
 | 
				
			||||||
 | 
				
			|||||||
@ -167,13 +167,8 @@ 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)) {
 | 
					                if (equipmentKeys.includes(equipmentName as TEquipmentKey) && equipmentName != "ValidNewLoadoutId") {
 | 
				
			||||||
                    logger.debug(`general Item config saved of type ${equipmentName}`, {
 | 
					                    logger.debug(`general Item config saved of type ${equipmentName}`, {
 | 
				
			||||||
                        config: equipment
 | 
					                        config: equipment
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
@ -221,7 +216,7 @@ export const handleInventoryItemConfigChange = async (
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    logger.error(`loadout category not implemented, changes will be lost: ${equipmentName}`, {
 | 
					                    logger.warn(`loadout category not implemented, changes may be lost: ${equipmentName}`, {
 | 
				
			||||||
                        config: equipment
 | 
					                        config: equipment
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
				
			|||||||
@ -64,12 +64,8 @@ export const handleSetShipDecorations = async (
 | 
				
			|||||||
        throw new Error(`unknown room: ${placedDecoration.Room}`);
 | 
					        throw new Error(`unknown room: ${placedDecoration.Room}`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const entry = Object.entries(ExportResources).find(arr => arr[1].deco == placedDecoration.Type);
 | 
					    const [itemType, meta] = Object.entries(ExportResources).find(arr => arr[1].deco == placedDecoration.Type)!;
 | 
				
			||||||
    if (!entry) {
 | 
					    if (!itemType || meta.capacityCost === undefined) {
 | 
				
			||||||
        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}`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -92,13 +92,5 @@
 | 
				
			|||||||
  "/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"
 | 
					 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
				
			|||||||
@ -527,7 +527,6 @@
 | 
				
			|||||||
                                <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">
 | 
				
			||||||
@ -547,7 +546,6 @@
 | 
				
			|||||||
                </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">
 | 
				
			||||||
@ -779,18 +777,6 @@
 | 
				
			|||||||
                                        <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>
 | 
				
			||||||
@ -802,21 +788,14 @@
 | 
				
			|||||||
                                    <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" data-default="-1" />
 | 
					                                            <input class="form-control" id="spoofMasteryRank" type="number" min="-1" max="65535" />
 | 
				
			||||||
                                            <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" data-default="1" />
 | 
					                                            <input class="form-control" id="nightwaveStandingMultiplier" type="number" min="1" max="1000000" value="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>
 | 
				
			||||||
@ -865,7 +844,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="worldState.galleonOfGhouls" data-loc="worldState_galleonOfGhouls"></label>
 | 
					                                    <label class="form-label" for="changeSyndicate" 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>
 | 
				
			||||||
@ -874,7 +853,7 @@
 | 
				
			|||||||
                                    </select>
 | 
					                                    </select>
 | 
				
			||||||
                                </div>
 | 
					                                </div>
 | 
				
			||||||
                                <div class="form-group mt-2">
 | 
					                                <div class="form-group mt-2">
 | 
				
			||||||
                                    <label class="form-label" for="worldState.eidolonOverride" data-loc="worldState_eidolonOverride"></label>
 | 
					                                    <label class="form-label" for="changeSyndicate" 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>
 | 
				
			||||||
@ -882,7 +861,7 @@
 | 
				
			|||||||
                                    </select>
 | 
					                                    </select>
 | 
				
			||||||
                                </div>
 | 
					                                </div>
 | 
				
			||||||
                                <div class="form-group mt-2">
 | 
					                                <div class="form-group mt-2">
 | 
				
			||||||
                                    <label class="form-label" for="worldState.vallisOverride" data-loc="worldState_vallisOverride"></label>
 | 
					                                    <label class="form-label" for="changeSyndicate" 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>
 | 
				
			||||||
@ -890,7 +869,7 @@
 | 
				
			|||||||
                                    </select>
 | 
					                                    </select>
 | 
				
			||||||
                                </div>
 | 
					                                </div>
 | 
				
			||||||
                                <div class="form-group mt-2">
 | 
					                                <div class="form-group mt-2">
 | 
				
			||||||
                                    <label class="form-label" for="worldState.duviriOverride" data-loc="worldState_duviriOverride"></label>
 | 
					                                    <label class="form-label" for="changeSyndicate" 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>
 | 
				
			||||||
@ -901,7 +880,7 @@
 | 
				
			|||||||
                                    </select>
 | 
					                                    </select>
 | 
				
			||||||
                                </div>
 | 
					                                </div>
 | 
				
			||||||
                                <div class="form-group mt-2">
 | 
					                                <div class="form-group mt-2">
 | 
				
			||||||
                                    <label class="form-label" for="worldState.nightwaveOverride" data-loc="worldState_nightwaveOverride"></label>
 | 
					                                    <label class="form-label" for="changeSyndicate" 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>
 | 
				
			||||||
@ -923,7 +902,7 @@
 | 
				
			|||||||
                                    </select>
 | 
					                                    </select>
 | 
				
			||||||
                                </div>
 | 
					                                </div>
 | 
				
			||||||
                                <div class="form-group mt-2">
 | 
					                                <div class="form-group mt-2">
 | 
				
			||||||
                                    <label class="form-label" for="worldState.allTheFissures" data-loc="worldState_fissures"></label>
 | 
					                                    <label class="form-label" for="changeSyndicate" 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>
 | 
				
			||||||
@ -938,9 +917,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.darvoStockMultiplier" data-loc="worldState_darvoStockMultiplier"></label>
 | 
					                                    <label class="form-label" for="worldState.circuitGameModes" 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" data-default="1" />
 | 
					                                        <input id="worldState.darvoStockMultiplier" class="form-control" type="number" step="0.01" placeholder="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>
 | 
				
			||||||
 | 
				
			|||||||
@ -651,7 +651,6 @@ 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" &&
 | 
				
			||||||
@ -664,6 +663,7 @@ 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,6 +677,13 @@ 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 = "#";
 | 
				
			||||||
@ -714,14 +721,6 @@ 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 = "#";
 | 
				
			||||||
@ -1873,8 +1872,6 @@ 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();
 | 
				
			||||||
@ -1882,15 +1879,14 @@ function doAcquireMod() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    const count = parseInt($("#mod-count").val());
 | 
					    const count = parseInt($("#mod-count").val());
 | 
				
			||||||
    if (count != 0) {
 | 
					    if (count != 0) {
 | 
				
			||||||
        Promise.all([window.itemListPromise, revalidateAuthz()]).then(([itemList]) => {
 | 
					        revalidateAuthz().then(() => {
 | 
				
			||||||
            $.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 () {
 | 
				
			||||||
@ -1905,11 +1901,6 @@ 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) {
 | 
				
			||||||
@ -1993,14 +1984,16 @@ 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;
 | 
				
			||||||
                        const elm = document.getElementById(key);
 | 
					                        var x = document.getElementById(`${key}`);
 | 
				
			||||||
                        if (elm.type == "checkbox") {
 | 
					                        if (x != null) {
 | 
				
			||||||
                            elm.checked = value;
 | 
					                            if (x.type == "checkbox") {
 | 
				
			||||||
                        } else if (elm.classList.contains("tags-input")) {
 | 
					                                x.checked = value;
 | 
				
			||||||
                            elm.value = value.join(", ");
 | 
					                            } else if (x.classList.contains("tags-input")) {
 | 
				
			||||||
                            elm.oninput();
 | 
					                                x.value = value.join(", ");
 | 
				
			||||||
                        } else {
 | 
					                                x.oninput();
 | 
				
			||||||
                            elm.value = value ?? elm.getAttribute("data-default");
 | 
					                            } else {
 | 
				
			||||||
 | 
					                                x.value = value;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
 | 
				
			|||||||
@ -127,7 +127,6 @@ 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`,
 | 
				
			||||||
@ -183,13 +182,9 @@ 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`,
 | 
				
			||||||
@ -286,19 +281,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% Health Orb Chance on Mercy`,
 | 
					    upgrade_OnExecutionHealthDrop: `[UNTRANSLATED] 100% chance to drop a Health Orb on Mercy`,
 | 
				
			||||||
    upgrade_OnExecutionEnergyDrop: `[UNTRANSLATED] +50% Energy Orb Chance on Mercy`,
 | 
					    upgrade_OnExecutionEnergyDrop: `[UNTRANSLATED] 50% chance to drop an Energy Orb on Mercy`,
 | 
				
			||||||
    upgrade_OnFailHackReset: `[UNTRANSLATED] +50% Hacking Retry Chance`,
 | 
					    upgrade_OnFailHackReset: `[UNTRANSLATED] +50% to retry on Hacking failure`,
 | 
				
			||||||
    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`,
 | 
				
			||||||
 | 
				
			|||||||
@ -126,7 +126,6 @@ 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`,
 | 
				
			||||||
@ -182,13 +181,9 @@ 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`,
 | 
				
			||||||
@ -285,19 +280,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% Health Orb Chance on Mercy`,
 | 
					    upgrade_OnExecutionHealthDrop: `100% chance to drop a Health Orb on Mercy`,
 | 
				
			||||||
    upgrade_OnExecutionEnergyDrop: `+50% Energy Orb Chance on Mercy`,
 | 
					    upgrade_OnExecutionEnergyDrop: `50% chance to drop an Energy Orb on Mercy`,
 | 
				
			||||||
    upgrade_OnFailHackReset: `+50% Hacking Retry Chance`,
 | 
					    upgrade_OnFailHackReset: `+50% to retry on Hacking failure`,
 | 
				
			||||||
    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`,
 | 
				
			||||||
 | 
				
			|||||||
@ -127,7 +127,6 @@ 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`,
 | 
				
			||||||
@ -183,13 +182,9 @@ 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`,
 | 
				
			||||||
 | 
				
			|||||||
@ -127,7 +127,6 @@ 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`,
 | 
				
			||||||
@ -183,13 +182,9 @@ 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`,
 | 
				
			||||||
@ -289,7 +284,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% Hacking Retry Chance`,
 | 
					    upgrade_OnFailHackReset: `[UNTRANSLATED] +50% to retry on Hacking failure`,
 | 
				
			||||||
    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`,
 | 
				
			||||||
 | 
				
			|||||||
@ -127,7 +127,6 @@ 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: `Добавить недостающие моды максимального ранга`,
 | 
				
			||||||
@ -183,13 +182,9 @@ 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: `Аккаунт`,
 | 
				
			||||||
@ -286,19 +281,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% Health Orb Chance on Mercy`,
 | 
					    upgrade_OnExecutionHealthDrop: `[UNTRANSLATED] 100% chance to drop a Health Orb on Mercy`,
 | 
				
			||||||
    upgrade_OnExecutionEnergyDrop: `[UNTRANSLATED] +50% Energy Orb Chance on Mercy`,
 | 
					    upgrade_OnExecutionEnergyDrop: `[UNTRANSLATED] 50% chance to drop an Energy Orb on Mercy`,
 | 
				
			||||||
    upgrade_OnFailHackReset: `[UNTRANSLATED] +50% Hacking Retry Chance`,
 | 
					    upgrade_OnFailHackReset: `[UNTRANSLATED] +50% to retry on Hacking failure`,
 | 
				
			||||||
    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`,
 | 
				
			||||||
 | 
				
			|||||||
@ -2,8 +2,8 @@
 | 
				
			|||||||
dict = {
 | 
					dict = {
 | 
				
			||||||
    general_inventoryUpdateNote: `注意:要在游戏中查看更改,您需要重新同步库存,例如使用引导程序的 /sync 命令、访问道场 / 中继站或重新登录`,
 | 
					    general_inventoryUpdateNote: `注意:要在游戏中查看更改,您需要重新同步库存,例如使用引导程序的 /sync 命令、访问道场 / 中继站或重新登录`,
 | 
				
			||||||
    general_addButton: `添加`,
 | 
					    general_addButton: `添加`,
 | 
				
			||||||
    general_setButton: `设置`,
 | 
					    general_setButton: `[UNTRANSLATED] Set`,
 | 
				
			||||||
    general_removeButton: `移除`,
 | 
					    general_removeButton: `[UNTRANSLATED] Remove`,
 | 
				
			||||||
    general_bulkActions: `批量操作`,
 | 
					    general_bulkActions: `批量操作`,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    code_loginFail: `登录失败。请检查邮箱和密码。`,
 | 
					    code_loginFail: `登录失败。请检查邮箱和密码。`,
 | 
				
			||||||
@ -120,14 +120,13 @@ dict = {
 | 
				
			|||||||
    detailedView_archonShardsDescription: `您可以使用这些无限插槽应用各种强化效果`,
 | 
					    detailedView_archonShardsDescription: `您可以使用这些无限插槽应用各种强化效果`,
 | 
				
			||||||
    detailedView_archonShardsDescription2: `请注意, 在加载时, 每个执政官源力石都需要一定的时间来生效。`,
 | 
					    detailedView_archonShardsDescription2: `请注意, 在加载时, 每个执政官源力石都需要一定的时间来生效。`,
 | 
				
			||||||
    detailedView_valenceBonusLabel: `效价加成`,
 | 
					    detailedView_valenceBonusLabel: `效价加成`,
 | 
				
			||||||
    detailedView_valenceBonusDescription: `您可以设置或移除武器上的效价加成。`,
 | 
					    detailedView_valenceBonusDescription: `[UNTRANSLATED] You can set or remove the Valence Bonus from your weapon.`,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    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`,
 | 
				
			||||||
@ -137,17 +136,17 @@ dict = {
 | 
				
			|||||||
    cheats_skipAllDialogue: `跳过所有对话`,
 | 
					    cheats_skipAllDialogue: `跳过所有对话`,
 | 
				
			||||||
    cheats_unlockAllScans: `解锁所有扫描`,
 | 
					    cheats_unlockAllScans: `解锁所有扫描`,
 | 
				
			||||||
    cheats_unlockAllMissions: `解锁所有任务`,
 | 
					    cheats_unlockAllMissions: `解锁所有任务`,
 | 
				
			||||||
    cheats_unlockAllMissions_ok: `操作成功。请注意,您需要进入道场 / 中继站或重新登录客户端以刷新星图数据。`,
 | 
					    cheats_unlockAllMissions_ok: `[UNTRANSLATED] Success. Please note that you'll need to enter a dojo/relay or relog for the client to refresh the star chart.`,
 | 
				
			||||||
    cheats_infiniteCredits: `无限现金`,
 | 
					    cheats_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: `解锁所有飞船功能`,
 | 
				
			||||||
@ -183,13 +182,9 @@ 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: `账户`,
 | 
				
			||||||
@ -311,8 +306,8 @@ dict = {
 | 
				
			|||||||
    damageType_Poison: `毒素`,
 | 
					    damageType_Poison: `毒素`,
 | 
				
			||||||
    damageType_Radiation: `辐射`,
 | 
					    damageType_Radiation: `辐射`,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    theme_dark: `暗色主题`,
 | 
					    theme_dark: `[UNTRANSLATED] Dark Theme`,
 | 
				
			||||||
    theme_light: `亮色主题`,
 | 
					    theme_light: `[UNTRANSLATED] Light Theme`,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    prettier_sucks_ass: ``
 | 
					    prettier_sucks_ass: ``
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user