From 2569e59cfffdd7401a2e7ed9a2e5642962a2fbe0 Mon Sep 17 00:00:00 2001 From: Sainan Date: Sat, 15 Mar 2025 12:06:24 +0100 Subject: [PATCH 1/3] use NextRefill to handle daily reset --- src/controllers/api/inventoryController.ts | 16 +++++----------- src/models/inventoryModels/inventoryModel.ts | 5 ++++- src/models/loginModel.ts | 1 - src/types/inventoryTypes/inventoryTypes.ts | 4 +++- src/types/loginTypes.ts | 1 - 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/controllers/api/inventoryController.ts b/src/controllers/api/inventoryController.ts index 53d554c7..8316b9cb 100644 --- a/src/controllers/api/inventoryController.ts +++ b/src/controllers/api/inventoryController.ts @@ -1,5 +1,5 @@ import { RequestHandler } from "express"; -import { getAccountForRequest } from "@/src/services/loginService"; +import { getAccountIdForRequest } from "@/src/services/loginService"; import { Inventory, TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel"; import { config } from "@/src/services/configService"; import allDialogue from "@/static/fixed_responses/allDialogue.json"; @@ -17,9 +17,9 @@ import { applyCheatsToInfestedFoundry, handleSubsumeCompletion } from "./infeste import { allDailyAffiliationKeys, createLibraryDailyTask } from "@/src/services/inventoryService"; export const inventoryController: RequestHandler = async (request, response) => { - const account = await getAccountForRequest(request); + const accountId = await getAccountIdForRequest(request); - const inventory = await Inventory.findOne({ accountOwnerId: account._id.toString() }); + const inventory = await Inventory.findOne({ accountOwnerId: accountId }); if (!inventory) { response.status(400).json({ error: "inventory was undefined" }); @@ -27,11 +27,7 @@ export const inventoryController: RequestHandler = async (request, response) => } // Handle daily reset - const today: number = Math.trunc(new Date().getTime() / 86400000); - if (account.LastLoginDay != today) { - account.LastLoginDay = today; - await account.save(); - + if (!inventory.NextRefill || Date.now() >= inventory.NextRefill.getTime()) { for (const key of allDailyAffiliationKeys) { inventory[key] = 16000 + inventory.PlayerLevel * 500; } @@ -39,6 +35,7 @@ export const inventoryController: RequestHandler = async (request, response) => inventory.LibraryAvailableDailyTaskInfo = createLibraryDailyTask(); + inventory.NextRefill = new Date((Math.trunc(Date.now() / 86400000) + 1) * 86400000); await inventory.save(); } @@ -219,9 +216,6 @@ export const getInventoryResponse = async ( applyCheatsToInfestedFoundry(inventoryResponse.InfestedFoundry); } - // Fix for #380 - inventoryResponse.NextRefill = { $date: { $numberLong: "9999999999999" } }; - // This determines if the "void fissures" tab is shown in navigation. inventoryResponse.HasOwnedVoidProjectionsPreviously = true; diff --git a/src/models/inventoryModels/inventoryModel.ts b/src/models/inventoryModels/inventoryModel.ts index c7446f41..d16eab27 100644 --- a/src/models/inventoryModels/inventoryModel.ts +++ b/src/models/inventoryModels/inventoryModel.ts @@ -1360,7 +1360,7 @@ const inventorySchema = new Schema( //https://warframe.fandom.com/wiki/Helminth InfestedFoundry: infestedFoundrySchema, - NextRefill: Schema.Types.Mixed, // Date, convert to IMongoDate + NextRefill: { type: Date, default: undefined }, //Purchase this new permanent skin from the Lotus customization options in Personal Quarters located in your Orbiter. //https://warframe.fandom.com/wiki/Lotus#The_New_War @@ -1435,6 +1435,9 @@ inventorySchema.set("toJSON", { if (inventoryDatabase.BlessingCooldown) { inventoryResponse.BlessingCooldown = toMongoDate(inventoryDatabase.BlessingCooldown); } + if (inventoryDatabase.NextRefill) { + inventoryResponse.NextRefill = toMongoDate(inventoryDatabase.NextRefill); + } } }); diff --git a/src/models/loginModel.ts b/src/models/loginModel.ts index 75a12356..47cbe8ff 100644 --- a/src/models/loginModel.ts +++ b/src/models/loginModel.ts @@ -21,7 +21,6 @@ const databaseAccountSchema = new Schema( TrackedSettings: { type: [String], default: [] }, Nonce: { type: Number, default: 0 }, Dropped: Boolean, - LastLoginDay: { type: Number }, LatestEventMessageDate: { type: Date, default: 0 } }, opts diff --git a/src/types/inventoryTypes/inventoryTypes.ts b/src/types/inventoryTypes/inventoryTypes.ts index 6fff6735..70d070b0 100644 --- a/src/types/inventoryTypes/inventoryTypes.ts +++ b/src/types/inventoryTypes/inventoryTypes.ts @@ -42,6 +42,7 @@ export interface IInventoryDatabase | "PendingCoupon" | "Drones" | "RecentVendorPurchases" + | "NextRefill" | TEquipmentKey >, InventoryDatabaseEquipment { @@ -69,6 +70,7 @@ export interface IInventoryDatabase PendingCoupon?: IPendingCouponDatabase; Drones: IDroneDatabase[]; RecentVendorPurchases?: IRecentVendorPurchaseDatabase[]; + NextRefill?: Date; } export interface IQuestKeyDatabase { @@ -307,7 +309,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu UseAdultOperatorLoadout?: boolean; NemesisAbandonedRewards: string[]; LastInventorySync: IOid; - NextRefill: IMongoDate; // Next time argon crystals will have a decay tick + NextRefill?: IMongoDate; FoundToday?: IMiscItem[]; // for Argon Crystals CustomMarkers?: ICustomMarkers[]; ActiveLandscapeTraps: any[]; diff --git a/src/types/loginTypes.ts b/src/types/loginTypes.ts index 108b0417..0aaf2eed 100644 --- a/src/types/loginTypes.ts +++ b/src/types/loginTypes.ts @@ -15,7 +15,6 @@ export interface IDatabaseAccount extends IAccountAndLoginResponseCommons { email: string; password: string; Dropped?: boolean; - LastLoginDay?: number; LatestEventMessageDate: Date; } -- 2.47.2 From 449690cdac0a2d3f1903f0024eae257dad8e5503 Mon Sep 17 00:00:00 2001 From: Sainan Date: Sat, 15 Mar 2025 13:18:48 +0100 Subject: [PATCH 2/3] feat: argon crystal decay --- src/controllers/api/inventoryController.ts | 37 +++++++++++++++++++- src/models/inventoryModels/inventoryModel.ts | 3 +- src/services/inventoryService.ts | 16 +++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/controllers/api/inventoryController.ts b/src/controllers/api/inventoryController.ts index 8316b9cb..070a074d 100644 --- a/src/controllers/api/inventoryController.ts +++ b/src/controllers/api/inventoryController.ts @@ -14,7 +14,8 @@ import { ExportVirtuals } from "warframe-public-export-plus"; import { applyCheatsToInfestedFoundry, handleSubsumeCompletion } from "./infestedFoundryController"; -import { allDailyAffiliationKeys, createLibraryDailyTask } from "@/src/services/inventoryService"; +import { addMiscItems, allDailyAffiliationKeys, createLibraryDailyTask } from "@/src/services/inventoryService"; +import { logger } from "@/src/utils/logger"; export const inventoryController: RequestHandler = async (request, response) => { const accountId = await getAccountIdForRequest(request); @@ -35,6 +36,40 @@ export const inventoryController: RequestHandler = async (request, response) => inventory.LibraryAvailableDailyTaskInfo = createLibraryDailyTask(); + if (inventory.NextRefill) { + const lastLoginDay = Math.trunc(inventory.NextRefill.getTime() / 86400000) - 1; + const today = Math.trunc(Date.now() / 86400000); + const daysPassed = today - lastLoginDay; + for (let i = 0; i != daysPassed; ++i) { + const numArgonCrystals = + inventory.MiscItems.find(x => x.ItemType == "/Lotus/Types/Items/MiscItems/ArgonCrystal") + ?.ItemCount ?? 0; + if (numArgonCrystals == 0) { + break; + } + const numStableArgonCrystals = + inventory.FoundToday?.find(x => x.ItemType == "/Lotus/Types/Items/MiscItems/ArgonCrystal") + ?.ItemCount ?? 0; + const numDecayingArgonCrystals = numArgonCrystals - numStableArgonCrystals; + const numDecayingArgonCrystalsToRemove = Math.ceil(numDecayingArgonCrystals / 2); + logger.debug(`ticking argon crystals for day ${i + 1} of ${daysPassed}`, { + numArgonCrystals, + numStableArgonCrystals, + numDecayingArgonCrystals, + numDecayingArgonCrystalsToRemove + }); + // Remove half of owned decaying argon crystals + addMiscItems(inventory, [ + { + ItemType: "/Lotus/Types/Items/MiscItems/ArgonCrystal", + ItemCount: numDecayingArgonCrystalsToRemove * -1 + } + ]); + // All stable argon crystals are now decaying + inventory.FoundToday = undefined; + } + } + inventory.NextRefill = new Date((Math.trunc(Date.now() / 86400000) + 1) * 86400000); await inventory.save(); } diff --git a/src/models/inventoryModels/inventoryModel.ts b/src/models/inventoryModels/inventoryModel.ts index d16eab27..c0bdcb58 100644 --- a/src/models/inventoryModels/inventoryModel.ts +++ b/src/models/inventoryModels/inventoryModel.ts @@ -1161,7 +1161,8 @@ const inventorySchema = new Schema( ChallengeProgress: [challengeProgressSchema], //Account Item like Ferrite,Form,Kuva etc - MiscItems: [typeCountSchema], + MiscItems: { type: [typeCountSchema], default: [] }, + FoundToday: { type: [typeCountSchema], default: undefined }, //Non Upgrade Mods Example:I have 999 item WeaponElectricityDamageMod (only "ItemCount"+"ItemType") RawUpgrades: [RawUpgrades], diff --git a/src/services/inventoryService.ts b/src/services/inventoryService.ts index 42e0fa66..cac1254d 100644 --- a/src/services/inventoryService.ts +++ b/src/services/inventoryService.ts @@ -1045,6 +1045,22 @@ export const addMiscItems = (inventory: TInventoryDatabaseDocument, itemsArray: } MiscItems[itemIndex].ItemCount += ItemCount; + + if (ItemType == "/Lotus/Types/Items/MiscItems/ArgonCrystal") { + inventory.FoundToday ??= []; + let foundTodayIndex = inventory.FoundToday.findIndex(x => x.ItemType == ItemType); + if (foundTodayIndex == -1) { + foundTodayIndex = inventory.FoundToday.push({ ItemType, ItemCount: 0 }) - 1; + } + inventory.FoundToday[foundTodayIndex].ItemCount += ItemCount; + if (inventory.FoundToday[foundTodayIndex].ItemCount <= 0) { + inventory.FoundToday.splice(foundTodayIndex, 1); + } + if (inventory.FoundToday.length == 0) { + inventory.FoundToday = undefined; + } + } + if (MiscItems[itemIndex].ItemCount == 0) { MiscItems.splice(itemIndex, 1); } else if (MiscItems[itemIndex].ItemCount <= 0) { -- 2.47.2 From 8358b4f7b539609d345f95b3a6c1e7444989ae7a Mon Sep 17 00:00:00 2001 From: Sainan Date: Sat, 15 Mar 2025 13:36:17 +0100 Subject: [PATCH 3/3] feat: noArgonCrystalDecay cheat --- config.json.example | 1 + src/controllers/api/inventoryController.ts | 62 ++++++++++++---------- src/services/configService.ts | 1 + static/webui/index.html | 4 ++ static/webui/translations/de.js | 1 + static/webui/translations/en.js | 1 + static/webui/translations/fr.js | 1 + static/webui/translations/ru.js | 1 + static/webui/translations/zh.js | 1 + 9 files changed, 44 insertions(+), 29 deletions(-) diff --git a/config.json.example b/config.json.example index 85054641..c8a2df6a 100644 --- a/config.json.example +++ b/config.json.example @@ -29,6 +29,7 @@ "unlockExilusEverywhere": false, "unlockArcanesEverywhere": false, "noDailyStandingLimits": false, + "noArgonCrystalDecay": false, "noVendorPurchaseLimits": true, "instantResourceExtractorDrones": false, "noDojoRoomBuildStage": false, diff --git a/src/controllers/api/inventoryController.ts b/src/controllers/api/inventoryController.ts index 070a074d..40d13d4c 100644 --- a/src/controllers/api/inventoryController.ts +++ b/src/controllers/api/inventoryController.ts @@ -37,36 +37,40 @@ export const inventoryController: RequestHandler = async (request, response) => inventory.LibraryAvailableDailyTaskInfo = createLibraryDailyTask(); if (inventory.NextRefill) { - const lastLoginDay = Math.trunc(inventory.NextRefill.getTime() / 86400000) - 1; - const today = Math.trunc(Date.now() / 86400000); - const daysPassed = today - lastLoginDay; - for (let i = 0; i != daysPassed; ++i) { - const numArgonCrystals = - inventory.MiscItems.find(x => x.ItemType == "/Lotus/Types/Items/MiscItems/ArgonCrystal") - ?.ItemCount ?? 0; - if (numArgonCrystals == 0) { - break; - } - const numStableArgonCrystals = - inventory.FoundToday?.find(x => x.ItemType == "/Lotus/Types/Items/MiscItems/ArgonCrystal") - ?.ItemCount ?? 0; - const numDecayingArgonCrystals = numArgonCrystals - numStableArgonCrystals; - const numDecayingArgonCrystalsToRemove = Math.ceil(numDecayingArgonCrystals / 2); - logger.debug(`ticking argon crystals for day ${i + 1} of ${daysPassed}`, { - numArgonCrystals, - numStableArgonCrystals, - numDecayingArgonCrystals, - numDecayingArgonCrystalsToRemove - }); - // Remove half of owned decaying argon crystals - addMiscItems(inventory, [ - { - ItemType: "/Lotus/Types/Items/MiscItems/ArgonCrystal", - ItemCount: numDecayingArgonCrystalsToRemove * -1 - } - ]); - // All stable argon crystals are now decaying + if (config.noArgonCrystalDecay) { inventory.FoundToday = undefined; + } else { + const lastLoginDay = Math.trunc(inventory.NextRefill.getTime() / 86400000) - 1; + const today = Math.trunc(Date.now() / 86400000); + const daysPassed = today - lastLoginDay; + for (let i = 0; i != daysPassed; ++i) { + const numArgonCrystals = + inventory.MiscItems.find(x => x.ItemType == "/Lotus/Types/Items/MiscItems/ArgonCrystal") + ?.ItemCount ?? 0; + if (numArgonCrystals == 0) { + break; + } + const numStableArgonCrystals = + inventory.FoundToday?.find(x => x.ItemType == "/Lotus/Types/Items/MiscItems/ArgonCrystal") + ?.ItemCount ?? 0; + const numDecayingArgonCrystals = numArgonCrystals - numStableArgonCrystals; + const numDecayingArgonCrystalsToRemove = Math.ceil(numDecayingArgonCrystals / 2); + logger.debug(`ticking argon crystals for day ${i + 1} of ${daysPassed}`, { + numArgonCrystals, + numStableArgonCrystals, + numDecayingArgonCrystals, + numDecayingArgonCrystalsToRemove + }); + // Remove half of owned decaying argon crystals + addMiscItems(inventory, [ + { + ItemType: "/Lotus/Types/Items/MiscItems/ArgonCrystal", + ItemCount: numDecayingArgonCrystalsToRemove * -1 + } + ]); + // All stable argon crystals are now decaying + inventory.FoundToday = undefined; + } } } diff --git a/src/services/configService.ts b/src/services/configService.ts index b19ac57e..66c50dda 100644 --- a/src/services/configService.ts +++ b/src/services/configService.ts @@ -55,6 +55,7 @@ interface IConfig { unlockExilusEverywhere?: boolean; unlockArcanesEverywhere?: boolean; noDailyStandingLimits?: boolean; + noArgonCrystalDecay?: boolean; noVendorPurchaseLimits?: boolean; instantResourceExtractorDrones?: boolean; noDojoRoomBuildStage?: boolean; diff --git a/static/webui/index.html b/static/webui/index.html index bd5f13cc..540378d9 100644 --- a/static/webui/index.html +++ b/static/webui/index.html @@ -517,6 +517,10 @@ +
+ + +
diff --git a/static/webui/translations/de.js b/static/webui/translations/de.js index 0d6d4c9f..aefd1f84 100644 --- a/static/webui/translations/de.js +++ b/static/webui/translations/de.js @@ -110,6 +110,7 @@ dict = { cheats_unlockExilusEverywhere: `Exilus-Adapter überall`, cheats_unlockArcanesEverywhere: `Arkana-Adapter überall`, cheats_noDailyStandingLimits: `Kein tägliches Ansehenslimit`, + cheats_noArgonCrystalDecay: `[UNTRANSLATED] No Argon Crystal Decay`, cheats_noVendorPurchaseLimits: `Keine Kaufbeschränkungen bei Händlern`, cheats_instantResourceExtractorDrones: `Sofortige Ressourcen-Extraktor-Drohnen`, cheats_noDojoRoomBuildStage: `Kein Dojo-Raum-Bauvorgang`, diff --git a/static/webui/translations/en.js b/static/webui/translations/en.js index 455ab2e4..b60ba241 100644 --- a/static/webui/translations/en.js +++ b/static/webui/translations/en.js @@ -109,6 +109,7 @@ dict = { cheats_unlockExilusEverywhere: `Exilus Adapters Everywhere`, cheats_unlockArcanesEverywhere: `Arcane Adapters Everywhere`, cheats_noDailyStandingLimits: `No Daily Standing Limits`, + cheats_noArgonCrystalDecay: `No Argon Crystal Decay`, cheats_noVendorPurchaseLimits: `No Vendor Purchase Limits`, cheats_instantResourceExtractorDrones: `Instant Resource Extractor Drones`, cheats_noDojoRoomBuildStage: `No Dojo Room Build Stage`, diff --git a/static/webui/translations/fr.js b/static/webui/translations/fr.js index 9840911a..96b52eaa 100644 --- a/static/webui/translations/fr.js +++ b/static/webui/translations/fr.js @@ -110,6 +110,7 @@ dict = { cheats_unlockExilusEverywhere: `Adaptateurs Exilus partout`, cheats_unlockArcanesEverywhere: `Adaptateur d'Arcanes partout`, cheats_noDailyStandingLimits: `Pas de limite de réputation journalière`, + cheats_noArgonCrystalDecay: `[UNTRANSLATED] No Argon Crystal Decay`, cheats_noVendorPurchaseLimits: `[UNTRANSLATED] No Vendor Purchase Limits`, cheats_instantResourceExtractorDrones: `Ressources de drone d'extraction instantannées`, cheats_noDojoRoomBuildStage: `No Dojo Room Build Stage`, diff --git a/static/webui/translations/ru.js b/static/webui/translations/ru.js index 030c704b..502b84af 100644 --- a/static/webui/translations/ru.js +++ b/static/webui/translations/ru.js @@ -110,6 +110,7 @@ dict = { cheats_unlockExilusEverywhere: `Адаптеры Эксилус везде`, cheats_unlockArcanesEverywhere: `Адаптеры для мистификаторов везде`, cheats_noDailyStandingLimits: `Без ежедневных ограничений репутации`, + cheats_noArgonCrystalDecay: `[UNTRANSLATED] No Argon Crystal Decay`, cheats_noVendorPurchaseLimits: `[UNTRANSLATED] No Vendor Purchase Limits`, cheats_instantResourceExtractorDrones: `Мгновенные Экстракторы Ресурсов`, cheats_noDojoRoomBuildStage: `Мгновенное Строительтво Комнат Додзё`, diff --git a/static/webui/translations/zh.js b/static/webui/translations/zh.js index a783bb04..57207f0a 100644 --- a/static/webui/translations/zh.js +++ b/static/webui/translations/zh.js @@ -110,6 +110,7 @@ dict = { cheats_unlockExilusEverywhere: `全物品自带适配器`, cheats_unlockArcanesEverywhere: `全物品自带赋能适配器`, cheats_noDailyStandingLimits: `无每日声望限制`, + cheats_noArgonCrystalDecay: `[UNTRANSLATED] No Argon Crystal Decay`, cheats_noVendorPurchaseLimits: `[UNTRANSLATED] No Vendor Purchase Limits`, cheats_instantResourceExtractorDrones: `即时资源采集无人机`, cheats_noDojoRoomBuildStage: `无视道场房间建造阶段`, -- 2.47.2