merge upstream
This commit is contained in:
commit
90c1fdeace
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.77",
|
"warframe-public-export-plus": "^0.5.78",
|
||||||
"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",
|
||||||
@ -5479,9 +5479,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/warframe-public-export-plus": {
|
"node_modules/warframe-public-export-plus": {
|
||||||
"version": "0.5.77",
|
"version": "0.5.78",
|
||||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.77.tgz",
|
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.78.tgz",
|
||||||
"integrity": "sha512-Th/b82pYB4i95afC/s8MDDXsVMl3vyy1qDwLO/AzV6peVBTs2kCSO68nNh7yXDiviGlNl0HRq+LR25jMjtFwSg=="
|
"integrity": "sha512-Zvg7N+EdXS8cOAZIxqCbqiqyvQZBgh2xTxEwpHnoyJjNBpm3sP/7dtXmzHaxAZjyaCL4pvi9e7kTvxmpH8Pcag=="
|
||||||
},
|
},
|
||||||
"node_modules/warframe-riven-info": {
|
"node_modules/warframe-riven-info": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
|
@ -39,7 +39,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.77",
|
"warframe-public-export-plus": "^0.5.78",
|
||||||
"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",
|
||||||
|
@ -6,10 +6,18 @@ import allDialogue from "@/static/fixed_responses/allDialogue.json";
|
|||||||
import { ILoadoutDatabase } from "@/src/types/saveLoadoutTypes";
|
import { ILoadoutDatabase } from "@/src/types/saveLoadoutTypes";
|
||||||
import { IInventoryClient, IShipInventory, equipmentKeys } from "@/src/types/inventoryTypes/inventoryTypes";
|
import { IInventoryClient, IShipInventory, equipmentKeys } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
import { IPolarity, ArtifactPolarity } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
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 { applyCheatsToInfestedFoundry, handleSubsumeCompletion } from "@/src/services/infestedFoundryService";
|
||||||
import {
|
import {
|
||||||
addEmailItem,
|
addEmailItem,
|
||||||
|
addItem,
|
||||||
addMiscItems,
|
addMiscItems,
|
||||||
allDailyAffiliationKeys,
|
allDailyAffiliationKeys,
|
||||||
checkCalendarAutoAdvance,
|
checkCalendarAutoAdvance,
|
||||||
@ -30,7 +38,8 @@ import { unixTimesInMs } from "@/src/constants/timeConstants";
|
|||||||
import { DailyDeal } from "@/src/models/worldStateModel";
|
import { DailyDeal } from "@/src/models/worldStateModel";
|
||||||
import { EquipmentFeatures } from "@/src/types/equipmentTypes";
|
import { EquipmentFeatures } from "@/src/types/equipmentTypes";
|
||||||
import { generateRewardSeed } from "@/src/services/rngService";
|
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) => {
|
export const inventoryController: RequestHandler = async (request, response) => {
|
||||||
const account = await getAccountForRequest(request);
|
const account = await getAccountForRequest(request);
|
||||||
@ -186,6 +195,63 @@ export const inventoryController: RequestHandler = async (request, response) =>
|
|||||||
//await inventory.save();
|
//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) {
|
if (inventory.LastInventorySync) {
|
||||||
const lastSyncDuviriMood = Math.trunc(inventory.LastInventorySync.getTimestamp().getTime() / 7200000);
|
const lastSyncDuviriMood = Math.trunc(inventory.LastInventorySync.getTimestamp().getTime() / 7200000);
|
||||||
const currentDuviriMood = Math.trunc(Date.now() / 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 { removeIgnoredUserController } from "@/src/controllers/api/removeIgnoredUserController";
|
||||||
import { renamePetController } from "@/src/controllers/api/renamePetController";
|
import { renamePetController } from "@/src/controllers/api/renamePetController";
|
||||||
import { rerollRandomModController } from "@/src/controllers/api/rerollRandomModController";
|
import { rerollRandomModController } from "@/src/controllers/api/rerollRandomModController";
|
||||||
|
import { resetQuestProgressController } from "@/src/controllers/api/resetQuestProgressController";
|
||||||
import { retrievePetFromStasisController } from "@/src/controllers/api/retrievePetFromStasisController";
|
import { retrievePetFromStasisController } from "@/src/controllers/api/retrievePetFromStasisController";
|
||||||
import { saveDialogueController } from "@/src/controllers/api/saveDialogueController";
|
import { saveDialogueController } from "@/src/controllers/api/saveDialogueController";
|
||||||
import { saveLoadoutController } from "@/src/controllers/api/saveLoadoutController";
|
import { saveLoadoutController } from "@/src/controllers/api/saveLoadoutController";
|
||||||
@ -209,6 +210,7 @@ apiRouter.get("/questControl.php", questControlController);
|
|||||||
apiRouter.get("/queueDojoComponentDestruction.php", queueDojoComponentDestructionController);
|
apiRouter.get("/queueDojoComponentDestruction.php", queueDojoComponentDestructionController);
|
||||||
apiRouter.get("/removeFriend.php", removeFriendGetController);
|
apiRouter.get("/removeFriend.php", removeFriendGetController);
|
||||||
apiRouter.get("/removeFromAlliance.php", removeFromAllianceController);
|
apiRouter.get("/removeFromAlliance.php", removeFromAllianceController);
|
||||||
|
apiRouter.get("/resetQuestProgress.php", resetQuestProgressController);
|
||||||
apiRouter.get("/setActiveQuest.php", setActiveQuestController);
|
apiRouter.get("/setActiveQuest.php", setActiveQuestController);
|
||||||
apiRouter.get("/setActiveShip.php", setActiveShipController);
|
apiRouter.get("/setActiveShip.php", setActiveShipController);
|
||||||
apiRouter.get("/setAllianceGuildPermissions.php", setAllianceGuildPermissionsController);
|
apiRouter.get("/setAllianceGuildPermissions.php", setAllianceGuildPermissionsController);
|
||||||
|
@ -1635,6 +1635,15 @@ export const addEmailItem = async (
|
|||||||
return inventoryChanges;
|
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 = (
|
export const applyClientEquipmentUpdates = (
|
||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
gearArray: IEquipmentClient[],
|
gearArray: IEquipmentClient[],
|
||||||
@ -1653,13 +1662,26 @@ export const applyClientEquipmentUpdates = (
|
|||||||
item.XP ??= 0;
|
item.XP ??= 0;
|
||||||
item.XP += XP;
|
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) {
|
if (xpinfoIndex !== -1) {
|
||||||
const xpinfo = inventory.XPInfo[xpinfoIndex];
|
const xpinfo = inventory.XPInfo[xpinfoIndex];
|
||||||
xpinfo.XP += XP;
|
xpinfo.XP += XP;
|
||||||
} else {
|
} else {
|
||||||
inventory.XPInfo.push({
|
inventory.XPInfo.push({
|
||||||
ItemType: item.ItemType,
|
ItemType: xpItemType,
|
||||||
XP: XP
|
XP: XP
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -558,6 +558,7 @@ export const addMissionInventoryUpdates = async (
|
|||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
inventory.DeathSquadable = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "LockedWeaponGroup": {
|
case "LockedWeaponGroup": {
|
||||||
@ -576,7 +577,7 @@ export const addMissionInventoryUpdates = async (
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "IncHarvester": {
|
case "IncHarvester": {
|
||||||
inventory.Harvestable = true;
|
// Unsure what to do with this
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "CurrentLoadOutIds": {
|
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 sortieTilesetMissions from "@/static/fixed_responses/worldState/sortieTilesetMissions.json";
|
||||||
import syndicateMissions from "@/static/fixed_responses/worldState/syndicateMissions.json";
|
import syndicateMissions from "@/static/fixed_responses/worldState/syndicateMissions.json";
|
||||||
import darvoDeals from "@/static/fixed_responses/worldState/darvoDeals.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 { buildConfig } from "@/src/services/buildConfigService";
|
||||||
import { unixTimesInMs } from "@/src/constants/timeConstants";
|
import { unixTimesInMs } from "@/src/constants/timeConstants";
|
||||||
import { config } from "@/src/services/configService";
|
import { config } from "@/src/services/configService";
|
||||||
import { getRandomElement, getRandomInt, sequentiallyUniqueRandomElement, SRng } from "@/src/services/rngService";
|
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 {
|
import {
|
||||||
ICalendarDay,
|
ICalendarDay,
|
||||||
ICalendarEvent,
|
ICalendarEvent,
|
||||||
ICalendarSeason,
|
ICalendarSeason,
|
||||||
|
IInvasion,
|
||||||
ILiteSortie,
|
ILiteSortie,
|
||||||
IPrimeVaultTrader,
|
IPrimeVaultTrader,
|
||||||
IPrimeVaultTraderOffer,
|
IPrimeVaultTraderOffer,
|
||||||
@ -1227,6 +1230,78 @@ const getAllVarziaManifests = (): IPrimeVaultTraderOffer[] => {
|
|||||||
return [...dualPacks, ...singlePacks, ...items, ...bobbleHeads, ...relics];
|
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 => {
|
export const getWorldState = (buildLabel?: string): IWorldState => {
|
||||||
const constraints: ITimeConstraint[] = [];
|
const constraints: ITimeConstraint[] = [];
|
||||||
if (config.worldState?.eidolonOverride) {
|
if (config.worldState?.eidolonOverride) {
|
||||||
@ -1275,6 +1350,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
|
|||||||
LiteSorties: [],
|
LiteSorties: [],
|
||||||
ActiveMissions: [],
|
ActiveMissions: [],
|
||||||
GlobalUpgrades: [],
|
GlobalUpgrades: [],
|
||||||
|
Invasions: [],
|
||||||
VoidTraders: [],
|
VoidTraders: [],
|
||||||
PrimeVaultTraders: [],
|
PrimeVaultTraders: [],
|
||||||
VoidStorms: [],
|
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
|
// Baro
|
||||||
{
|
{
|
||||||
const baroIndex = Math.trunc((Date.now() - 910800000) / (unixTimesInMs.day * 14));
|
const baroIndex = Math.trunc((Date.now() - 910800000) / (unixTimesInMs.day * 14));
|
||||||
|
@ -12,6 +12,7 @@ export interface IWorldState {
|
|||||||
SyndicateMissions: ISyndicateMissionInfo[];
|
SyndicateMissions: ISyndicateMissionInfo[];
|
||||||
ActiveMissions: IFissure[];
|
ActiveMissions: IFissure[];
|
||||||
GlobalUpgrades: IGlobalUpgrade[];
|
GlobalUpgrades: IGlobalUpgrade[];
|
||||||
|
Invasions: IInvasion[];
|
||||||
NodeOverrides: INodeOverride[];
|
NodeOverrides: INodeOverride[];
|
||||||
VoidTraders: IVoidTrader[];
|
VoidTraders: IVoidTrader[];
|
||||||
PrimeVaultTraders: IPrimeVaultTrader[];
|
PrimeVaultTraders: IPrimeVaultTrader[];
|
||||||
@ -82,6 +83,28 @@ export interface IGlobalUpgrade {
|
|||||||
LocalizeDescTag: string;
|
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 {
|
export interface IFissure {
|
||||||
_id: IOid;
|
_id: IOid;
|
||||||
Region: number;
|
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": [
|
"SyndicateMissions": [
|
||||||
{
|
{
|
||||||
"_id": { "$oid": "663a4fc5ba6f84724fa4804c" },
|
"_id": { "$oid": "663a4fc5ba6f84724fa4804c" },
|
||||||
|
@ -4,7 +4,7 @@ dict = {
|
|||||||
general_addButton: `Agregar`,
|
general_addButton: `Agregar`,
|
||||||
general_setButton: `Establecer`,
|
general_setButton: `Establecer`,
|
||||||
general_bulkActions: `Acciones masivas`,
|
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_loginFail: `Error al iniciar sesión. Verifica el correo electrónico y la contraseña.`,
|
||||||
code_regFail: `Error al registrar la cuenta. ¿Ya existe una cuenta con este correo?`,
|
code_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_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_addModsConfirm: `¿Estás seguro de que deseas agregar |COUNT| modificadores a tu cuenta?`,
|
||||||
code_succImport: `Importación exitosa.`,
|
code_succImport: `Importación exitosa.`,
|
||||||
code_succRelog: `[UNTRANSLATED] Done. Please note that you'll need to relog to see a difference in-game.`,
|
code_succRelog: `Hecho. Ten en cuenta que deberás volver a iniciar sesión para ver los cambios en el juego.`,
|
||||||
code_nothingToDo: `[UNTRANSLATED] Done. There was nothing to do.`,
|
code_nothingToDo: `Hecho. No había nada que hacer.`,
|
||||||
code_gild: `Refinar`,
|
code_gild: `Refinar`,
|
||||||
code_moa: `Moa`,
|
code_moa: `Moa`,
|
||||||
code_zanuka: `Sabueso`,
|
code_zanuka: `Sabueso`,
|
||||||
@ -129,7 +129,7 @@ dict = {
|
|||||||
mods_fingerprintHelp: `¿Necesitas ayuda con la huella digital?`,
|
mods_fingerprintHelp: `¿Necesitas ayuda con la huella digital?`,
|
||||||
mods_rivens: `Agrietados`,
|
mods_rivens: `Agrietados`,
|
||||||
mods_mods: `Mods`,
|
mods_mods: `Mods`,
|
||||||
mods_addMax: `[UNTRANSLATED] Add Maxed`,
|
mods_addMax: `Agregar al máximo`,
|
||||||
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`,
|
||||||
@ -185,13 +185,13 @@ dict = {
|
|||||||
cheats_noDojoResearchTime: `Sin tiempo de investigación del dojo`,
|
cheats_noDojoResearchTime: `Sin tiempo de investigación del dojo`,
|
||||||
cheats_fastClanAscension: `Ascenso rápido del clan`,
|
cheats_fastClanAscension: `Ascenso rápido del clan`,
|
||||||
cheats_missionsCanGiveAllRelics: `Las misiones pueden otorgar todas las reliquias`,
|
cheats_missionsCanGiveAllRelics: `Las misiones pueden otorgar todas las reliquias`,
|
||||||
cheats_exceptionalRelicsAlwaysGiveBronzeReward: `[UNTRANSLATED] Exceptional Relics Always Give Bronze Reward`,
|
cheats_exceptionalRelicsAlwaysGiveBronzeReward: `Las reliquias excepcionales siempre otorgan recompensa de bronce`,
|
||||||
cheats_flawlessRelicsAlwaysGiveSilverReward: `[UNTRANSLATED] Flawless Relics Always Give Silver Reward`,
|
cheats_flawlessRelicsAlwaysGiveSilverReward: `Las reliquias impecables siempre otorgan recompensa de plata`,
|
||||||
cheats_radiantRelicsAlwaysGiveGoldReward: `[UNTRANSLATED] Radiant Relics Always Give Gold Reward`,
|
cheats_radiantRelicsAlwaysGiveGoldReward: `Las reliquias radiantes siempre otorgan recompensa de oro`,
|
||||||
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_relicRewardItemCountMultiplier: `Multiplicador de cantidad de recompensas de reliquia`,
|
||||||
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`,
|
||||||
@ -202,7 +202,7 @@ dict = {
|
|||||||
cheats_changeSupportedSyndicate: `Sindicatos disponibles`,
|
cheats_changeSupportedSyndicate: `Sindicatos disponibles`,
|
||||||
cheats_changeButton: `Cambiar`,
|
cheats_changeButton: `Cambiar`,
|
||||||
cheats_none: `Ninguno`,
|
cheats_none: `Ninguno`,
|
||||||
cheats_markAllAsRead: `[UNTRANSLATED] Mark Inbox As Read`,
|
cheats_markAllAsRead: `Marcar bandeja de entrada como leída`,
|
||||||
|
|
||||||
worldState: `Estado del mundo`,
|
worldState: `Estado del mundo`,
|
||||||
worldState_creditBoost: `Potenciador de Créditos`,
|
worldState_creditBoost: `Potenciador de Créditos`,
|
||||||
@ -249,8 +249,8 @@ dict = {
|
|||||||
worldState_allAtOnceSteelPath: `Todo a la vez, Camino de Acero`,
|
worldState_allAtOnceSteelPath: `Todo a la vez, Camino de Acero`,
|
||||||
worldState_theCircuitOverride: `Cambio del Circuito`,
|
worldState_theCircuitOverride: `Cambio del Circuito`,
|
||||||
worldState_darvoStockMultiplier: `Multiplicador de stock de Darvo`,
|
worldState_darvoStockMultiplier: `Multiplicador de stock de Darvo`,
|
||||||
worldState_varziaFullyStocked: `[UNTRANSLATED] Varzia Fully Stocked`,
|
worldState_varziaFullyStocked: `Varzia con stock completo`,
|
||||||
worldState_varziaOverride: `[UNTRANSLATED] Varzia Rotation Override`,
|
worldState_varziaOverride: `Cambio en rotación de Varzia`,
|
||||||
|
|
||||||
import_importNote: `Puedes proporcionar una respuesta de inventario completa o parcial (representación del cliente) aquí. Todos los campos compatibles con el importador <b>serán sobrescritos</b> en tu cuenta.`,
|
import_importNote: `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`,
|
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_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_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_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_OnHackSprintSpeed: `+75% de velocidad de carrera durante 15s después de hackear`,
|
||||||
upgrade_SwiftExecute: `[UNTRANSLATED] +50% Mercy Kill Speed`,
|
upgrade_SwiftExecute: `+50% de velocidad al ejecutar remates (Mercy)`,
|
||||||
upgrade_OnHackInvis: `[UNTRANSLATED] Invisible for 15 seconds after Hacking`,
|
upgrade_OnHackInvis: `Invisible durante 15 segundos después de hackear`,
|
||||||
|
|
||||||
damageType_Electricity: `Eletricidade`,
|
damageType_Electricity: `Eletricidade`,
|
||||||
damageType_Fire: `Ígneo`,
|
damageType_Fire: `Ígneo`,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user