From c7edb08d891616f684f6a9e94e4312e15de4a88c Mon Sep 17 00:00:00 2001 From: Chomp Date: Tue, 10 Dec 2024 13:22:35 +0000 Subject: [PATCH] Updated types and readme --- README.md | 2 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../10ScopesAndTypes/types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ TypeScript/13AddTrader/types/utils/App.d.ts | 2 +- .../13AddTrader/types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../14AfterDBLoadHook/types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../16ImporterUtil/types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../18CustomItemService/types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ TypeScript/1LogToConsole/types/utils/App.d.ts | 2 +- .../1LogToConsole/types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../20CustomChatBot/types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../22CustomSptCommand/types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ TypeScript/24WebSocket/types/utils/App.d.ts | 2 +- .../24WebSocket/types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ TypeScript/2EditDatabase/types/utils/App.d.ts | 2 +- .../2EditDatabase/types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../3GetSptConfigFile/types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../5ReplaceMethod/types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ TypeScript/7OnLoadHook/types/utils/App.d.ts | 2 +- .../7OnLoadHook/types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ TypeScript/8OnUpdateHook/types/utils/App.d.ts | 2 +- .../8OnUpdateHook/types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 2 +- .../generators/RepeatableQuestGenerator.d.ts | 13 ++++---- .../RepeatableQuestRewardGenerator.d.ts | 8 +++-- .../models/eft/common/ILocationBase.d.ts | 13 ++++++++ .../models/eft/common/tables/IQuest.d.ts | 2 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 ++++++++ .../types/models/spt/config/IItemConfig.d.ts | 2 ++ .../services/CircleOfCultistService.d.ts | 20 +++++++++--- .../types/services/ItemFilterService.d.ts | 5 +++ TypeScript/9RouterHooks/types/utils/App.d.ts | 2 +- .../9RouterHooks/types/utils/RandomUtil.d.ts | 32 ++++++++++++++++++- 337 files changed, 2717 insertions(+), 505 deletions(-) diff --git a/README.md b/README.md index 9e5aacd..b2bb6b8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Mod examples for v3.10.2 +# Mod examples for v3.10.3 A collection of example mods that perform typical actions in SPT diff --git a/TypeScript/10ScopesAndTypes/types/controllers/QuestController.d.ts b/TypeScript/10ScopesAndTypes/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/10ScopesAndTypes/types/controllers/QuestController.d.ts +++ b/TypeScript/10ScopesAndTypes/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/10ScopesAndTypes/types/controllers/RepeatableQuestController.d.ts b/TypeScript/10ScopesAndTypes/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/10ScopesAndTypes/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/10ScopesAndTypes/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/10ScopesAndTypes/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/10ScopesAndTypes/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/10ScopesAndTypes/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/10ScopesAndTypes/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/10ScopesAndTypes/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/10ScopesAndTypes/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/10ScopesAndTypes/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/10ScopesAndTypes/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/10ScopesAndTypes/types/models/eft/common/ILocationBase.d.ts b/TypeScript/10ScopesAndTypes/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/10ScopesAndTypes/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/config/IItemConfig.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/10ScopesAndTypes/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/10ScopesAndTypes/types/services/CircleOfCultistService.d.ts b/TypeScript/10ScopesAndTypes/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/10ScopesAndTypes/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/10ScopesAndTypes/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/10ScopesAndTypes/types/services/ItemFilterService.d.ts b/TypeScript/10ScopesAndTypes/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/10ScopesAndTypes/types/services/ItemFilterService.d.ts +++ b/TypeScript/10ScopesAndTypes/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/10ScopesAndTypes/types/utils/App.d.ts b/TypeScript/10ScopesAndTypes/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/10ScopesAndTypes/types/utils/App.d.ts +++ b/TypeScript/10ScopesAndTypes/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/10ScopesAndTypes/types/utils/RandomUtil.d.ts b/TypeScript/10ScopesAndTypes/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/10ScopesAndTypes/types/utils/RandomUtil.d.ts +++ b/TypeScript/10ScopesAndTypes/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/11BundleLoadingSample/types/controllers/QuestController.d.ts b/TypeScript/11BundleLoadingSample/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/11BundleLoadingSample/types/controllers/QuestController.d.ts +++ b/TypeScript/11BundleLoadingSample/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/11BundleLoadingSample/types/controllers/RepeatableQuestController.d.ts b/TypeScript/11BundleLoadingSample/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/11BundleLoadingSample/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/11BundleLoadingSample/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/11BundleLoadingSample/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/11BundleLoadingSample/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/11BundleLoadingSample/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/11BundleLoadingSample/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/11BundleLoadingSample/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/11BundleLoadingSample/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/11BundleLoadingSample/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/11BundleLoadingSample/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/11BundleLoadingSample/types/models/eft/common/ILocationBase.d.ts b/TypeScript/11BundleLoadingSample/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/11BundleLoadingSample/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/config/IItemConfig.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/11BundleLoadingSample/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/11BundleLoadingSample/types/services/CircleOfCultistService.d.ts b/TypeScript/11BundleLoadingSample/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/11BundleLoadingSample/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/11BundleLoadingSample/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/11BundleLoadingSample/types/services/ItemFilterService.d.ts b/TypeScript/11BundleLoadingSample/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/11BundleLoadingSample/types/services/ItemFilterService.d.ts +++ b/TypeScript/11BundleLoadingSample/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/11BundleLoadingSample/types/utils/App.d.ts b/TypeScript/11BundleLoadingSample/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/11BundleLoadingSample/types/utils/App.d.ts +++ b/TypeScript/11BundleLoadingSample/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/11BundleLoadingSample/types/utils/RandomUtil.d.ts b/TypeScript/11BundleLoadingSample/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/11BundleLoadingSample/types/utils/RandomUtil.d.ts +++ b/TypeScript/11BundleLoadingSample/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/12ClassExtensionOverride/types/controllers/QuestController.d.ts b/TypeScript/12ClassExtensionOverride/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/12ClassExtensionOverride/types/controllers/QuestController.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/12ClassExtensionOverride/types/controllers/RepeatableQuestController.d.ts b/TypeScript/12ClassExtensionOverride/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/12ClassExtensionOverride/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/12ClassExtensionOverride/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/12ClassExtensionOverride/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/12ClassExtensionOverride/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/12ClassExtensionOverride/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/12ClassExtensionOverride/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/12ClassExtensionOverride/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/12ClassExtensionOverride/types/models/eft/common/ILocationBase.d.ts b/TypeScript/12ClassExtensionOverride/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IItemConfig.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/12ClassExtensionOverride/types/services/CircleOfCultistService.d.ts b/TypeScript/12ClassExtensionOverride/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/12ClassExtensionOverride/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/12ClassExtensionOverride/types/services/ItemFilterService.d.ts b/TypeScript/12ClassExtensionOverride/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/12ClassExtensionOverride/types/services/ItemFilterService.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/12ClassExtensionOverride/types/utils/App.d.ts b/TypeScript/12ClassExtensionOverride/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/12ClassExtensionOverride/types/utils/App.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/12ClassExtensionOverride/types/utils/RandomUtil.d.ts b/TypeScript/12ClassExtensionOverride/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/12ClassExtensionOverride/types/utils/RandomUtil.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/controllers/QuestController.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/controllers/QuestController.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/controllers/RepeatableQuestController.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/common/ILocationBase.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IItemConfig.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/services/CircleOfCultistService.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/services/ItemFilterService.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/services/ItemFilterService.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/utils/App.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/utils/App.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/utils/RandomUtil.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/utils/RandomUtil.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/13AddTrader/types/controllers/QuestController.d.ts b/TypeScript/13AddTrader/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/13AddTrader/types/controllers/QuestController.d.ts +++ b/TypeScript/13AddTrader/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/13AddTrader/types/controllers/RepeatableQuestController.d.ts b/TypeScript/13AddTrader/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/13AddTrader/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/13AddTrader/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/13AddTrader/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/13AddTrader/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/13AddTrader/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/13AddTrader/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/13AddTrader/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/13AddTrader/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/13AddTrader/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/13AddTrader/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/13AddTrader/types/models/eft/common/ILocationBase.d.ts b/TypeScript/13AddTrader/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/13AddTrader/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/13AddTrader/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/13AddTrader/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/13AddTrader/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/13AddTrader/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/13AddTrader/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/13AddTrader/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/13AddTrader/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/13AddTrader/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/13AddTrader/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/13AddTrader/types/models/spt/config/IItemConfig.d.ts b/TypeScript/13AddTrader/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/13AddTrader/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/13AddTrader/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/13AddTrader/types/services/CircleOfCultistService.d.ts b/TypeScript/13AddTrader/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/13AddTrader/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/13AddTrader/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/13AddTrader/types/services/ItemFilterService.d.ts b/TypeScript/13AddTrader/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/13AddTrader/types/services/ItemFilterService.d.ts +++ b/TypeScript/13AddTrader/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/13AddTrader/types/utils/App.d.ts b/TypeScript/13AddTrader/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/13AddTrader/types/utils/App.d.ts +++ b/TypeScript/13AddTrader/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/13AddTrader/types/utils/RandomUtil.d.ts b/TypeScript/13AddTrader/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/13AddTrader/types/utils/RandomUtil.d.ts +++ b/TypeScript/13AddTrader/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/14AfterDBLoadHook/types/controllers/QuestController.d.ts b/TypeScript/14AfterDBLoadHook/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/14AfterDBLoadHook/types/controllers/QuestController.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/14AfterDBLoadHook/types/controllers/RepeatableQuestController.d.ts b/TypeScript/14AfterDBLoadHook/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/14AfterDBLoadHook/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/14AfterDBLoadHook/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/14AfterDBLoadHook/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/14AfterDBLoadHook/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/14AfterDBLoadHook/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/14AfterDBLoadHook/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/14AfterDBLoadHook/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/14AfterDBLoadHook/types/models/eft/common/ILocationBase.d.ts b/TypeScript/14AfterDBLoadHook/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IItemConfig.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/14AfterDBLoadHook/types/services/CircleOfCultistService.d.ts b/TypeScript/14AfterDBLoadHook/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/14AfterDBLoadHook/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/14AfterDBLoadHook/types/services/ItemFilterService.d.ts b/TypeScript/14AfterDBLoadHook/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/14AfterDBLoadHook/types/services/ItemFilterService.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/14AfterDBLoadHook/types/utils/App.d.ts b/TypeScript/14AfterDBLoadHook/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/14AfterDBLoadHook/types/utils/App.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/14AfterDBLoadHook/types/utils/RandomUtil.d.ts b/TypeScript/14AfterDBLoadHook/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/14AfterDBLoadHook/types/utils/RandomUtil.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/15HttpListenerExample/types/controllers/QuestController.d.ts b/TypeScript/15HttpListenerExample/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/15HttpListenerExample/types/controllers/QuestController.d.ts +++ b/TypeScript/15HttpListenerExample/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/15HttpListenerExample/types/controllers/RepeatableQuestController.d.ts b/TypeScript/15HttpListenerExample/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/15HttpListenerExample/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/15HttpListenerExample/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/15HttpListenerExample/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/15HttpListenerExample/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/15HttpListenerExample/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/15HttpListenerExample/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/15HttpListenerExample/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/15HttpListenerExample/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/15HttpListenerExample/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/15HttpListenerExample/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/15HttpListenerExample/types/models/eft/common/ILocationBase.d.ts b/TypeScript/15HttpListenerExample/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/15HttpListenerExample/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/15HttpListenerExample/types/models/spt/config/IItemConfig.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/15HttpListenerExample/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/15HttpListenerExample/types/services/CircleOfCultistService.d.ts b/TypeScript/15HttpListenerExample/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/15HttpListenerExample/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/15HttpListenerExample/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/15HttpListenerExample/types/services/ItemFilterService.d.ts b/TypeScript/15HttpListenerExample/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/15HttpListenerExample/types/services/ItemFilterService.d.ts +++ b/TypeScript/15HttpListenerExample/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/15HttpListenerExample/types/utils/App.d.ts b/TypeScript/15HttpListenerExample/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/15HttpListenerExample/types/utils/App.d.ts +++ b/TypeScript/15HttpListenerExample/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/15HttpListenerExample/types/utils/RandomUtil.d.ts b/TypeScript/15HttpListenerExample/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/15HttpListenerExample/types/utils/RandomUtil.d.ts +++ b/TypeScript/15HttpListenerExample/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/16ImporterUtil/types/controllers/QuestController.d.ts b/TypeScript/16ImporterUtil/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/16ImporterUtil/types/controllers/QuestController.d.ts +++ b/TypeScript/16ImporterUtil/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/16ImporterUtil/types/controllers/RepeatableQuestController.d.ts b/TypeScript/16ImporterUtil/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/16ImporterUtil/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/16ImporterUtil/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/16ImporterUtil/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/16ImporterUtil/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/16ImporterUtil/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/16ImporterUtil/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/16ImporterUtil/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/16ImporterUtil/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/16ImporterUtil/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/16ImporterUtil/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/16ImporterUtil/types/models/eft/common/ILocationBase.d.ts b/TypeScript/16ImporterUtil/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/16ImporterUtil/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/16ImporterUtil/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/16ImporterUtil/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/16ImporterUtil/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/16ImporterUtil/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/16ImporterUtil/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/16ImporterUtil/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/16ImporterUtil/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/16ImporterUtil/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/16ImporterUtil/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/16ImporterUtil/types/models/spt/config/IItemConfig.d.ts b/TypeScript/16ImporterUtil/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/16ImporterUtil/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/16ImporterUtil/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/16ImporterUtil/types/services/CircleOfCultistService.d.ts b/TypeScript/16ImporterUtil/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/16ImporterUtil/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/16ImporterUtil/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/16ImporterUtil/types/services/ItemFilterService.d.ts b/TypeScript/16ImporterUtil/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/16ImporterUtil/types/services/ItemFilterService.d.ts +++ b/TypeScript/16ImporterUtil/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/16ImporterUtil/types/utils/App.d.ts b/TypeScript/16ImporterUtil/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/16ImporterUtil/types/utils/App.d.ts +++ b/TypeScript/16ImporterUtil/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/16ImporterUtil/types/utils/RandomUtil.d.ts b/TypeScript/16ImporterUtil/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/16ImporterUtil/types/utils/RandomUtil.d.ts +++ b/TypeScript/16ImporterUtil/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/17AsyncImporterWithDependency1/types/controllers/QuestController.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/controllers/QuestController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/17AsyncImporterWithDependency1/types/controllers/RepeatableQuestController.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/17AsyncImporterWithDependency1/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/17AsyncImporterWithDependency1/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/ILocationBase.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IItemConfig.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/services/CircleOfCultistService.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/17AsyncImporterWithDependency1/types/services/ItemFilterService.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/services/ItemFilterService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/17AsyncImporterWithDependency1/types/utils/App.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/utils/App.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/utils/RandomUtil.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/utils/RandomUtil.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/17AsyncImporterWithDependency2/types/controllers/QuestController.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/controllers/QuestController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/17AsyncImporterWithDependency2/types/controllers/RepeatableQuestController.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/17AsyncImporterWithDependency2/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/17AsyncImporterWithDependency2/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/ILocationBase.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IItemConfig.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/services/CircleOfCultistService.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/17AsyncImporterWithDependency2/types/services/ItemFilterService.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/services/ItemFilterService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/17AsyncImporterWithDependency2/types/utils/App.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/utils/App.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/utils/RandomUtil.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/utils/RandomUtil.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/controllers/QuestController.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/controllers/QuestController.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/controllers/RepeatableQuestController.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/common/ILocationBase.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IItemConfig.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/services/CircleOfCultistService.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/services/ItemFilterService.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/services/ItemFilterService.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/utils/App.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/utils/App.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/utils/RandomUtil.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/utils/RandomUtil.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/18CustomItemService/types/controllers/QuestController.d.ts b/TypeScript/18CustomItemService/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/18CustomItemService/types/controllers/QuestController.d.ts +++ b/TypeScript/18CustomItemService/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/18CustomItemService/types/controllers/RepeatableQuestController.d.ts b/TypeScript/18CustomItemService/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/18CustomItemService/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/18CustomItemService/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/18CustomItemService/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/18CustomItemService/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/18CustomItemService/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/18CustomItemService/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/18CustomItemService/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/18CustomItemService/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/18CustomItemService/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/18CustomItemService/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/18CustomItemService/types/models/eft/common/ILocationBase.d.ts b/TypeScript/18CustomItemService/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/18CustomItemService/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/18CustomItemService/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/18CustomItemService/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/18CustomItemService/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/18CustomItemService/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/18CustomItemService/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/18CustomItemService/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/18CustomItemService/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/18CustomItemService/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/18CustomItemService/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/18CustomItemService/types/models/spt/config/IItemConfig.d.ts b/TypeScript/18CustomItemService/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/18CustomItemService/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/18CustomItemService/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/18CustomItemService/types/services/CircleOfCultistService.d.ts b/TypeScript/18CustomItemService/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/18CustomItemService/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/18CustomItemService/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/18CustomItemService/types/services/ItemFilterService.d.ts b/TypeScript/18CustomItemService/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/18CustomItemService/types/services/ItemFilterService.d.ts +++ b/TypeScript/18CustomItemService/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/18CustomItemService/types/utils/App.d.ts b/TypeScript/18CustomItemService/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/18CustomItemService/types/utils/App.d.ts +++ b/TypeScript/18CustomItemService/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/18CustomItemService/types/utils/RandomUtil.d.ts b/TypeScript/18CustomItemService/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/18CustomItemService/types/utils/RandomUtil.d.ts +++ b/TypeScript/18CustomItemService/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/19UseExternalLibraries/types/controllers/QuestController.d.ts b/TypeScript/19UseExternalLibraries/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/19UseExternalLibraries/types/controllers/QuestController.d.ts +++ b/TypeScript/19UseExternalLibraries/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/19UseExternalLibraries/types/controllers/RepeatableQuestController.d.ts b/TypeScript/19UseExternalLibraries/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/19UseExternalLibraries/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/19UseExternalLibraries/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/19UseExternalLibraries/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/19UseExternalLibraries/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/19UseExternalLibraries/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/19UseExternalLibraries/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/19UseExternalLibraries/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/19UseExternalLibraries/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/19UseExternalLibraries/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/19UseExternalLibraries/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/19UseExternalLibraries/types/models/eft/common/ILocationBase.d.ts b/TypeScript/19UseExternalLibraries/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/19UseExternalLibraries/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/19UseExternalLibraries/types/models/spt/config/IItemConfig.d.ts b/TypeScript/19UseExternalLibraries/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/19UseExternalLibraries/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/19UseExternalLibraries/types/services/CircleOfCultistService.d.ts b/TypeScript/19UseExternalLibraries/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/19UseExternalLibraries/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/19UseExternalLibraries/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/19UseExternalLibraries/types/services/ItemFilterService.d.ts b/TypeScript/19UseExternalLibraries/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/19UseExternalLibraries/types/services/ItemFilterService.d.ts +++ b/TypeScript/19UseExternalLibraries/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/19UseExternalLibraries/types/utils/App.d.ts b/TypeScript/19UseExternalLibraries/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/19UseExternalLibraries/types/utils/App.d.ts +++ b/TypeScript/19UseExternalLibraries/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/19UseExternalLibraries/types/utils/RandomUtil.d.ts b/TypeScript/19UseExternalLibraries/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/19UseExternalLibraries/types/utils/RandomUtil.d.ts +++ b/TypeScript/19UseExternalLibraries/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/1LogToConsole/types/controllers/QuestController.d.ts b/TypeScript/1LogToConsole/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/1LogToConsole/types/controllers/QuestController.d.ts +++ b/TypeScript/1LogToConsole/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/1LogToConsole/types/controllers/RepeatableQuestController.d.ts b/TypeScript/1LogToConsole/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/1LogToConsole/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/1LogToConsole/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/1LogToConsole/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/1LogToConsole/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/1LogToConsole/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/1LogToConsole/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/1LogToConsole/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/1LogToConsole/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/1LogToConsole/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/1LogToConsole/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/1LogToConsole/types/models/eft/common/ILocationBase.d.ts b/TypeScript/1LogToConsole/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/1LogToConsole/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/1LogToConsole/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/1LogToConsole/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/1LogToConsole/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/1LogToConsole/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/1LogToConsole/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/1LogToConsole/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/1LogToConsole/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/1LogToConsole/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/1LogToConsole/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/1LogToConsole/types/models/spt/config/IItemConfig.d.ts b/TypeScript/1LogToConsole/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/1LogToConsole/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/1LogToConsole/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/1LogToConsole/types/services/CircleOfCultistService.d.ts b/TypeScript/1LogToConsole/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/1LogToConsole/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/1LogToConsole/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/1LogToConsole/types/services/ItemFilterService.d.ts b/TypeScript/1LogToConsole/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/1LogToConsole/types/services/ItemFilterService.d.ts +++ b/TypeScript/1LogToConsole/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/1LogToConsole/types/utils/App.d.ts b/TypeScript/1LogToConsole/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/1LogToConsole/types/utils/App.d.ts +++ b/TypeScript/1LogToConsole/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/1LogToConsole/types/utils/RandomUtil.d.ts b/TypeScript/1LogToConsole/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/1LogToConsole/types/utils/RandomUtil.d.ts +++ b/TypeScript/1LogToConsole/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/20CustomChatBot/types/controllers/QuestController.d.ts b/TypeScript/20CustomChatBot/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/20CustomChatBot/types/controllers/QuestController.d.ts +++ b/TypeScript/20CustomChatBot/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/20CustomChatBot/types/controllers/RepeatableQuestController.d.ts b/TypeScript/20CustomChatBot/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/20CustomChatBot/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/20CustomChatBot/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/20CustomChatBot/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/20CustomChatBot/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/20CustomChatBot/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/20CustomChatBot/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/20CustomChatBot/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/20CustomChatBot/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/20CustomChatBot/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/20CustomChatBot/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/20CustomChatBot/types/models/eft/common/ILocationBase.d.ts b/TypeScript/20CustomChatBot/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/20CustomChatBot/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/20CustomChatBot/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/20CustomChatBot/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/20CustomChatBot/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/20CustomChatBot/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/20CustomChatBot/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/20CustomChatBot/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/20CustomChatBot/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/20CustomChatBot/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/20CustomChatBot/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/20CustomChatBot/types/models/spt/config/IItemConfig.d.ts b/TypeScript/20CustomChatBot/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/20CustomChatBot/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/20CustomChatBot/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/20CustomChatBot/types/services/CircleOfCultistService.d.ts b/TypeScript/20CustomChatBot/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/20CustomChatBot/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/20CustomChatBot/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/20CustomChatBot/types/services/ItemFilterService.d.ts b/TypeScript/20CustomChatBot/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/20CustomChatBot/types/services/ItemFilterService.d.ts +++ b/TypeScript/20CustomChatBot/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/20CustomChatBot/types/utils/App.d.ts b/TypeScript/20CustomChatBot/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/20CustomChatBot/types/utils/App.d.ts +++ b/TypeScript/20CustomChatBot/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/20CustomChatBot/types/utils/RandomUtil.d.ts b/TypeScript/20CustomChatBot/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/20CustomChatBot/types/utils/RandomUtil.d.ts +++ b/TypeScript/20CustomChatBot/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/21CustomCommandoCommand/types/controllers/QuestController.d.ts b/TypeScript/21CustomCommandoCommand/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/21CustomCommandoCommand/types/controllers/QuestController.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/21CustomCommandoCommand/types/controllers/RepeatableQuestController.d.ts b/TypeScript/21CustomCommandoCommand/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/21CustomCommandoCommand/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/21CustomCommandoCommand/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/21CustomCommandoCommand/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/21CustomCommandoCommand/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/21CustomCommandoCommand/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/21CustomCommandoCommand/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/21CustomCommandoCommand/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/21CustomCommandoCommand/types/models/eft/common/ILocationBase.d.ts b/TypeScript/21CustomCommandoCommand/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/21CustomCommandoCommand/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/21CustomCommandoCommand/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/21CustomCommandoCommand/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/21CustomCommandoCommand/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/21CustomCommandoCommand/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/21CustomCommandoCommand/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/21CustomCommandoCommand/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/21CustomCommandoCommand/types/models/spt/config/IItemConfig.d.ts b/TypeScript/21CustomCommandoCommand/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/21CustomCommandoCommand/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/21CustomCommandoCommand/types/services/CircleOfCultistService.d.ts b/TypeScript/21CustomCommandoCommand/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/21CustomCommandoCommand/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/21CustomCommandoCommand/types/services/ItemFilterService.d.ts b/TypeScript/21CustomCommandoCommand/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/21CustomCommandoCommand/types/services/ItemFilterService.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/21CustomCommandoCommand/types/utils/App.d.ts b/TypeScript/21CustomCommandoCommand/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/21CustomCommandoCommand/types/utils/App.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/21CustomCommandoCommand/types/utils/RandomUtil.d.ts b/TypeScript/21CustomCommandoCommand/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/21CustomCommandoCommand/types/utils/RandomUtil.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/22CustomSptCommand/types/controllers/QuestController.d.ts b/TypeScript/22CustomSptCommand/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/22CustomSptCommand/types/controllers/QuestController.d.ts +++ b/TypeScript/22CustomSptCommand/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/22CustomSptCommand/types/controllers/RepeatableQuestController.d.ts b/TypeScript/22CustomSptCommand/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/22CustomSptCommand/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/22CustomSptCommand/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/22CustomSptCommand/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/22CustomSptCommand/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/22CustomSptCommand/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/22CustomSptCommand/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/22CustomSptCommand/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/22CustomSptCommand/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/22CustomSptCommand/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/22CustomSptCommand/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/22CustomSptCommand/types/models/eft/common/ILocationBase.d.ts b/TypeScript/22CustomSptCommand/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/22CustomSptCommand/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/22CustomSptCommand/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/22CustomSptCommand/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/22CustomSptCommand/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/22CustomSptCommand/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/22CustomSptCommand/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/22CustomSptCommand/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/22CustomSptCommand/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/22CustomSptCommand/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/22CustomSptCommand/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/22CustomSptCommand/types/models/spt/config/IItemConfig.d.ts b/TypeScript/22CustomSptCommand/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/22CustomSptCommand/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/22CustomSptCommand/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/22CustomSptCommand/types/services/CircleOfCultistService.d.ts b/TypeScript/22CustomSptCommand/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/22CustomSptCommand/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/22CustomSptCommand/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/22CustomSptCommand/types/services/ItemFilterService.d.ts b/TypeScript/22CustomSptCommand/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/22CustomSptCommand/types/services/ItemFilterService.d.ts +++ b/TypeScript/22CustomSptCommand/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/22CustomSptCommand/types/utils/App.d.ts b/TypeScript/22CustomSptCommand/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/22CustomSptCommand/types/utils/App.d.ts +++ b/TypeScript/22CustomSptCommand/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/22CustomSptCommand/types/utils/RandomUtil.d.ts b/TypeScript/22CustomSptCommand/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/22CustomSptCommand/types/utils/RandomUtil.d.ts +++ b/TypeScript/22CustomSptCommand/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/23CustomAbstractChatBot/types/controllers/QuestController.d.ts b/TypeScript/23CustomAbstractChatBot/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/23CustomAbstractChatBot/types/controllers/QuestController.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/23CustomAbstractChatBot/types/controllers/RepeatableQuestController.d.ts b/TypeScript/23CustomAbstractChatBot/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/23CustomAbstractChatBot/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/23CustomAbstractChatBot/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/23CustomAbstractChatBot/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/23CustomAbstractChatBot/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/23CustomAbstractChatBot/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/23CustomAbstractChatBot/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/23CustomAbstractChatBot/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/23CustomAbstractChatBot/types/models/eft/common/ILocationBase.d.ts b/TypeScript/23CustomAbstractChatBot/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/23CustomAbstractChatBot/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/23CustomAbstractChatBot/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/23CustomAbstractChatBot/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/23CustomAbstractChatBot/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/23CustomAbstractChatBot/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/23CustomAbstractChatBot/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/23CustomAbstractChatBot/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IItemConfig.d.ts b/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/23CustomAbstractChatBot/types/services/CircleOfCultistService.d.ts b/TypeScript/23CustomAbstractChatBot/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/23CustomAbstractChatBot/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/23CustomAbstractChatBot/types/services/ItemFilterService.d.ts b/TypeScript/23CustomAbstractChatBot/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/23CustomAbstractChatBot/types/services/ItemFilterService.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/23CustomAbstractChatBot/types/utils/App.d.ts b/TypeScript/23CustomAbstractChatBot/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/23CustomAbstractChatBot/types/utils/App.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/23CustomAbstractChatBot/types/utils/RandomUtil.d.ts b/TypeScript/23CustomAbstractChatBot/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/23CustomAbstractChatBot/types/utils/RandomUtil.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/24WebSocket/types/controllers/QuestController.d.ts b/TypeScript/24WebSocket/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/24WebSocket/types/controllers/QuestController.d.ts +++ b/TypeScript/24WebSocket/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/24WebSocket/types/controllers/RepeatableQuestController.d.ts b/TypeScript/24WebSocket/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/24WebSocket/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/24WebSocket/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/24WebSocket/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/24WebSocket/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/24WebSocket/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/24WebSocket/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/24WebSocket/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/24WebSocket/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/24WebSocket/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/24WebSocket/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/24WebSocket/types/models/eft/common/ILocationBase.d.ts b/TypeScript/24WebSocket/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/24WebSocket/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/24WebSocket/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/24WebSocket/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/24WebSocket/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/24WebSocket/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/24WebSocket/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/24WebSocket/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/24WebSocket/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/24WebSocket/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/24WebSocket/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/24WebSocket/types/models/spt/config/IItemConfig.d.ts b/TypeScript/24WebSocket/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/24WebSocket/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/24WebSocket/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/24WebSocket/types/services/CircleOfCultistService.d.ts b/TypeScript/24WebSocket/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/24WebSocket/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/24WebSocket/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/24WebSocket/types/services/ItemFilterService.d.ts b/TypeScript/24WebSocket/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/24WebSocket/types/services/ItemFilterService.d.ts +++ b/TypeScript/24WebSocket/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/24WebSocket/types/utils/App.d.ts b/TypeScript/24WebSocket/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/24WebSocket/types/utils/App.d.ts +++ b/TypeScript/24WebSocket/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/24WebSocket/types/utils/RandomUtil.d.ts b/TypeScript/24WebSocket/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/24WebSocket/types/utils/RandomUtil.d.ts +++ b/TypeScript/24WebSocket/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/2EditDatabase/types/controllers/QuestController.d.ts b/TypeScript/2EditDatabase/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/2EditDatabase/types/controllers/QuestController.d.ts +++ b/TypeScript/2EditDatabase/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/2EditDatabase/types/controllers/RepeatableQuestController.d.ts b/TypeScript/2EditDatabase/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/2EditDatabase/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/2EditDatabase/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/2EditDatabase/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/2EditDatabase/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/2EditDatabase/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/2EditDatabase/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/2EditDatabase/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/2EditDatabase/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/2EditDatabase/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/2EditDatabase/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/2EditDatabase/types/models/eft/common/ILocationBase.d.ts b/TypeScript/2EditDatabase/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/2EditDatabase/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/2EditDatabase/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/2EditDatabase/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/2EditDatabase/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/2EditDatabase/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/2EditDatabase/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/2EditDatabase/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/2EditDatabase/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/2EditDatabase/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/2EditDatabase/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/2EditDatabase/types/models/spt/config/IItemConfig.d.ts b/TypeScript/2EditDatabase/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/2EditDatabase/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/2EditDatabase/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/2EditDatabase/types/services/CircleOfCultistService.d.ts b/TypeScript/2EditDatabase/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/2EditDatabase/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/2EditDatabase/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/2EditDatabase/types/services/ItemFilterService.d.ts b/TypeScript/2EditDatabase/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/2EditDatabase/types/services/ItemFilterService.d.ts +++ b/TypeScript/2EditDatabase/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/2EditDatabase/types/utils/App.d.ts b/TypeScript/2EditDatabase/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/2EditDatabase/types/utils/App.d.ts +++ b/TypeScript/2EditDatabase/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/2EditDatabase/types/utils/RandomUtil.d.ts b/TypeScript/2EditDatabase/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/2EditDatabase/types/utils/RandomUtil.d.ts +++ b/TypeScript/2EditDatabase/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/3GetSptConfigFile/types/controllers/QuestController.d.ts b/TypeScript/3GetSptConfigFile/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/3GetSptConfigFile/types/controllers/QuestController.d.ts +++ b/TypeScript/3GetSptConfigFile/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/3GetSptConfigFile/types/controllers/RepeatableQuestController.d.ts b/TypeScript/3GetSptConfigFile/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/3GetSptConfigFile/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/3GetSptConfigFile/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/3GetSptConfigFile/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/3GetSptConfigFile/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/3GetSptConfigFile/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/3GetSptConfigFile/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/3GetSptConfigFile/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/3GetSptConfigFile/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/3GetSptConfigFile/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/3GetSptConfigFile/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/3GetSptConfigFile/types/models/eft/common/ILocationBase.d.ts b/TypeScript/3GetSptConfigFile/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/3GetSptConfigFile/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/config/IItemConfig.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/3GetSptConfigFile/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/3GetSptConfigFile/types/services/CircleOfCultistService.d.ts b/TypeScript/3GetSptConfigFile/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/3GetSptConfigFile/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/3GetSptConfigFile/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/3GetSptConfigFile/types/services/ItemFilterService.d.ts b/TypeScript/3GetSptConfigFile/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/3GetSptConfigFile/types/services/ItemFilterService.d.ts +++ b/TypeScript/3GetSptConfigFile/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/3GetSptConfigFile/types/utils/App.d.ts b/TypeScript/3GetSptConfigFile/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/3GetSptConfigFile/types/utils/App.d.ts +++ b/TypeScript/3GetSptConfigFile/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/3GetSptConfigFile/types/utils/RandomUtil.d.ts b/TypeScript/3GetSptConfigFile/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/3GetSptConfigFile/types/utils/RandomUtil.d.ts +++ b/TypeScript/3GetSptConfigFile/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/QuestController.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/QuestController.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/RepeatableQuestController.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/ILocationBase.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IItemConfig.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/CircleOfCultistService.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/ItemFilterService.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/ItemFilterService.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/App.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/App.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/RandomUtil.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/RandomUtil.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/4UseACustomConfigFile/types/controllers/QuestController.d.ts b/TypeScript/4UseACustomConfigFile/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/4UseACustomConfigFile/types/controllers/QuestController.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/4UseACustomConfigFile/types/controllers/RepeatableQuestController.d.ts b/TypeScript/4UseACustomConfigFile/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/4UseACustomConfigFile/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/4UseACustomConfigFile/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/4UseACustomConfigFile/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/4UseACustomConfigFile/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/4UseACustomConfigFile/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/4UseACustomConfigFile/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/4UseACustomConfigFile/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/4UseACustomConfigFile/types/models/eft/common/ILocationBase.d.ts b/TypeScript/4UseACustomConfigFile/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IItemConfig.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/4UseACustomConfigFile/types/services/CircleOfCultistService.d.ts b/TypeScript/4UseACustomConfigFile/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/4UseACustomConfigFile/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/4UseACustomConfigFile/types/services/ItemFilterService.d.ts b/TypeScript/4UseACustomConfigFile/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/4UseACustomConfigFile/types/services/ItemFilterService.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/4UseACustomConfigFile/types/utils/App.d.ts b/TypeScript/4UseACustomConfigFile/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/4UseACustomConfigFile/types/utils/App.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/4UseACustomConfigFile/types/utils/RandomUtil.d.ts b/TypeScript/4UseACustomConfigFile/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/4UseACustomConfigFile/types/utils/RandomUtil.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/5ReplaceMethod/types/controllers/QuestController.d.ts b/TypeScript/5ReplaceMethod/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/5ReplaceMethod/types/controllers/QuestController.d.ts +++ b/TypeScript/5ReplaceMethod/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/5ReplaceMethod/types/controllers/RepeatableQuestController.d.ts b/TypeScript/5ReplaceMethod/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/5ReplaceMethod/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/5ReplaceMethod/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/5ReplaceMethod/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/5ReplaceMethod/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/5ReplaceMethod/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/5ReplaceMethod/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/5ReplaceMethod/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/5ReplaceMethod/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/5ReplaceMethod/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/5ReplaceMethod/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/5ReplaceMethod/types/models/eft/common/ILocationBase.d.ts b/TypeScript/5ReplaceMethod/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/5ReplaceMethod/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/5ReplaceMethod/types/models/spt/config/IItemConfig.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/5ReplaceMethod/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/5ReplaceMethod/types/services/CircleOfCultistService.d.ts b/TypeScript/5ReplaceMethod/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/5ReplaceMethod/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/5ReplaceMethod/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/5ReplaceMethod/types/services/ItemFilterService.d.ts b/TypeScript/5ReplaceMethod/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/5ReplaceMethod/types/services/ItemFilterService.d.ts +++ b/TypeScript/5ReplaceMethod/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/5ReplaceMethod/types/utils/App.d.ts b/TypeScript/5ReplaceMethod/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/5ReplaceMethod/types/utils/App.d.ts +++ b/TypeScript/5ReplaceMethod/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/5ReplaceMethod/types/utils/RandomUtil.d.ts b/TypeScript/5ReplaceMethod/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/5ReplaceMethod/types/utils/RandomUtil.d.ts +++ b/TypeScript/5ReplaceMethod/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/6ReferenceAnotherClass/types/controllers/QuestController.d.ts b/TypeScript/6ReferenceAnotherClass/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/6ReferenceAnotherClass/types/controllers/QuestController.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/6ReferenceAnotherClass/types/controllers/RepeatableQuestController.d.ts b/TypeScript/6ReferenceAnotherClass/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/6ReferenceAnotherClass/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/6ReferenceAnotherClass/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/6ReferenceAnotherClass/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/6ReferenceAnotherClass/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/6ReferenceAnotherClass/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/6ReferenceAnotherClass/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/6ReferenceAnotherClass/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/6ReferenceAnotherClass/types/models/eft/common/ILocationBase.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IItemConfig.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/6ReferenceAnotherClass/types/services/CircleOfCultistService.d.ts b/TypeScript/6ReferenceAnotherClass/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/6ReferenceAnotherClass/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/6ReferenceAnotherClass/types/services/ItemFilterService.d.ts b/TypeScript/6ReferenceAnotherClass/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/6ReferenceAnotherClass/types/services/ItemFilterService.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/6ReferenceAnotherClass/types/utils/App.d.ts b/TypeScript/6ReferenceAnotherClass/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/6ReferenceAnotherClass/types/utils/App.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/6ReferenceAnotherClass/types/utils/RandomUtil.d.ts b/TypeScript/6ReferenceAnotherClass/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/6ReferenceAnotherClass/types/utils/RandomUtil.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/7OnLoadHook/types/controllers/QuestController.d.ts b/TypeScript/7OnLoadHook/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/7OnLoadHook/types/controllers/QuestController.d.ts +++ b/TypeScript/7OnLoadHook/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/7OnLoadHook/types/controllers/RepeatableQuestController.d.ts b/TypeScript/7OnLoadHook/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/7OnLoadHook/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/7OnLoadHook/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/7OnLoadHook/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/7OnLoadHook/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/7OnLoadHook/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/7OnLoadHook/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/7OnLoadHook/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/7OnLoadHook/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/7OnLoadHook/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/7OnLoadHook/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/7OnLoadHook/types/models/eft/common/ILocationBase.d.ts b/TypeScript/7OnLoadHook/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/7OnLoadHook/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/7OnLoadHook/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/7OnLoadHook/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/7OnLoadHook/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/7OnLoadHook/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/7OnLoadHook/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/7OnLoadHook/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/7OnLoadHook/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/7OnLoadHook/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/7OnLoadHook/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/7OnLoadHook/types/models/spt/config/IItemConfig.d.ts b/TypeScript/7OnLoadHook/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/7OnLoadHook/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/7OnLoadHook/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/7OnLoadHook/types/services/CircleOfCultistService.d.ts b/TypeScript/7OnLoadHook/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/7OnLoadHook/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/7OnLoadHook/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/7OnLoadHook/types/services/ItemFilterService.d.ts b/TypeScript/7OnLoadHook/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/7OnLoadHook/types/services/ItemFilterService.d.ts +++ b/TypeScript/7OnLoadHook/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/7OnLoadHook/types/utils/App.d.ts b/TypeScript/7OnLoadHook/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/7OnLoadHook/types/utils/App.d.ts +++ b/TypeScript/7OnLoadHook/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/7OnLoadHook/types/utils/RandomUtil.d.ts b/TypeScript/7OnLoadHook/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/7OnLoadHook/types/utils/RandomUtil.d.ts +++ b/TypeScript/7OnLoadHook/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/8OnUpdateHook/types/controllers/QuestController.d.ts b/TypeScript/8OnUpdateHook/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/8OnUpdateHook/types/controllers/QuestController.d.ts +++ b/TypeScript/8OnUpdateHook/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/8OnUpdateHook/types/controllers/RepeatableQuestController.d.ts b/TypeScript/8OnUpdateHook/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/8OnUpdateHook/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/8OnUpdateHook/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/8OnUpdateHook/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/8OnUpdateHook/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/8OnUpdateHook/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/8OnUpdateHook/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/8OnUpdateHook/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/8OnUpdateHook/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/8OnUpdateHook/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/8OnUpdateHook/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/8OnUpdateHook/types/models/eft/common/ILocationBase.d.ts b/TypeScript/8OnUpdateHook/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/8OnUpdateHook/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/8OnUpdateHook/types/models/spt/config/IItemConfig.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/8OnUpdateHook/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/8OnUpdateHook/types/services/CircleOfCultistService.d.ts b/TypeScript/8OnUpdateHook/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/8OnUpdateHook/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/8OnUpdateHook/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/8OnUpdateHook/types/services/ItemFilterService.d.ts b/TypeScript/8OnUpdateHook/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/8OnUpdateHook/types/services/ItemFilterService.d.ts +++ b/TypeScript/8OnUpdateHook/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/8OnUpdateHook/types/utils/App.d.ts b/TypeScript/8OnUpdateHook/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/8OnUpdateHook/types/utils/App.d.ts +++ b/TypeScript/8OnUpdateHook/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/8OnUpdateHook/types/utils/RandomUtil.d.ts b/TypeScript/8OnUpdateHook/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/8OnUpdateHook/types/utils/RandomUtil.d.ts +++ b/TypeScript/8OnUpdateHook/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. * diff --git a/TypeScript/9RouterHooks/types/controllers/QuestController.d.ts b/TypeScript/9RouterHooks/types/controllers/QuestController.d.ts index ac486e3..85221d6 100644 --- a/TypeScript/9RouterHooks/types/controllers/QuestController.d.ts +++ b/TypeScript/9RouterHooks/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/TypeScript/9RouterHooks/types/controllers/RepeatableQuestController.d.ts b/TypeScript/9RouterHooks/types/controllers/RepeatableQuestController.d.ts index 016f8c6..9893318 100644 --- a/TypeScript/9RouterHooks/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/9RouterHooks/types/controllers/RepeatableQuestController.d.ts @@ -154,7 +154,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/TypeScript/9RouterHooks/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/9RouterHooks/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc..802a68b 100644 --- a/TypeScript/9RouterHooks/types/generators/RepeatableQuestGenerator.d.ts +++ b/TypeScript/9RouterHooks/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/TypeScript/9RouterHooks/types/generators/RepeatableQuestRewardGenerator.d.ts b/TypeScript/9RouterHooks/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78cca..f029974 100644 --- a/TypeScript/9RouterHooks/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/TypeScript/9RouterHooks/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/TypeScript/9RouterHooks/types/models/eft/common/ILocationBase.d.ts b/TypeScript/9RouterHooks/types/models/eft/common/ILocationBase.d.ts index 75836b6..69000e1 100644 --- a/TypeScript/9RouterHooks/types/models/eft/common/ILocationBase.d.ts +++ b/TypeScript/9RouterHooks/types/models/eft/common/ILocationBase.d.ts @@ -11,23 +11,36 @@ export interface ILocationBase { Banners: IBanner[]; BossLocationSpawn: IBossLocationSpawn[]; BotAssault: number; + /** Weighting on how likely a bot will be Easy difficulty */ BotEasy: number; + /** Weighting on how likely a bot will be Hard difficulty */ BotHard: number; + /** Weighting on how likely a bot will be Impossible difficulty */ BotImpossible: number; BotLocationModifier: IBotLocationModifier; BotMarksman: number; + /** Maximum Number of bots that are currently alive/loading/delayed */ BotMax: number; + /** Is not used in 33420 */ BotMaxPlayer: number; + /** Is not used in 33420 */ BotMaxTimePlayer: number; + /** Does not even exist in the client in 33420 */ BotMaxPvE: number; + /** Weighting on how likely a bot will be Normal difficulty */ BotNormal: number; + /** How many bot slots that need to be open before trying to spawn new bots. */ BotSpawnCountStep: number; + /** How often to check if bots are spawn-able. In seconds */ BotSpawnPeriodCheck: number; + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ BotSpawnTimeOffMax: number; BotSpawnTimeOffMin: number; BotSpawnTimeOnMax: number; BotSpawnTimeOnMin: number; + /** How soon bots will be allowed to spawn */ BotStart: number; + /** After this long bots will no longer spawn */ BotStop: number; Description: string; DisabledForScav: boolean; diff --git a/TypeScript/9RouterHooks/types/models/eft/common/tables/IQuest.d.ts b/TypeScript/9RouterHooks/types/models/eft/common/tables/IQuest.d.ts index e956856..521c67f 100644 --- a/TypeScript/9RouterHooks/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/9RouterHooks/types/models/eft/common/tables/IQuest.d.ts @@ -148,8 +148,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/TypeScript/9RouterHooks/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/9RouterHooks/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a..b596c2b 100644 --- a/TypeScript/9RouterHooks/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/9RouterHooks/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/TypeScript/9RouterHooks/types/models/spt/config/IItemConfig.d.ts b/TypeScript/9RouterHooks/types/models/spt/config/IItemConfig.d.ts index a8833bf..d516ba9 100644 --- a/TypeScript/9RouterHooks/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/9RouterHooks/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/TypeScript/9RouterHooks/types/services/CircleOfCultistService.d.ts b/TypeScript/9RouterHooks/types/services/CircleOfCultistService.d.ts index e804617..7568261 100644 --- a/TypeScript/9RouterHooks/types/services/CircleOfCultistService.d.ts +++ b/TypeScript/9RouterHooks/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over diff --git a/TypeScript/9RouterHooks/types/services/ItemFilterService.d.ts b/TypeScript/9RouterHooks/types/services/ItemFilterService.d.ts index 7ff6532..120d44e 100644 --- a/TypeScript/9RouterHooks/types/services/ItemFilterService.d.ts +++ b/TypeScript/9RouterHooks/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/TypeScript/9RouterHooks/types/utils/App.d.ts b/TypeScript/9RouterHooks/types/utils/App.d.ts index 0e4850e..db46d2c 100644 --- a/TypeScript/9RouterHooks/types/utils/App.d.ts +++ b/TypeScript/9RouterHooks/types/utils/App.d.ts @@ -4,10 +4,10 @@ import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpServer } from "@spt/servers/HttpServer"; +import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; -import { DatabaseService } from "@spt/services/DatabaseService"; export declare class App { protected logger: ILogger; protected timeUtil: TimeUtil; diff --git a/TypeScript/9RouterHooks/types/utils/RandomUtil.d.ts b/TypeScript/9RouterHooks/types/utils/RandomUtil.d.ts index 601300c..a94c336 100644 --- a/TypeScript/9RouterHooks/types/utils/RandomUtil.d.ts +++ b/TypeScript/9RouterHooks/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. *