chore(webui): update Chinese translation #2476
8
package-lock.json
generated
8
package-lock.json
generated
@ -23,7 +23,7 @@
|
||||
"ncp": "^2.0.0",
|
||||
"typescript": "^5.5",
|
||||
"undici": "^7.10.0",
|
||||
"warframe-public-export-plus": "^0.5.77",
|
||||
"warframe-public-export-plus": "^0.5.78",
|
||||
"warframe-riven-info": "^0.1.2",
|
||||
"winston": "^3.17.0",
|
||||
"winston-daily-rotate-file": "^5.0.0",
|
||||
@ -5479,9 +5479,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/warframe-public-export-plus": {
|
||||
"version": "0.5.77",
|
||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.77.tgz",
|
||||
"integrity": "sha512-Th/b82pYB4i95afC/s8MDDXsVMl3vyy1qDwLO/AzV6peVBTs2kCSO68nNh7yXDiviGlNl0HRq+LR25jMjtFwSg=="
|
||||
"version": "0.5.78",
|
||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.78.tgz",
|
||||
"integrity": "sha512-Zvg7N+EdXS8cOAZIxqCbqiqyvQZBgh2xTxEwpHnoyJjNBpm3sP/7dtXmzHaxAZjyaCL4pvi9e7kTvxmpH8Pcag=="
|
||||
},
|
||||
"node_modules/warframe-riven-info": {
|
||||
"version": "0.1.2",
|
||||
|
@ -39,7 +39,7 @@
|
||||
"ncp": "^2.0.0",
|
||||
"typescript": "^5.5",
|
||||
"undici": "^7.10.0",
|
||||
"warframe-public-export-plus": "^0.5.77",
|
||||
"warframe-public-export-plus": "^0.5.78",
|
||||
"warframe-riven-info": "^0.1.2",
|
||||
"winston": "^3.17.0",
|
||||
"winston-daily-rotate-file": "^5.0.0",
|
||||
|
@ -6,10 +6,18 @@ import allDialogue from "@/static/fixed_responses/allDialogue.json";
|
||||
import { ILoadoutDatabase } from "@/src/types/saveLoadoutTypes";
|
||||
import { IInventoryClient, IShipInventory, equipmentKeys } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { IPolarity, ArtifactPolarity } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||
import { ExportCustoms, ExportFlavour, ExportResources, ExportVirtuals } from "warframe-public-export-plus";
|
||||
import {
|
||||
eFaction,
|
||||
ExportCustoms,
|
||||
ExportFlavour,
|
||||
ExportResources,
|
||||
ExportVirtuals,
|
||||
ICountedItem
|
||||
} from "warframe-public-export-plus";
|
||||
import { applyCheatsToInfestedFoundry, handleSubsumeCompletion } from "@/src/services/infestedFoundryService";
|
||||
import {
|
||||
addEmailItem,
|
||||
addItem,
|
||||
addMiscItems,
|
||||
allDailyAffiliationKeys,
|
||||
checkCalendarAutoAdvance,
|
||||
@ -30,7 +38,8 @@ import { unixTimesInMs } from "@/src/constants/timeConstants";
|
||||
import { DailyDeal } from "@/src/models/worldStateModel";
|
||||
import { EquipmentFeatures } from "@/src/types/equipmentTypes";
|
||||
import { generateRewardSeed } from "@/src/services/rngService";
|
||||
import { getWorldState } from "@/src/services/worldStateService";
|
||||
import { getInvasionByOid, getWorldState } from "@/src/services/worldStateService";
|
||||
import { createMessage } from "@/src/services/inboxService";
|
||||
|
||||
export const inventoryController: RequestHandler = async (request, response) => {
|
||||
const account = await getAccountForRequest(request);
|
||||
@ -186,6 +195,63 @@ export const inventoryController: RequestHandler = async (request, response) =>
|
||||
//await inventory.save();
|
||||
}
|
||||
|
||||
for (let i = 0; i != inventory.QualifyingInvasions.length; ) {
|
||||
const qi = inventory.QualifyingInvasions[i];
|
||||
const invasion = getInvasionByOid(qi.invasionId.toString());
|
||||
if (!invasion) {
|
||||
logger.debug(`removing QualifyingInvasions entry for unknown invasion: ${qi.invasionId.toString()}`);
|
||||
inventory.QualifyingInvasions.splice(i, 1);
|
||||
continue;
|
||||
}
|
||||
if (invasion.Completed) {
|
||||
let factionSidedWith: string | undefined;
|
||||
let battlePay: ICountedItem[] | undefined;
|
||||
if (qi.AttackerScore >= 3) {
|
||||
factionSidedWith = invasion.Faction;
|
||||
battlePay = invasion.AttackerReward.countedItems;
|
||||
logger.debug(`invasion pay from ${factionSidedWith}`, { battlePay });
|
||||
} else if (qi.DefenderScore >= 3) {
|
||||
factionSidedWith = invasion.DefenderFaction;
|
||||
battlePay = invasion.DefenderReward.countedItems;
|
||||
logger.debug(`invasion pay from ${factionSidedWith}`, { battlePay });
|
||||
}
|
||||
if (factionSidedWith) {
|
||||
if (battlePay) {
|
||||
// Decoupling rewards from the inbox message because it may delete itself without being read
|
||||
for (const item of battlePay) {
|
||||
await addItem(inventory, item.ItemType, item.ItemCount);
|
||||
}
|
||||
await createMessage(account._id, [
|
||||
{
|
||||
sndr: eFaction.find(x => x.tag == factionSidedWith)?.name ?? factionSidedWith, // TOVERIFY
|
||||
msg: `/Lotus/Language/G1Quests/${factionSidedWith}_InvasionThankyouMessageBody`,
|
||||
sub: `/Lotus/Language/G1Quests/${factionSidedWith}_InvasionThankyouMessageSubject`,
|
||||
countedAtt: battlePay,
|
||||
attVisualOnly: true,
|
||||
icon:
|
||||
factionSidedWith == "FC_GRINEER"
|
||||
? "/Lotus/Interface/Icons/Npcs/EliteRifleLancerAvatar.png" // Source: https://www.reddit.com/r/Warframe/comments/1aj4usx/battle_pay_worth_10_plat/, https://www.youtube.com/watch?v=XhNZ6ai6BOY
|
||||
: "/Lotus/Interface/Icons/Npcs/CrewmanNormal.png", // My best source for this is https://www.youtube.com/watch?v=rxrCCFm73XE around 1:37
|
||||
// TOVERIFY: highPriority?
|
||||
endDate: new Date(Date.now() + 86400_000) // TOVERIFY: This type of inbox message seems to automatically delete itself. We'll just delete it after 24 hours, but it's not clear if this is correct.
|
||||
}
|
||||
]);
|
||||
}
|
||||
if (invasion.Faction != "FC_INFESTATION") {
|
||||
// Sided with grineer -> opposed corpus -> send zanuka (harvester)
|
||||
// Sided with corpus -> opposed grineer -> send g3 (death squad)
|
||||
inventory[factionSidedWith != "FC_GRINEER" ? "DeathSquadable" : "Harvestable"] = true;
|
||||
// TOVERIFY: Should this happen earlier?
|
||||
// TOVERIFY: Should this send an (ephemeral) email?
|
||||
}
|
||||
}
|
||||
logger.debug(`removing QualifyingInvasions entry for completed invasion: ${qi.invasionId.toString()}`);
|
||||
inventory.QualifyingInvasions.splice(i, 1);
|
||||
continue;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
if (inventory.LastInventorySync) {
|
||||
const lastSyncDuviriMood = Math.trunc(inventory.LastInventorySync.getTimestamp().getTime() / 7200000);
|
||||
const currentDuviriMood = Math.trunc(Date.now() / 7200000);
|
||||
|
5
src/controllers/api/resetQuestProgressController.ts
Normal file
5
src/controllers/api/resetQuestProgressController.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const resetQuestProgressController: RequestHandler = (_req, res) => {
|
||||
res.send("1").end();
|
||||
};
|
@ -112,6 +112,7 @@ import { removeFromGuildController } from "@/src/controllers/api/removeFromGuild
|
||||
import { removeIgnoredUserController } from "@/src/controllers/api/removeIgnoredUserController";
|
||||
import { renamePetController } from "@/src/controllers/api/renamePetController";
|
||||
import { rerollRandomModController } from "@/src/controllers/api/rerollRandomModController";
|
||||
import { resetQuestProgressController } from "@/src/controllers/api/resetQuestProgressController";
|
||||
import { retrievePetFromStasisController } from "@/src/controllers/api/retrievePetFromStasisController";
|
||||
import { saveDialogueController } from "@/src/controllers/api/saveDialogueController";
|
||||
import { saveLoadoutController } from "@/src/controllers/api/saveLoadoutController";
|
||||
@ -209,6 +210,7 @@ apiRouter.get("/questControl.php", questControlController);
|
||||
apiRouter.get("/queueDojoComponentDestruction.php", queueDojoComponentDestructionController);
|
||||
apiRouter.get("/removeFriend.php", removeFriendGetController);
|
||||
apiRouter.get("/removeFromAlliance.php", removeFromAllianceController);
|
||||
apiRouter.get("/resetQuestProgress.php", resetQuestProgressController);
|
||||
apiRouter.get("/setActiveQuest.php", setActiveQuestController);
|
||||
apiRouter.get("/setActiveShip.php", setActiveShipController);
|
||||
apiRouter.get("/setAllianceGuildPermissions.php", setAllianceGuildPermissionsController);
|
||||
|
@ -1635,6 +1635,15 @@ export const addEmailItem = async (
|
||||
return inventoryChanges;
|
||||
};
|
||||
|
||||
const xpEarningParts: readonly string[] = [
|
||||
"LWPT_BLADE",
|
||||
"LWPT_GUN_BARREL",
|
||||
"LWPT_AMP_OCULUS",
|
||||
"LWPT_MOA_HEAD",
|
||||
"LWPT_ZANUKA_HEAD",
|
||||
"LWPT_HB_DECK"
|
||||
];
|
||||
|
||||
export const applyClientEquipmentUpdates = (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
gearArray: IEquipmentClient[],
|
||||
@ -1653,13 +1662,26 @@ export const applyClientEquipmentUpdates = (
|
||||
item.XP ??= 0;
|
||||
item.XP += XP;
|
||||
|
||||
const xpinfoIndex = inventory.XPInfo.findIndex(x => x.ItemType == item.ItemType);
|
||||
let xpItemType = item.ItemType;
|
||||
if (item.ModularParts) {
|
||||
for (const part of item.ModularParts) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
const partType = ExportWeapons[part]?.partType;
|
||||
if (partType !== undefined && xpEarningParts.indexOf(partType) != -1) {
|
||||
xpItemType = part;
|
||||
break;
|
||||
}
|
||||
}
|
||||
logger.debug(`adding xp to ${xpItemType} for modular item ${fromOid(ItemId)} (${item.ItemType})`);
|
||||
}
|
||||
|
||||
const xpinfoIndex = inventory.XPInfo.findIndex(x => x.ItemType == xpItemType);
|
||||
if (xpinfoIndex !== -1) {
|
||||
const xpinfo = inventory.XPInfo[xpinfoIndex];
|
||||
xpinfo.XP += XP;
|
||||
} else {
|
||||
inventory.XPInfo.push({
|
||||
ItemType: item.ItemType,
|
||||
ItemType: xpItemType,
|
||||
XP: XP
|
||||
});
|
||||
}
|
||||
|
@ -558,6 +558,7 @@ export const addMissionInventoryUpdates = async (
|
||||
}
|
||||
]);
|
||||
}
|
||||
inventory.DeathSquadable = false;
|
||||
break;
|
||||
}
|
||||
case "LockedWeaponGroup": {
|
||||
@ -576,7 +577,7 @@ export const addMissionInventoryUpdates = async (
|
||||
break;
|
||||
}
|
||||
case "IncHarvester": {
|
||||
inventory.Harvestable = true;
|
||||
// Unsure what to do with this
|
||||
break;
|
||||
}
|
||||
case "CurrentLoadOutIds": {
|
||||
|
@ -6,15 +6,18 @@ import sortieTilesets from "@/static/fixed_responses/worldState/sortieTilesets.j
|
||||
import sortieTilesetMissions from "@/static/fixed_responses/worldState/sortieTilesetMissions.json";
|
||||
import syndicateMissions from "@/static/fixed_responses/worldState/syndicateMissions.json";
|
||||
import darvoDeals from "@/static/fixed_responses/worldState/darvoDeals.json";
|
||||
import invasionNodes from "@/static/fixed_responses/worldState/invasionNodes.json";
|
||||
import invasionRewards from "@/static/fixed_responses/worldState/invasionRewards.json";
|
||||
import { buildConfig } from "@/src/services/buildConfigService";
|
||||
import { unixTimesInMs } from "@/src/constants/timeConstants";
|
||||
import { config } from "@/src/services/configService";
|
||||
import { getRandomElement, getRandomInt, sequentiallyUniqueRandomElement, SRng } from "@/src/services/rngService";
|
||||
import { eMissionType, ExportRegions, ExportSyndicates, IRegion } from "warframe-public-export-plus";
|
||||
import { eMissionType, ExportRegions, ExportSyndicates, IMissionReward, IRegion } from "warframe-public-export-plus";
|
||||
import {
|
||||
ICalendarDay,
|
||||
ICalendarEvent,
|
||||
ICalendarSeason,
|
||||
IInvasion,
|
||||
ILiteSortie,
|
||||
IPrimeVaultTrader,
|
||||
IPrimeVaultTraderOffer,
|
||||
@ -1227,6 +1230,78 @@ const getAllVarziaManifests = (): IPrimeVaultTraderOffer[] => {
|
||||
return [...dualPacks, ...singlePacks, ...items, ...bobbleHeads, ...relics];
|
||||
};
|
||||
|
||||
const createInvasion = (day: number, idx: number): IInvasion => {
|
||||
const id = day * 3 + idx;
|
||||
const defender = (["FC_GRINEER", "FC_CORPUS", day % 2 ? "FC_GRINEER" : "FC_CORPUS"] as const)[idx];
|
||||
const rng = new SRng(new SRng(id).randomInt(0, 1_000_000));
|
||||
const isInfestationOutbreak = rng.randomInt(0, 1) == 0;
|
||||
const attacker = isInfestationOutbreak ? "FC_INFESTATION" : defender == "FC_GRINEER" ? "FC_CORPUS" : "FC_GRINEER";
|
||||
const startMs = EPOCH + day * 86400_000;
|
||||
const oid =
|
||||
((startMs / 1000) & 0xffffffff).toString(16).padStart(8, "0") +
|
||||
"fd148cb8" +
|
||||
(idx & 0xffffffff).toString(16).padStart(8, "0");
|
||||
const node = sequentiallyUniqueRandomElement(invasionNodes[defender], id, 5, 690175)!; // Can't repeat the other 2 on this day nor the last 3
|
||||
const progress = (Date.now() - startMs) / 86400_000;
|
||||
const countMultiplier = isInfestationOutbreak || rng.randomInt(0, 1) ? -1 : 1; // if defender is winning, count is negative
|
||||
const fiftyPercent = rng.randomInt(1000, 29000); // introduce some 'yitter' for the percentages
|
||||
const rewardFloat = rng.randomFloat();
|
||||
const rewardTier = rewardFloat < 0.201 ? "RARE" : rewardFloat < 0.7788 ? "COMMON" : "UNCOMMON";
|
||||
const attackerReward: IMissionReward = {};
|
||||
const defenderReward: IMissionReward = {};
|
||||
if (isInfestationOutbreak) {
|
||||
defenderReward.countedItems = [
|
||||
rng.randomElement(invasionRewards[rng.randomInt(0, 1) ? "FC_INFESTATION" : defender][rewardTier])!
|
||||
];
|
||||
} else {
|
||||
attackerReward.countedItems = [rng.randomElement(invasionRewards[attacker][rewardTier])!];
|
||||
defenderReward.countedItems = [rng.randomElement(invasionRewards[defender][rewardTier])!];
|
||||
}
|
||||
return {
|
||||
_id: { $oid: oid },
|
||||
Faction: attacker,
|
||||
DefenderFaction: defender,
|
||||
Node: node,
|
||||
Count: Math.round(
|
||||
(progress < 0.5 ? progress * 2 * fiftyPercent : fiftyPercent + (30_000 - fiftyPercent) * (progress - 0.5)) *
|
||||
countMultiplier
|
||||
),
|
||||
Goal: 30000, // Value seems to range from 30000 to 98000 in intervals of 1000. Higher values are increasingly rare. I don't think this is relevant for the frontend besides dividing count by it.
|
||||
LocTag: isInfestationOutbreak
|
||||
? ExportRegions[node].missionIndex == 0
|
||||
? "/Lotus/Language/Menu/InfestedInvasionBoss"
|
||||
: "/Lotus/Language/Menu/InfestedInvasionGeneric"
|
||||
: attacker == "FC_CORPUS"
|
||||
? "/Lotus/Language/Menu/CorpusInvasionGeneric"
|
||||
: "/Lotus/Language/Menu/GrineerInvasionGeneric",
|
||||
Completed: startMs + 86400_000 < Date.now(), // Sorta unfaithful. Invasions on live are (at least in part) in fluenced by people completing them. And otherwise also probably not hardcoded to last 24 hours.
|
||||
ChainID: { $oid: oid },
|
||||
AttackerReward: attackerReward,
|
||||
AttackerMissionInfo: {
|
||||
seed: rng.randomInt(0, 1_000_000),
|
||||
faction: defender
|
||||
},
|
||||
DefenderReward: defenderReward,
|
||||
DefenderMissionInfo: {
|
||||
seed: rng.randomInt(0, 1_000_000),
|
||||
faction: attacker
|
||||
},
|
||||
Activation: {
|
||||
$date: {
|
||||
$numberLong: startMs.toString()
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export const getInvasionByOid = (oid: string): IInvasion | undefined => {
|
||||
const arr = oid.split("fd148cb8");
|
||||
if (arr.length == 2 && arr[0].length == 8 && arr[1].length == 8) {
|
||||
return createInvasion(idToDay(oid), parseInt(arr[1], 16));
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const getWorldState = (buildLabel?: string): IWorldState => {
|
||||
const constraints: ITimeConstraint[] = [];
|
||||
if (config.worldState?.eidolonOverride) {
|
||||
@ -1275,6 +1350,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
||||
LiteSorties: [],
|
||||
ActiveMissions: [],
|
||||
GlobalUpgrades: [],
|
||||
Invasions: [],
|
||||
VoidTraders: [],
|
||||
PrimeVaultTraders: [],
|
||||
VoidStorms: [],
|
||||
@ -1477,6 +1553,20 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
||||
});
|
||||
}
|
||||
|
||||
// Rough outline of dynamic invasions.
|
||||
// TODO: Invasions chains, e.g. an infestation mission would soon lead to other nodes on that planet also having an infestation invasion.
|
||||
// TODO: Grineer/Corpus to fund their death stars with each invasion win.
|
||||
{
|
||||
worldState.Invasions.push(createInvasion(day, 0));
|
||||
worldState.Invasions.push(createInvasion(day, 1));
|
||||
worldState.Invasions.push(createInvasion(day, 2));
|
||||
|
||||
// Completed invasions stay for up to 24 hours as the winner 'occupies' that node
|
||||
worldState.Invasions.push(createInvasion(day - 1, 0));
|
||||
worldState.Invasions.push(createInvasion(day - 1, 1));
|
||||
worldState.Invasions.push(createInvasion(day - 1, 2));
|
||||
}
|
||||
|
||||
// Baro
|
||||
{
|
||||
const baroIndex = Math.trunc((Date.now() - 910800000) / (unixTimesInMs.day * 14));
|
||||
|
@ -12,6 +12,7 @@ export interface IWorldState {
|
||||
SyndicateMissions: ISyndicateMissionInfo[];
|
||||
ActiveMissions: IFissure[];
|
||||
GlobalUpgrades: IGlobalUpgrade[];
|
||||
Invasions: IInvasion[];
|
||||
NodeOverrides: INodeOverride[];
|
||||
VoidTraders: IVoidTrader[];
|
||||
PrimeVaultTraders: IPrimeVaultTrader[];
|
||||
@ -82,6 +83,28 @@ export interface IGlobalUpgrade {
|
||||
LocalizeDescTag: string;
|
||||
}
|
||||
|
||||
export interface IInvasion {
|
||||
_id: IOid;
|
||||
Faction: string;
|
||||
DefenderFaction: string;
|
||||
Node: string;
|
||||
Count: number;
|
||||
Goal: number;
|
||||
LocTag: string;
|
||||
Completed: boolean;
|
||||
ChainID: IOid;
|
||||
AttackerReward: IMissionReward;
|
||||
AttackerMissionInfo: IInvasionMissionInfo;
|
||||
DefenderReward: IMissionReward;
|
||||
DefenderMissionInfo: IInvasionMissionInfo;
|
||||
Activation: IMongoDate;
|
||||
}
|
||||
|
||||
export interface IInvasionMissionInfo {
|
||||
seed: number;
|
||||
faction: string;
|
||||
}
|
||||
|
||||
export interface IFissure {
|
||||
_id: IOid;
|
||||
Region: number;
|
||||
|
114
static/fixed_responses/worldState/invasionNodes.json
Normal file
114
static/fixed_responses/worldState/invasionNodes.json
Normal file
@ -0,0 +1,114 @@
|
||||
{
|
||||
"FC_CORPUS": [
|
||||
"SettlementNode1",
|
||||
"SettlementNode2",
|
||||
"SettlementNode3",
|
||||
"SettlementNode11",
|
||||
"SettlementNode12",
|
||||
"SettlementNode14",
|
||||
"SettlementNode15",
|
||||
"SettlementNode20",
|
||||
"SolNode1",
|
||||
"SolNode2",
|
||||
"SolNode4",
|
||||
"SolNode6",
|
||||
"SolNode10",
|
||||
"SolNode17",
|
||||
"SolNode21",
|
||||
"SolNode22",
|
||||
"SolNode23",
|
||||
"SolNode25",
|
||||
"SolNode38",
|
||||
"SolNode43",
|
||||
"SolNode48",
|
||||
"SolNode49",
|
||||
"SolNode51",
|
||||
"SolNode53",
|
||||
"SolNode56",
|
||||
"SolNode57",
|
||||
"SolNode61",
|
||||
"SolNode62",
|
||||
"SolNode65",
|
||||
"SolNode66",
|
||||
"SolNode72",
|
||||
"SolNode73",
|
||||
"SolNode74",
|
||||
"SolNode76",
|
||||
"SolNode78",
|
||||
"SolNode81",
|
||||
"SolNode84",
|
||||
"SolNode88",
|
||||
"SolNode97",
|
||||
"SolNode100",
|
||||
"SolNode101",
|
||||
"SolNode102",
|
||||
"SolNode104",
|
||||
"SolNode107",
|
||||
"SolNode109",
|
||||
"SolNode118",
|
||||
"SolNode121",
|
||||
"SolNode123",
|
||||
"SolNode125",
|
||||
"SolNode126",
|
||||
"SolNode127",
|
||||
"SolNode128",
|
||||
"SolNode203",
|
||||
"SolNode205",
|
||||
"SolNode209",
|
||||
"SolNode210",
|
||||
"SolNode211",
|
||||
"SolNode212",
|
||||
"SolNode214",
|
||||
"SolNode216",
|
||||
"SolNode217",
|
||||
"SolNode220"
|
||||
],
|
||||
"FC_GRINEER": [
|
||||
"SolNode11",
|
||||
"SolNode16",
|
||||
"SolNode18",
|
||||
"SolNode19",
|
||||
"SolNode20",
|
||||
"SolNode30",
|
||||
"SolNode31",
|
||||
"SolNode32",
|
||||
"SolNode36",
|
||||
"SolNode41",
|
||||
"SolNode42",
|
||||
"SolNode45",
|
||||
"SolNode46",
|
||||
"SolNode50",
|
||||
"SolNode58",
|
||||
"SolNode67",
|
||||
"SolNode68",
|
||||
"SolNode70",
|
||||
"SolNode82",
|
||||
"SolNode93",
|
||||
"SolNode96",
|
||||
"SolNode99",
|
||||
"SolNode106",
|
||||
"SolNode113",
|
||||
"SolNode131",
|
||||
"SolNode132",
|
||||
"SolNode135",
|
||||
"SolNode137",
|
||||
"SolNode138",
|
||||
"SolNode139",
|
||||
"SolNode140",
|
||||
"SolNode141",
|
||||
"SolNode144",
|
||||
"SolNode146",
|
||||
"SolNode147",
|
||||
"SolNode149",
|
||||
"SolNode177",
|
||||
"SolNode181",
|
||||
"SolNode184",
|
||||
"SolNode185",
|
||||
"SolNode187",
|
||||
"SolNode188",
|
||||
"SolNode189",
|
||||
"SolNode191",
|
||||
"SolNode195",
|
||||
"SolNode196"
|
||||
]
|
||||
}
|
190
static/fixed_responses/worldState/invasionRewards.json
Normal file
190
static/fixed_responses/worldState/invasionRewards.json
Normal file
@ -0,0 +1,190 @@
|
||||
{
|
||||
"FC_GRINEER": {
|
||||
"COMMON": [
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Items/Research/ChemComponent",
|
||||
"ItemCount": 3
|
||||
}
|
||||
],
|
||||
"UNCOMMON": [
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/KarakWraithBlueprint",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/KarakWraithBarrel",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/KarakWraithReceiver",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/KarakWraithStock",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/StrunWraithBlueprint",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/StrunWraithBarrel",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/StrunWraithReceiver",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/StrunWraithStock",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/LatronWraithBlueprint",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/LatronWraithBarrel",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/LatronWraithReceiver",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/LatronWraithStock",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/TwinVipersWraithBlueprint",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/TwinVipersWraithBarrel",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/TwinVipersWraithLink",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/TwinVipersWraithReceiver",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/GrineerCombatKnifeSortieBlueprint",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/GrineerCombatKnifeHilt",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/GrineerCombatKnifeBlade",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/GrineerCombatKnifeHeatsink",
|
||||
"ItemCount": 1
|
||||
}
|
||||
],
|
||||
"RARE": [
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Components/OrokinCatalystBlueprint",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Components/OrokinReactorBlueprint",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Components/FormaBlueprint",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Components/UtilityUnlockerBlueprint",
|
||||
"ItemCount": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"FC_CORPUS": {
|
||||
"COMMON": [
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Items/Research/EnergyComponent",
|
||||
"ItemCount": 3
|
||||
}
|
||||
],
|
||||
"UNCOMMON": [
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/DeraVandalBlueprint",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/DeraVandalBarrel",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/DeraVandalReceiver",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/DeraVandalStock",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/SnipetronVandalBlueprint",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/SnipetronVandalStock",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/SnipetronVandalReceiver",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Weapons/WeaponParts/SnipetronVandalBarrel",
|
||||
"ItemCount": 1
|
||||
}
|
||||
],
|
||||
"RARE": [
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Components/OrokinCatalystBlueprint",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Components/OrokinReactorBlueprint",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Components/FormaBlueprint",
|
||||
"ItemCount": 1
|
||||
},
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Recipes/Components/UtilityUnlockerBlueprint",
|
||||
"ItemCount": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"FC_INFESTATION": {
|
||||
"COMMON": [
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Items/Research/BioComponent",
|
||||
"ItemCount": 1
|
||||
}
|
||||
],
|
||||
"UNCOMMON": [
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Items/Research/BioComponent",
|
||||
"ItemCount": 2
|
||||
}
|
||||
],
|
||||
"RARE": [
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Items/MiscItems/InfestedAladCoordinate",
|
||||
"ItemCount": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -117,46 +117,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"Invasions": [
|
||||
{
|
||||
"_id": {
|
||||
"$oid": "67c8ec8b3d0d86b236c1c18f"
|
||||
},
|
||||
"Faction": "FC_INFESTATION",
|
||||
"DefenderFaction": "FC_CORPUS",
|
||||
"Node": "SolNode53",
|
||||
"Count": -28558,
|
||||
"Goal": 30000,
|
||||
"LocTag": "/Lotus/Language/Menu/InfestedInvasionBoss",
|
||||
"Completed": false,
|
||||
"ChainID": {
|
||||
"$oid": "67c8b6a2bde0dfd0f7c1c18d"
|
||||
},
|
||||
"AttackerReward": [],
|
||||
"AttackerMissionInfo": {
|
||||
"seed": 488863,
|
||||
"faction": "FC_CORPUS"
|
||||
},
|
||||
"DefenderReward": {
|
||||
"countedItems": [
|
||||
{
|
||||
"ItemType": "/Lotus/Types/Items/Research/EnergyComponent",
|
||||
"ItemCount": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
"DefenderMissionInfo": {
|
||||
"seed": 127653,
|
||||
"faction": "FC_INFESTATION",
|
||||
"missionReward": []
|
||||
},
|
||||
"Activation": {
|
||||
"$date": {
|
||||
"$numberLong": "1741221003031"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"SyndicateMissions": [
|
||||
{
|
||||
"_id": { "$oid": "663a4fc5ba6f84724fa4804c" },
|
||||
|
@ -4,7 +4,7 @@ dict = {
|
||||
general_addButton: `Agregar`,
|
||||
general_setButton: `Establecer`,
|
||||
general_bulkActions: `Acciones masivas`,
|
||||
general_loading: `[UNTRANSLATED] Loading...`,
|
||||
general_loading: `Cargando...`,
|
||||
|
||||
code_loginFail: `Error al iniciar sesión. Verifica el correo electrónico y la contraseña.`,
|
||||
code_regFail: `Error al registrar la cuenta. ¿Ya existe una cuenta con este correo?`,
|
||||
@ -45,8 +45,8 @@ dict = {
|
||||
code_focusUnlocked: `¡Desbloqueadas |COUNT| nuevas escuelas de enfoque! Se necesita una actualización del inventario para reflejar los cambios en el juego. Visitar la navegación debería ser la forma más sencilla de activarlo.`,
|
||||
code_addModsConfirm: `¿Estás seguro de que deseas agregar |COUNT| modificadores a tu cuenta?`,
|
||||
code_succImport: `Importación exitosa.`,
|
||||
code_succRelog: `[UNTRANSLATED] Done. Please note that you'll need to relog to see a difference in-game.`,
|
||||
code_nothingToDo: `[UNTRANSLATED] Done. There was nothing to do.`,
|
||||
code_succRelog: `Hecho. Ten en cuenta que deberás volver a iniciar sesión para ver los cambios en el juego.`,
|
||||
code_nothingToDo: `Hecho. No había nada que hacer.`,
|
||||
code_gild: `Refinar`,
|
||||
code_moa: `Moa`,
|
||||
code_zanuka: `Sabueso`,
|
||||
@ -129,7 +129,7 @@ dict = {
|
||||
mods_fingerprintHelp: `¿Necesitas ayuda con la huella digital?`,
|
||||
mods_rivens: `Agrietados`,
|
||||
mods_mods: `Mods`,
|
||||
mods_addMax: `[UNTRANSLATED] Add Maxed`,
|
||||
mods_addMax: `Agregar al máximo`,
|
||||
mods_addMissingUnrankedMods: `Agregar mods sin rango faltantes`,
|
||||
mods_removeUnranked: `Quitar mods sin rango`,
|
||||
mods_addMissingMaxRankMods: `Agregar mods de rango máximo faltantes`,
|
||||
@ -185,13 +185,13 @@ dict = {
|
||||
cheats_noDojoResearchTime: `Sin tiempo de investigación del dojo`,
|
||||
cheats_fastClanAscension: `Ascenso rápido del clan`,
|
||||
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_exceptionalRelicsAlwaysGiveBronzeReward: `Las reliquias excepcionales siempre otorgan recompensa de bronce`,
|
||||
cheats_flawlessRelicsAlwaysGiveSilverReward: `Las reliquias impecables siempre otorgan recompensa de plata`,
|
||||
cheats_radiantRelicsAlwaysGiveGoldReward: `Las reliquias radiantes siempre otorgan recompensa de oro`,
|
||||
cheats_unlockAllSimarisResearchEntries: `Desbloquear todas las entradas de investigación de Simaris`,
|
||||
cheats_disableDailyTribute: `Desactivar tributo diario`,
|
||||
cheats_spoofMasteryRank: `Rango de maestría simulado (-1 para desactivar)`,
|
||||
cheats_relicRewardItemCountMultiplier: `[UNTRANSLATED] Relic Reward Item Count Multiplier`,
|
||||
cheats_relicRewardItemCountMultiplier: `Multiplicador de cantidad de recompensas de reliquia`,
|
||||
cheats_nightwaveStandingMultiplier: `Multiplicador de Reputación de Onda Nocturna`,
|
||||
cheats_save: `Guardar`,
|
||||
cheats_account: `Cuenta`,
|
||||
@ -202,7 +202,7 @@ dict = {
|
||||
cheats_changeSupportedSyndicate: `Sindicatos disponibles`,
|
||||
cheats_changeButton: `Cambiar`,
|
||||
cheats_none: `Ninguno`,
|
||||
cheats_markAllAsRead: `[UNTRANSLATED] Mark Inbox As Read`,
|
||||
cheats_markAllAsRead: `Marcar bandeja de entrada como leída`,
|
||||
|
||||
worldState: `Estado del mundo`,
|
||||
worldState_creditBoost: `Potenciador de Créditos`,
|
||||
@ -249,8 +249,8 @@ dict = {
|
||||
worldState_allAtOnceSteelPath: `Todo a la vez, Camino de Acero`,
|
||||
worldState_theCircuitOverride: `Cambio del Circuito`,
|
||||
worldState_darvoStockMultiplier: `Multiplicador de stock de Darvo`,
|
||||
worldState_varziaFullyStocked: `[UNTRANSLATED] Varzia Fully Stocked`,
|
||||
worldState_varziaOverride: `[UNTRANSLATED] Varzia Rotation Override`,
|
||||
worldState_varziaFullyStocked: `Varzia con stock completo`,
|
||||
worldState_varziaOverride: `Cambio en rotación de Varzia`,
|
||||
|
||||
import_importNote: `Puedes proporcionar una respuesta de inventario completa o parcial (representación del cliente) aquí. Todos los campos compatibles con el importador <b>serán sobrescritos</b> en tu cuenta.`,
|
||||
import_submit: `Enviar`,
|
||||
@ -303,10 +303,10 @@ dict = {
|
||||
upgrade_OnExecutionTerrify: `50% de probabilidad de que enemigos en un radio de 15m entren en pánico por 8s tras una ejecución`,
|
||||
upgrade_OnHackLockers: `Desbloquea 5 casilleros en un radio de 20m tras hackear`,
|
||||
upgrade_OnExecutionBlind: `Ciega a los enemigos en un radio de 18m tras una ejecución`,
|
||||
upgrade_OnExecutionDrainPower: `[UNTRANSLATED] Next ability cast gains +50% Ability Strength on Mercy`,
|
||||
upgrade_OnExecutionDrainPower: `La próxima habilidad usada gana +50% de fuerza al realizar un remate (Mercy)`,
|
||||
upgrade_OnHackSprintSpeed: `+75% de velocidad de carrera durante 15s después de hackear`,
|
||||
upgrade_SwiftExecute: `[UNTRANSLATED] +50% Mercy Kill Speed`,
|
||||
upgrade_OnHackInvis: `[UNTRANSLATED] Invisible for 15 seconds after Hacking`,
|
||||
upgrade_SwiftExecute: `+50% de velocidad al ejecutar remates (Mercy)`,
|
||||
upgrade_OnHackInvis: `Invisible durante 15 segundos después de hackear`,
|
||||
|
||||
damageType_Electricity: `Eletricidade`,
|
||||
damageType_Fire: `Ígneo`,
|
||||
|
Loading…
x
Reference in New Issue
Block a user