diff --git a/config-vanilla.json b/config-vanilla.json index 7a72dc10..c7cf618c 100644 --- a/config-vanilla.json +++ b/config-vanilla.json @@ -86,6 +86,8 @@ "bellyOfTheBeastProgressOverride": 0, "eightClaw": false, "eightClawProgressOverride": 0, + "thermiaFracturesOverride": null, + "thermiaFracturesProgressOverride": 0, "eidolonOverride": "", "vallisOverride": "", "duviriOverride": "", diff --git a/package-lock.json b/package-lock.json index 46f51c85..3b2f138b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "ncp": "^2.0.0", "typescript": "^5.5", "undici": "^7.10.0", - "warframe-public-export-plus": "^0.5.81", + "warframe-public-export-plus": "^0.5.82", "warframe-riven-info": "^0.1.2", "winston": "^3.17.0", "winston-daily-rotate-file": "^5.0.0", @@ -5507,9 +5507,9 @@ } }, "node_modules/warframe-public-export-plus": { - "version": "0.5.81", - "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.81.tgz", - "integrity": "sha512-kh3e21XThVDSwdC3TJsMsXZnlZ4B/21HdeJkKcjuTygpCd842EPEKS3lRZl3mpXFOmdha744vAW1XEyHfiLofg==" + "version": "0.5.82", + "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.82.tgz", + "integrity": "sha512-hZa9KpMDA2wy0Hn03y9Nfyzbjxer1I6Rvb52b363uzrqS0cvDO56rhiDo71JbraeV34qF6yo+Vca1zwFmw2srA==" }, "node_modules/warframe-riven-info": { "version": "0.1.2", diff --git a/package.json b/package.json index 8b758bcc..f7617ec7 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "ncp": "^2.0.0", "typescript": "^5.5", "undici": "^7.10.0", - "warframe-public-export-plus": "^0.5.81", + "warframe-public-export-plus": "^0.5.82", "warframe-riven-info": "^0.1.2", "winston": "^3.17.0", "winston-daily-rotate-file": "^5.0.0", diff --git a/src/controllers/api/entratiLabConquestModeController.ts b/src/controllers/api/entratiLabConquestModeController.ts index e5b6c818..c16595ee 100644 --- a/src/controllers/api/entratiLabConquestModeController.ts +++ b/src/controllers/api/entratiLabConquestModeController.ts @@ -1,6 +1,6 @@ import { toMongoDate } from "@/src/helpers/inventoryHelpers"; import { getJSONfromString } from "@/src/helpers/stringHelpers"; -import { getInventory } from "@/src/services/inventoryService"; +import { getInventory, updateEntratiVault } from "@/src/services/inventoryService"; import { getAccountIdForRequest } from "@/src/services/loginService"; import { RequestHandler } from "express"; @@ -11,26 +11,7 @@ export const entratiLabConquestModeController: RequestHandler = async (req, res) "EntratiVaultCountResetDate EntratiVaultCountLastPeriod EntratiLabConquestUnlocked EchoesHexConquestUnlocked EchoesHexConquestActiveFrameVariants EchoesHexConquestActiveStickers EntratiLabConquestActiveFrameVariants EntratiLabConquestCacheScoreMission EchoesHexConquestCacheScoreMission" ); const body = getJSONfromString(String(req.body)); - if (!inventory.EntratiVaultCountResetDate || Date.now() >= inventory.EntratiVaultCountResetDate.getTime()) { - const EPOCH = 1734307200 * 1000; // Mondays, amirite? - const day = Math.trunc((Date.now() - EPOCH) / 86400000); - const week = Math.trunc(day / 7); - const weekStart = EPOCH + week * 604800000; - const weekEnd = weekStart + 604800000; - inventory.EntratiVaultCountLastPeriod = 0; - inventory.EntratiVaultCountResetDate = new Date(weekEnd); - if (inventory.EntratiLabConquestUnlocked) { - inventory.EntratiLabConquestUnlocked = 0; - inventory.EntratiLabConquestCacheScoreMission = 0; - inventory.EntratiLabConquestActiveFrameVariants = []; - } - if (inventory.EchoesHexConquestUnlocked) { - inventory.EchoesHexConquestUnlocked = 0; - inventory.EchoesHexConquestCacheScoreMission = 0; - inventory.EchoesHexConquestActiveFrameVariants = []; - inventory.EchoesHexConquestActiveStickers = []; - } - } + updateEntratiVault(inventory); if (body.BuyMode) { inventory.EntratiVaultCountLastPeriod! += 2; if (body.IsEchoesDeepArchemedea) { @@ -51,7 +32,7 @@ export const entratiLabConquestModeController: RequestHandler = async (req, res) } await inventory.save(); res.json({ - EntratiVaultCountResetDate: toMongoDate(inventory.EntratiVaultCountResetDate), + EntratiVaultCountResetDate: toMongoDate(inventory.EntratiVaultCountResetDate!), EntratiVaultCountLastPeriod: inventory.EntratiVaultCountLastPeriod, EntratiLabConquestUnlocked: inventory.EntratiLabConquestUnlocked, EntratiLabConquestCacheScoreMission: inventory.EntratiLabConquestCacheScoreMission, diff --git a/src/controllers/api/saveDialogueController.ts b/src/controllers/api/saveDialogueController.ts index fa5a89cb..dcbd04e2 100644 --- a/src/controllers/api/saveDialogueController.ts +++ b/src/controllers/api/saveDialogueController.ts @@ -20,8 +20,6 @@ export const saveDialogueController: RequestHandler = async (req, res) => { const tomorrowAt0Utc = config.noKimCooldowns ? Date.now() : (Math.trunc(Date.now() / 86400_000) + 1) * 86400_000; - inventory.DialogueHistory ??= {}; - inventory.DialogueHistory.Dialogues ??= []; const dialogue = getDialogue(inventory, request.DialogueName); dialogue.Rank = request.Rank; dialogue.Chemistry += request.Chemistry; diff --git a/src/controllers/custom/completeAllMissionsController.ts b/src/controllers/custom/completeAllMissionsController.ts index 66ac3c13..0d53135f 100644 --- a/src/controllers/custom/completeAllMissionsController.ts +++ b/src/controllers/custom/completeAllMissionsController.ts @@ -35,6 +35,7 @@ export const completeAllMissionsController: RequestHandler = async (req, res) => await handleStoreItemAcquisition(reward.StoreItem, inventory, reward.ItemCount, undefined, true); } addString(inventory.NodeIntrosCompleted, "TeshinHardModeUnlocked"); + addString(inventory.NodeIntrosCompleted, "CetusSyndicate_IntroJob"); await inventory.save(); res.end(); }; diff --git a/src/services/configService.ts b/src/services/configService.ts index 7d6a8337..1ecba208 100644 --- a/src/services/configService.ts +++ b/src/services/configService.ts @@ -98,6 +98,8 @@ export interface IConfig { bellyOfTheBeastProgressOverride?: number; eightClaw?: boolean; eightClawProgressOverride?: number; + thermiaFracturesOverride?: boolean; + thermiaFracturesProgressOverride?: number; eidolonOverride?: string; vallisOverride?: string; duviriOverride?: string; diff --git a/src/services/importService.ts b/src/services/importService.ts index 3337a243..518dacf8 100644 --- a/src/services/importService.ts +++ b/src/services/importService.ts @@ -444,7 +444,7 @@ export const importLoadOutPresets = (db: ILoadoutDatabase, client: ILoadOutPrese db.NORMAL_PVP = client.NORMAL_PVP.map(convertLoadOutConfig); db.LUNARO = client.LUNARO.map(convertLoadOutConfig); db.OPERATOR = client.OPERATOR.map(convertLoadOutConfig); - db.GEAR = client.GEAR.map(convertLoadOutConfig); + db.GEAR = client.GEAR?.map(convertLoadOutConfig); db.KDRIVE = client.KDRIVE.map(convertLoadOutConfig); db.DATAKNIFE = client.DATAKNIFE.map(convertLoadOutConfig); db.MECH = client.MECH.map(convertLoadOutConfig); diff --git a/src/services/inventoryService.ts b/src/services/inventoryService.ts index c6f16b08..bf679f1b 100644 --- a/src/services/inventoryService.ts +++ b/src/services/inventoryService.ts @@ -2286,11 +2286,13 @@ export const cleanupInventory = (inventory: TInventoryDatabaseDocument): void => }; export const getDialogue = (inventory: TInventoryDatabaseDocument, dialogueName: string): IDialogueDatabase => { - let dialogue = inventory.DialogueHistory!.Dialogues!.find(x => x.DialogueName == dialogueName); + inventory.DialogueHistory ??= {}; + inventory.DialogueHistory.Dialogues ??= []; + let dialogue = inventory.DialogueHistory.Dialogues.find(x => x.DialogueName == dialogueName); if (!dialogue) { dialogue = - inventory.DialogueHistory!.Dialogues![ - inventory.DialogueHistory!.Dialogues!.push({ + inventory.DialogueHistory.Dialogues[ + inventory.DialogueHistory.Dialogues.push({ Rank: 0, Chemistry: 0, AvailableDate: new Date(0), @@ -2449,3 +2451,26 @@ export const giveNemesisPetRecipe = ( export const getEffectiveAvatarImageType = (inventory: TInventoryDatabaseDocument): string => { return inventory.ActiveAvatarImageType ?? "/Lotus/Types/StoreItems/AvatarImages/AvatarImageDefault"; }; + +export const updateEntratiVault = (inventory: TInventoryDatabaseDocument): void => { + if (!inventory.EntratiVaultCountResetDate || Date.now() >= inventory.EntratiVaultCountResetDate.getTime()) { + const EPOCH = 1734307200 * 1000; // Mondays, amirite? + const day = Math.trunc((Date.now() - EPOCH) / 86400000); + const week = Math.trunc(day / 7); + const weekStart = EPOCH + week * 604800000; + const weekEnd = weekStart + 604800000; + inventory.EntratiVaultCountLastPeriod = 0; + inventory.EntratiVaultCountResetDate = new Date(weekEnd); + if (inventory.EntratiLabConquestUnlocked) { + inventory.EntratiLabConquestUnlocked = 0; + inventory.EntratiLabConquestCacheScoreMission = 0; + inventory.EntratiLabConquestActiveFrameVariants = []; + } + if (inventory.EchoesHexConquestUnlocked) { + inventory.EchoesHexConquestUnlocked = 0; + inventory.EchoesHexConquestCacheScoreMission = 0; + inventory.EchoesHexConquestActiveFrameVariants = []; + inventory.EchoesHexConquestActiveStickers = []; + } + } +}; diff --git a/src/services/missionInventoryUpdateService.ts b/src/services/missionInventoryUpdateService.ts index 28e40ec5..bccbed42 100644 --- a/src/services/missionInventoryUpdateService.ts +++ b/src/services/missionInventoryUpdateService.ts @@ -39,6 +39,7 @@ import { giveNemesisPetRecipe, giveNemesisWeaponRecipe, updateCurrency, + updateEntratiVault, updateSyndicate } from "@/src/services/inventoryService"; import { updateQuestKey } from "@/src/services/questService"; @@ -640,7 +641,7 @@ export const addMissionInventoryUpdates = async ( } const currentNode = inventoryUpdates.RewardInfo!.node; - let currentMissionKey; + let currentMissionKey: string | undefined; if (currentNode == goal.Node) { currentMissionKey = goal.MissionKeyName; } else if (goal.ConcurrentNodes && goal.ConcurrentMissionKeyNames) { @@ -651,15 +652,15 @@ export const addMissionInventoryUpdates = async ( } } } - if (currentMissionKey && currentMissionKey in goalMessagesByKey) { - let countBeforeUpload = goalProgress?.Count ?? 0; - let totalCount = countBeforeUpload + uploadProgress.Count; - if (goal.Best) { - countBeforeUpload = goalProgress?.Best ?? 0; - totalCount = uploadProgress.Best; - } - let reward; + const rewards = []; + let countBeforeUpload = goalProgress?.Count ?? 0; + let totalCount = countBeforeUpload + uploadProgress.Count; + if (goal.Best) { + countBeforeUpload = goalProgress?.Best ?? 0; + totalCount = uploadProgress.Best; + } + { if (goal.InterimGoals && goal.InterimRewards) { for (let i = 0; i < goal.InterimGoals.length; i++) { if ( @@ -668,70 +669,95 @@ export const addMissionInventoryUpdates = async ( (!goalProgress || countBeforeUpload < goal.InterimGoals[i]) && goal.InterimRewards[i] ) { - reward = goal.InterimRewards[i]; + rewards.push(goal.InterimRewards[i]); break; } } } if ( - !reward && goal.Goal && goal.Goal <= totalCount && (!goalProgress || countBeforeUpload < goal.Goal) && goal.Reward ) { - reward = goal.Reward; + rewards.push(goal.Reward); } if ( - !reward && goal.BonusGoal && goal.BonusGoal <= totalCount && (!goalProgress || countBeforeUpload < goal.BonusGoal) && goal.BonusReward ) { - reward = goal.BonusReward; - } - if (reward) { - if (currentMissionKey in goalMessagesByKey) { - // Send reward via inbox - const info = goalMessagesByKey[currentMissionKey]; - const message: IMessageCreationTemplate = { - sndr: info.sndr, - msg: info.msg, - sub: info.sub, - icon: info.icon, - highPriority: true - }; - - if (reward.items) { - message.att = reward.items.map(x => (isStoreItem(x) ? fromStoreItem(x) : x)); - } - if (reward.countedItems) { - message.countedAtt = reward.countedItems; - } - if (reward.credits) { - message.RegularCredits = reward.credits; - } - if (info.arg) { - const args: Record = { - PLAYER_NAME: account.DisplayName, - CREDIT_REWARD: reward.credits ?? 0 - }; - - info.arg.forEach(key => { - const value = args[key]; - if (value) { - message.arg ??= []; - message.arg.push({ Key: key, Tag: value }); - } - }); - } - - await createMessage(inventory.accountOwnerId, [message]); - } + rewards.push(goal.BonusReward); } } + const messages: IMessageCreationTemplate[] = []; + const infos: { + sndr: string; + msg: string; + sub: string; + icon: string; + arg?: string[]; + }[] = []; + + { + if (currentMissionKey && currentMissionKey in goalMessagesByKey) { + infos.push(goalMessagesByKey[currentMissionKey]); + } else if (goal.Tag in goalMessagesByTag) { + const combinedGoals = [...(goal.InterimGoals || []), goal.Goal, goal.BonusGoal]; + combinedGoals.forEach((n, i) => { + if (n !== undefined && n > countBeforeUpload && n <= totalCount) { + infos.push(goalMessagesByTag[goal.Tag][i]); + } + }); + } + } + + for (let i = 0; i < rewards.length; i++) { + if (infos[i]) { + const info = infos[i]; + const reward = rewards[i]; + const message: IMessageCreationTemplate = { + sndr: info.sndr, + msg: info.msg, + sub: info.sub, + icon: info.icon, + highPriority: true + }; + if (reward.items) { + message.att = reward.items.map(x => (isStoreItem(x) ? fromStoreItem(x) : x)); + } + if (reward.countedItems) { + message.countedAtt = reward.countedItems; + } + if (reward.credits) { + message.RegularCredits = reward.credits; + } + if (info.arg) { + const args: Record = { + PLAYER_NAME: account.DisplayName, + CREDIT_REWARD: reward.credits ?? 0 + }; + + for (let j = 0; j < info.arg.length; j++) { + const key = info.arg[j]; + const value = args[key]; + if (value) { + message.arg ??= []; + message.arg.push({ + Key: key, + Tag: value + }); + } + } + } + messages.push(message); + } + } + + if (messages.length > 0) await createMessage(inventory.accountOwnerId, messages); + if (goalProgress) { goalProgress.Best = Math.max(goalProgress.Best!, uploadProgress.Best); goalProgress.Count += uploadProgress.Count; @@ -1059,6 +1085,22 @@ const droptableAliases: Record = { "/Lotus/Types/DropTables/WF1999DropTables/LasrianTankHardModeDropTable" }; +const isEligibleForCreditReward = (rewardInfo: IRewardInfo, missions: IMission, node: IRegion): boolean => { + // (E)SO should not give credits for only completing zone 1, in which case it has no rewardQualifications (https://onlyg.it/OpenWF/SpaceNinjaServer/issues/1823) + if (getRotations(rewardInfo).length == 0) { + return missions.Tag == "SolNode720"; // Netracells don't use rewardQualifications but probably should give credits anyway + } + // The rest here might not be needed anymore, but just to be sure we don't give undue credits... + return ( + node.missionIndex != 23 && // junction + node.missionIndex != 28 && // open world + missions.Tag != "SolNode761" && // the index + missions.Tag != "SolNode762" && // the index + missions.Tag != "SolNode763" && // the index + missions.Tag != "CrewBattleNode556" // free flight + ); +}; + //TODO: return type of partial missioninventoryupdate response export const addMissionRewards = async ( account: TAccountDocument, @@ -1151,15 +1193,7 @@ export const addMissionRewards = async ( const node = ExportRegions[missions.Tag]; //node based credit rewards for mission completion - if ( - node.missionIndex != 23 && // junction - node.missionIndex != 28 && // open world - missions.Tag != "SolNode761" && // the index - missions.Tag != "SolNode762" && // the index - missions.Tag != "SolNode763" && // the index - missions.Tag != "CrewBattleNode556" && // free flight - getRotations(rewardInfo).length > 0 // (E)SO should not give credits for only completing zone 1, in which case it has no rewardQualifications (https://onlyg.it/OpenWF/SpaceNinjaServer/issues/1823) - ) { + if (isEligibleForCreditReward(rewardInfo, missions, node)) { const levelCreditReward = getLevelCreditRewards(node); missionCompletionCredits += levelCreditReward; logger.debug(`levelCreditReward ${levelCreditReward}`); @@ -1189,6 +1223,12 @@ export const addMissionRewards = async ( } ]); } + + // Consume netracells search pulse. Moved here to only cover successful completions. Discussed in https://onlyg.it/OpenWF/SpaceNinjaServer/issues/2673 + if (missions.Tag == "SolNode720") { + updateEntratiVault(inventory); + inventory.EntratiVaultCountLastPeriod! += 1; + } } if (rewardInfo.useVaultManifest) { @@ -1352,7 +1392,7 @@ export const addMissionRewards = async ( } } } else { - logger.error(`unknown droptable ${si.DropTable} for DROP_BLUEPRINT`); + logger.error(`unknown droptable ${si.DropTable} for DROP_MISC_ITEM`); } } } @@ -2617,3 +2657,38 @@ const goalMessagesByKey: Record = { + HeatFissure: [ + { + sndr: "/Lotus/Language/Npcs/Eudico", + msg: "/Lotus/Language/Messages/OrbHeistEventRewardAInboxMessageBody", + sub: "/Lotus/Language/Messages/OrbHeistEventRewardAInboxMessageTitle", + icon: "/Lotus/Interface/Icons/Npcs/Eudico.png" + }, + { + sndr: "/Lotus/Language/Npcs/Eudico", + msg: "/Lotus/Language/Messages/OrbHeistEventRewardBInboxMessageBody", + sub: "/Lotus/Language/Messages/OrbHeistEventRewardBInboxMessageTitle", + icon: "/Lotus/Interface/Icons/Npcs/Eudico.png" + }, + { + sndr: "/Lotus/Language/Npcs/Eudico", + msg: "/Lotus/Language/Messages/OrbHeistEventRewardCInboxMessageBody", + sub: "/Lotus/Language/Messages/OrbHeistEventRewardCInboxMessageTitle", + icon: "/Lotus/Interface/Icons/Npcs/Eudico.png" + }, + { + sndr: "/Lotus/Language/Npcs/Eudico", + msg: "/Lotus/Language/Messages/OrbHeistEventRewardDInboxMessageBody", + sub: "/Lotus/Language/Messages/OrbHeistEventRewardDInboxMessageTitle", + icon: "/Lotus/Interface/Icons/Npcs/Eudico.png" + }, + { + sndr: "/Lotus/Language/Npcs/Eudico", + msg: "/Lotus/Language/Messages/OrbHeistEventRewardEInboxMessageBody", + sub: "/Lotus/Language/Messages/OrbHeistEventRewardEInboxMessageTitle", + icon: "/Lotus/Interface/Icons/Npcs/Eudico.png" + } + ] +}; diff --git a/src/services/worldStateService.ts b/src/services/worldStateService.ts index 167fd62c..8a0c8961 100644 --- a/src/services/worldStateService.ts +++ b/src/services/worldStateService.ts @@ -2629,6 +2629,87 @@ export const getWorldState = (buildLabel?: string): IWorldState => { ); } + const thermiaFracturesCycleDay = day % 32; + const isThermiaFracturesActive = thermiaFracturesCycleDay < 14; + if (config.worldState?.thermiaFracturesOverride ?? isThermiaFracturesActive) { + const activeStartDay = day - thermiaFracturesCycleDay; + + const count = config.worldState?.thermiaFracturesProgressOverride ?? 0; + const activation = config.worldState?.thermiaFracturesOverride ? 1740416400000 : getSortieTime(activeStartDay); + const expiry = config.worldState?.thermiaFracturesOverride ? 2000000000000 : getSortieTime(activeStartDay + 14); + + worldState.Goals.push({ + _id: { $oid: "5c7cb0d00000000000000000" }, + Activation: { $date: { $numberLong: activation.toString() } }, + Expiry: { $date: { $numberLong: expiry.toString() } }, + Node: "SolNode129", + ScoreVar: "FissuresClosed", + ScoreLocTag: "/Lotus/Language/G1Quests/HeatFissuresEventScore", + Count: count, + HealthPct: count / 100, + Regions: [1], + Desc: "/Lotus/Language/G1Quests/HeatFissuresEventName", + ToolTip: "/Lotus/Language/G1Quests/HeatFissuresEventDesc", + OptionalInMission: true, + Tag: "HeatFissure", + UpgradeIds: [{ $oid: "5c81cefa4c4566791728eaa7" }, { $oid: "5c81cefa4c4566791728eaa6" }], + Personal: true, + Community: true, + Goal: 100, + Reward: { + items: ["/Lotus/StoreItems/Weapons/Corpus/LongGuns/CrpBFG/Vandal/VandalCrpBFG"] + }, + InterimGoals: [5, 25, 50, 75], + InterimRewards: [ + { items: ["/Lotus/StoreItems/Upgrades/Skins/Clan/OrbBadgeItem"] }, + { + items: [ + "/Lotus/StoreItems/Upgrades/Mods/DualSource/Shotgun/ShotgunMedicMod", + "/Lotus/StoreItems/Upgrades/Mods/DualSource/Rifle/SerratedRushMod" + ] + }, + { + items: [ + "/Lotus/StoreItems/Upgrades/Mods/DualSource/Pistol/MultishotDodgeMod", + "/Lotus/StoreItems/Upgrades/Mods/DualSource/Melee/CritDamageChargeSpeedMod" + ] + }, + { items: ["/Lotus/StoreItems/Upgrades/Skins/Sigils/OrbSigil"] } + ] + }); + worldState.NodeOverrides.push({ + _id: { $oid: "5c7cb0d00000000000000000" }, + Activation: { $date: { $numberLong: activation.toString() } }, + Expiry: { $date: { $numberLong: expiry.toString() } }, + Node: "SolNode129", + Faction: "FC_CORPUS", + CustomNpcEncounters: ["/Lotus/Types/Gameplay/Venus/Encounters/Heists/ExploiterHeistFissure"] + }); + if (count >= 35) { + worldState.GlobalUpgrades.push({ + _id: { $oid: "5c81cefa4c4566791728eaa6" }, + Activation: { $date: { $numberLong: activation.toString() } }, + ExpiryDate: { $date: { $numberLong: expiry.toString() } }, + UpgradeType: "GAMEPLAY_MONEY_REWARD_AMOUNT", + OperationType: "MULTIPLY", + Value: 2, + Nodes: ["SolNode129"] + }); + } + // Not sure about that + if (count == 100) { + worldState.GlobalUpgrades.push({ + _id: { $oid: "5c81cefa4c4566791728eaa7" }, + Activation: { $date: { $numberLong: activation.toString() } }, + ExpiryDate: { $date: { $numberLong: expiry.toString() } }, + UpgradeType: "GAMEPLAY_PICKUP_AMOUNT", + OperationType: "MULTIPLY", + Value: 2, + Nodes: ["SolNode129"] + }); + } + } + // Nightwave Challenges const nightwaveSyndicateTag = getNightwaveSyndicateTag(buildLabel); if (nightwaveSyndicateTag) { @@ -2727,7 +2808,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => { : Date.UTC( date.getUTCFullYear(), date.getUTCMonth(), - date.getUTCDate() + (day - ghoulsCycleDay + 17) + date.getUTCDate() + activeStartDay ).toString() } }, @@ -2738,7 +2819,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => { : Date.UTC( date.getUTCFullYear(), date.getUTCMonth(), - date.getUTCDate() + (day - ghoulsCycleDay + 21) + date.getUTCDate() + activeEndDay ).toString() } }, diff --git a/src/types/saveLoadoutTypes.ts b/src/types/saveLoadoutTypes.ts index 9e8e5bf9..33ff9708 100644 --- a/src/types/saveLoadoutTypes.ts +++ b/src/types/saveLoadoutTypes.ts @@ -79,7 +79,7 @@ export interface ILoadoutDatabase { NORMAL_PVP: ILoadoutConfigDatabase[]; LUNARO: ILoadoutConfigDatabase[]; OPERATOR: ILoadoutConfigDatabase[]; - GEAR: ILoadoutConfigDatabase[]; + GEAR?: ILoadoutConfigDatabase[]; KDRIVE: ILoadoutConfigDatabase[]; DATAKNIFE: ILoadoutConfigDatabase[]; MECH: ILoadoutConfigDatabase[]; @@ -96,7 +96,7 @@ export interface ILoadOutPresets { ARCHWING: ILoadoutConfigClient[]; SENTINEL: ILoadoutConfigClient[]; OPERATOR: ILoadoutConfigClient[]; - GEAR: ILoadoutConfigClient[]; + GEAR?: ILoadoutConfigClient[]; KDRIVE: ILoadoutConfigClient[]; DATAKNIFE: ILoadoutConfigClient[]; MECH: ILoadoutConfigClient[]; diff --git a/src/types/worldStateTypes.ts b/src/types/worldStateTypes.ts index fbb3547f..40463345 100644 --- a/src/types/worldStateTypes.ts +++ b/src/types/worldStateTypes.ts @@ -43,7 +43,7 @@ export interface IGoal { Count?: number; HealthPct?: number; - Icon: string; + Icon?: string; Desc: string; ToolTip?: string; Faction?: string; @@ -94,6 +94,9 @@ export interface IGoal { MissionKeyRotation?: string[]; MissionKeyRotationInterval?: number; + OptionalInMission?: boolean; + UpgradeIds?: IOid[]; + NightLevel?: string; } @@ -128,8 +131,9 @@ export interface IGlobalUpgrade { UpgradeType: string; OperationType: string; Value: number; - LocalizeTag: string; - LocalizeDescTag: string; + LocalizeTag?: string; + LocalizeDescTag?: string; + Nodes?: string[]; } export interface IInvasion { @@ -183,7 +187,7 @@ export interface INodeOverride { Seed?: number; LevelOverride?: string; Faction?: string; - CustomNpcEncounters?: string; + CustomNpcEncounters?: string[]; } export interface ISortie { diff --git a/static/webui/index.html b/static/webui/index.html index 83730e06..fc60a986 100644 --- a/static/webui/index.html +++ b/static/webui/index.html @@ -1103,6 +1103,25 @@ +
+
+ + +
+
+
+ +
+ + +
+
+
+