From 10616089ae3a4b0d251d56e70cea1d60cfc1a954 Mon Sep 17 00:00:00 2001 From: chomp Date: Sun, 15 Dec 2024 11:52:51 +0000 Subject: [PATCH 1/3] 3.10.3-dev (#43) Co-authored-by: Chomp Reviewed-on: https://dev.sp-tarkov.com/chomp/ModExamples/pulls/43 --- README.md | 2 +- .../types/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../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/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../services/CircleOfCultistService.d.ts | 20 +++- .../types/services/ItemFilterService.d.ts | 5 + .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 +++++- .../types/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../services/CircleOfCultistService.d.ts | 20 +++- .../types/services/ItemFilterService.d.ts | 5 + .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 +++++- .../types/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../services/CircleOfCultistService.d.ts | 20 +++- .../types/services/ItemFilterService.d.ts | 5 + .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 +++++- .../types/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../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/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../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/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../services/CircleOfCultistService.d.ts | 20 +++- .../types/services/ItemFilterService.d.ts | 5 + .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 +++++- .../types/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../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/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../services/CircleOfCultistService.d.ts | 20 +++- .../types/services/ItemFilterService.d.ts | 5 + .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 +++++- .../types/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../services/CircleOfCultistService.d.ts | 20 +++- .../types/services/ItemFilterService.d.ts | 5 + .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 +++++- .../types/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../services/CircleOfCultistService.d.ts | 20 +++- .../types/services/ItemFilterService.d.ts | 5 + .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 +++++- .../types/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../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/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../services/CircleOfCultistService.d.ts | 20 +++- .../types/services/ItemFilterService.d.ts | 5 + .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 +++++- .../types/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../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/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../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/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../services/CircleOfCultistService.d.ts | 20 +++- .../types/services/ItemFilterService.d.ts | 5 + .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 +++++- .../types/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../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/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../services/CircleOfCultistService.d.ts | 20 +++- .../types/services/ItemFilterService.d.ts | 5 + .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 +++++- .../types/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../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/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../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/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../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/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../services/CircleOfCultistService.d.ts | 20 +++- .../types/services/ItemFilterService.d.ts | 5 + .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 +++++- .../types/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../services/CircleOfCultistService.d.ts | 20 +++- .../types/services/ItemFilterService.d.ts | 5 + .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 +++++- .../types/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../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/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../services/CircleOfCultistService.d.ts | 20 +++- .../types/services/ItemFilterService.d.ts | 5 + .../types/utils/App.d.ts | 2 +- .../types/utils/RandomUtil.d.ts | 32 +++++- .../types/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../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/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../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/callbacks/SaveCallbacks.d.ts | 4 +- .../types/controllers/DialogueController.d.ts | 9 +- .../types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- .../types/helpers/ProfileHelper.d.ts | 19 ++++ .../models/eft/common/ILocationBase.d.ts | 13 +++ .../models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/ISearchFriendResponse.d.ts | 1 + .../types/models/eft/profile/ISptProfile.d.ts | 2 + .../models/eft/ws/IWsFriendsListAccept.d.ts | 5 + .../models/eft/ws/IWsNotificationEvent.d.ts | 2 +- .../types/models/enums/ConfigTypes.d.ts | 1 + .../models/spt/config/IBackupConfig.d.ts | 12 +++ .../types/models/spt/config/IItemConfig.d.ts | 2 + .../types/services/BackupService.d.ts | 98 +++++++++++++++++++ .../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 +++++- 617 files changed, 7393 insertions(+), 589 deletions(-) create mode 100644 TypeScript/10ScopesAndTypes/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/10ScopesAndTypes/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/10ScopesAndTypes/types/services/BackupService.d.ts create mode 100644 TypeScript/11BundleLoadingSample/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/11BundleLoadingSample/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/11BundleLoadingSample/types/services/BackupService.d.ts create mode 100644 TypeScript/12ClassExtensionOverride/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/12ClassExtensionOverride/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/12ClassExtensionOverride/types/services/BackupService.d.ts create mode 100644 TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/13.1AddTraderWithAssortJSON/types/services/BackupService.d.ts create mode 100644 TypeScript/13AddTrader/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/13AddTrader/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/13AddTrader/types/services/BackupService.d.ts create mode 100644 TypeScript/14AfterDBLoadHook/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/14AfterDBLoadHook/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/14AfterDBLoadHook/types/services/BackupService.d.ts create mode 100644 TypeScript/15HttpListenerExample/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/15HttpListenerExample/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/15HttpListenerExample/types/services/BackupService.d.ts create mode 100644 TypeScript/16ImporterUtil/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/16ImporterUtil/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/16ImporterUtil/types/services/BackupService.d.ts create mode 100644 TypeScript/17AsyncImporterWithDependency1/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/17AsyncImporterWithDependency1/types/services/BackupService.d.ts create mode 100644 TypeScript/17AsyncImporterWithDependency2/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/17AsyncImporterWithDependency2/types/services/BackupService.d.ts create mode 100644 TypeScript/18.1CustomItemServiceLootBox/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/18.1CustomItemServiceLootBox/types/services/BackupService.d.ts create mode 100644 TypeScript/18CustomItemService/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/18CustomItemService/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/18CustomItemService/types/services/BackupService.d.ts create mode 100644 TypeScript/19UseExternalLibraries/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/19UseExternalLibraries/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/19UseExternalLibraries/types/services/BackupService.d.ts create mode 100644 TypeScript/1LogToConsole/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/1LogToConsole/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/1LogToConsole/types/services/BackupService.d.ts create mode 100644 TypeScript/20CustomChatBot/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/20CustomChatBot/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/20CustomChatBot/types/services/BackupService.d.ts create mode 100644 TypeScript/21CustomCommandoCommand/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/21CustomCommandoCommand/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/21CustomCommandoCommand/types/services/BackupService.d.ts create mode 100644 TypeScript/22CustomSptCommand/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/22CustomSptCommand/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/22CustomSptCommand/types/services/BackupService.d.ts create mode 100644 TypeScript/23CustomAbstractChatBot/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/23CustomAbstractChatBot/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/23CustomAbstractChatBot/types/services/BackupService.d.ts create mode 100644 TypeScript/24WebSocket/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/24WebSocket/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/24WebSocket/types/services/BackupService.d.ts create mode 100644 TypeScript/2EditDatabase/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/2EditDatabase/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/2EditDatabase/types/services/BackupService.d.ts create mode 100644 TypeScript/3GetSptConfigFile/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/3GetSptConfigFile/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/3GetSptConfigFile/types/services/BackupService.d.ts create mode 100644 TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/BackupService.d.ts create mode 100644 TypeScript/4UseACustomConfigFile/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/4UseACustomConfigFile/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/4UseACustomConfigFile/types/services/BackupService.d.ts create mode 100644 TypeScript/5ReplaceMethod/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/5ReplaceMethod/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/5ReplaceMethod/types/services/BackupService.d.ts create mode 100644 TypeScript/6ReferenceAnotherClass/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/6ReferenceAnotherClass/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/6ReferenceAnotherClass/types/services/BackupService.d.ts create mode 100644 TypeScript/7OnLoadHook/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/7OnLoadHook/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/7OnLoadHook/types/services/BackupService.d.ts create mode 100644 TypeScript/8OnUpdateHook/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/8OnUpdateHook/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/8OnUpdateHook/types/services/BackupService.d.ts create mode 100644 TypeScript/9RouterHooks/types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 TypeScript/9RouterHooks/types/models/spt/config/IBackupConfig.d.ts create mode 100644 TypeScript/9RouterHooks/types/services/BackupService.d.ts 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/callbacks/SaveCallbacks.d.ts b/TypeScript/10ScopesAndTypes/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/10ScopesAndTypes/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/10ScopesAndTypes/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/10ScopesAndTypes/types/controllers/DialogueController.d.ts b/TypeScript/10ScopesAndTypes/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/10ScopesAndTypes/types/controllers/DialogueController.d.ts +++ b/TypeScript/10ScopesAndTypes/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/10ScopesAndTypes/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/10ScopesAndTypes/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/10ScopesAndTypes/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/10ScopesAndTypes/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/10ScopesAndTypes/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/10ScopesAndTypes/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/10ScopesAndTypes/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/10ScopesAndTypes/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/10ScopesAndTypes/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/10ScopesAndTypes/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/10ScopesAndTypes/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/10ScopesAndTypes/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/10ScopesAndTypes/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/10ScopesAndTypes/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/10ScopesAndTypes/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/10ScopesAndTypes/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/10ScopesAndTypes/types/models/enums/ConfigTypes.d.ts b/TypeScript/10ScopesAndTypes/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/10ScopesAndTypes/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/10ScopesAndTypes/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/10ScopesAndTypes/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/10ScopesAndTypes/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/11BundleLoadingSample/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/11BundleLoadingSample/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/11BundleLoadingSample/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/11BundleLoadingSample/types/controllers/DialogueController.d.ts b/TypeScript/11BundleLoadingSample/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/11BundleLoadingSample/types/controllers/DialogueController.d.ts +++ b/TypeScript/11BundleLoadingSample/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/11BundleLoadingSample/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/11BundleLoadingSample/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/11BundleLoadingSample/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/11BundleLoadingSample/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/11BundleLoadingSample/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/11BundleLoadingSample/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/11BundleLoadingSample/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/11BundleLoadingSample/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/11BundleLoadingSample/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/11BundleLoadingSample/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/11BundleLoadingSample/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/11BundleLoadingSample/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/11BundleLoadingSample/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/11BundleLoadingSample/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/11BundleLoadingSample/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/11BundleLoadingSample/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/11BundleLoadingSample/types/models/enums/ConfigTypes.d.ts b/TypeScript/11BundleLoadingSample/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/11BundleLoadingSample/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/11BundleLoadingSample/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/11BundleLoadingSample/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/11BundleLoadingSample/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/12ClassExtensionOverride/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/12ClassExtensionOverride/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/12ClassExtensionOverride/types/controllers/DialogueController.d.ts b/TypeScript/12ClassExtensionOverride/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/12ClassExtensionOverride/types/controllers/DialogueController.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/12ClassExtensionOverride/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/12ClassExtensionOverride/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/12ClassExtensionOverride/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/12ClassExtensionOverride/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/12ClassExtensionOverride/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/12ClassExtensionOverride/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/12ClassExtensionOverride/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/12ClassExtensionOverride/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/12ClassExtensionOverride/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/12ClassExtensionOverride/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/12ClassExtensionOverride/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/12ClassExtensionOverride/types/models/enums/ConfigTypes.d.ts b/TypeScript/12ClassExtensionOverride/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/12ClassExtensionOverride/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/12ClassExtensionOverride/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/controllers/DialogueController.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/controllers/DialogueController.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 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 @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/models/enums/ConfigTypes.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/13AddTrader/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/13AddTrader/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/13AddTrader/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/13AddTrader/types/controllers/DialogueController.d.ts b/TypeScript/13AddTrader/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/13AddTrader/types/controllers/DialogueController.d.ts +++ b/TypeScript/13AddTrader/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/13AddTrader/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/13AddTrader/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/13AddTrader/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/13AddTrader/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/13AddTrader/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/13AddTrader/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/13AddTrader/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/13AddTrader/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/13AddTrader/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/13AddTrader/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/13AddTrader/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/13AddTrader/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/13AddTrader/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/13AddTrader/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/13AddTrader/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/13AddTrader/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/13AddTrader/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/13AddTrader/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/13AddTrader/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/13AddTrader/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/13AddTrader/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/13AddTrader/types/models/enums/ConfigTypes.d.ts b/TypeScript/13AddTrader/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/13AddTrader/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/13AddTrader/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/13AddTrader/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/13AddTrader/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/13AddTrader/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/13AddTrader/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/13AddTrader/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/14AfterDBLoadHook/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/14AfterDBLoadHook/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/14AfterDBLoadHook/types/controllers/DialogueController.d.ts b/TypeScript/14AfterDBLoadHook/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/14AfterDBLoadHook/types/controllers/DialogueController.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/14AfterDBLoadHook/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/14AfterDBLoadHook/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/14AfterDBLoadHook/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/14AfterDBLoadHook/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/14AfterDBLoadHook/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/14AfterDBLoadHook/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/14AfterDBLoadHook/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/14AfterDBLoadHook/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/14AfterDBLoadHook/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/14AfterDBLoadHook/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/14AfterDBLoadHook/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/14AfterDBLoadHook/types/models/enums/ConfigTypes.d.ts b/TypeScript/14AfterDBLoadHook/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/14AfterDBLoadHook/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/14AfterDBLoadHook/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/15HttpListenerExample/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/15HttpListenerExample/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/15HttpListenerExample/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/15HttpListenerExample/types/controllers/DialogueController.d.ts b/TypeScript/15HttpListenerExample/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/15HttpListenerExample/types/controllers/DialogueController.d.ts +++ b/TypeScript/15HttpListenerExample/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/15HttpListenerExample/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/15HttpListenerExample/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/15HttpListenerExample/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/15HttpListenerExample/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/15HttpListenerExample/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/15HttpListenerExample/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/15HttpListenerExample/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/15HttpListenerExample/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/15HttpListenerExample/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/15HttpListenerExample/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/15HttpListenerExample/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/15HttpListenerExample/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/15HttpListenerExample/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/15HttpListenerExample/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/15HttpListenerExample/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/15HttpListenerExample/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/15HttpListenerExample/types/models/enums/ConfigTypes.d.ts b/TypeScript/15HttpListenerExample/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/15HttpListenerExample/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/15HttpListenerExample/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/15HttpListenerExample/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/15HttpListenerExample/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/15HttpListenerExample/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/16ImporterUtil/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/16ImporterUtil/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/16ImporterUtil/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/16ImporterUtil/types/controllers/DialogueController.d.ts b/TypeScript/16ImporterUtil/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/16ImporterUtil/types/controllers/DialogueController.d.ts +++ b/TypeScript/16ImporterUtil/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/16ImporterUtil/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/16ImporterUtil/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/16ImporterUtil/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/16ImporterUtil/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/16ImporterUtil/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/16ImporterUtil/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/16ImporterUtil/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/16ImporterUtil/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/16ImporterUtil/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/16ImporterUtil/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/16ImporterUtil/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/16ImporterUtil/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/16ImporterUtil/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/16ImporterUtil/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/16ImporterUtil/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/16ImporterUtil/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/16ImporterUtil/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/16ImporterUtil/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/16ImporterUtil/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/16ImporterUtil/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/16ImporterUtil/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/16ImporterUtil/types/models/enums/ConfigTypes.d.ts b/TypeScript/16ImporterUtil/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/16ImporterUtil/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/16ImporterUtil/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/16ImporterUtil/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/16ImporterUtil/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/16ImporterUtil/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/16ImporterUtil/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/16ImporterUtil/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/controllers/DialogueController.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/controllers/DialogueController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/enums/ConfigTypes.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/17AsyncImporterWithDependency1/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/controllers/DialogueController.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/controllers/DialogueController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/enums/ConfigTypes.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/17AsyncImporterWithDependency2/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/controllers/DialogueController.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/controllers/DialogueController.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 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 @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/models/enums/ConfigTypes.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/18.1CustomItemServiceLootBox/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/18CustomItemService/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/18CustomItemService/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/18CustomItemService/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/18CustomItemService/types/controllers/DialogueController.d.ts b/TypeScript/18CustomItemService/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/18CustomItemService/types/controllers/DialogueController.d.ts +++ b/TypeScript/18CustomItemService/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/18CustomItemService/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/18CustomItemService/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/18CustomItemService/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/18CustomItemService/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/18CustomItemService/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/18CustomItemService/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/18CustomItemService/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/18CustomItemService/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/18CustomItemService/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/18CustomItemService/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/18CustomItemService/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/18CustomItemService/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/18CustomItemService/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/18CustomItemService/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/18CustomItemService/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/18CustomItemService/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/18CustomItemService/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/18CustomItemService/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/18CustomItemService/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/18CustomItemService/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/18CustomItemService/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/18CustomItemService/types/models/enums/ConfigTypes.d.ts b/TypeScript/18CustomItemService/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/18CustomItemService/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/18CustomItemService/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/18CustomItemService/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/18CustomItemService/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/18CustomItemService/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/18CustomItemService/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/18CustomItemService/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/19UseExternalLibraries/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/19UseExternalLibraries/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/19UseExternalLibraries/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/19UseExternalLibraries/types/controllers/DialogueController.d.ts b/TypeScript/19UseExternalLibraries/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/19UseExternalLibraries/types/controllers/DialogueController.d.ts +++ b/TypeScript/19UseExternalLibraries/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/19UseExternalLibraries/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/19UseExternalLibraries/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/19UseExternalLibraries/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/19UseExternalLibraries/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/19UseExternalLibraries/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/19UseExternalLibraries/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/19UseExternalLibraries/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/19UseExternalLibraries/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/19UseExternalLibraries/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/19UseExternalLibraries/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/19UseExternalLibraries/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/19UseExternalLibraries/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/19UseExternalLibraries/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/19UseExternalLibraries/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/19UseExternalLibraries/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/19UseExternalLibraries/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/19UseExternalLibraries/types/models/enums/ConfigTypes.d.ts b/TypeScript/19UseExternalLibraries/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/19UseExternalLibraries/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/19UseExternalLibraries/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/19UseExternalLibraries/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/19UseExternalLibraries/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/19UseExternalLibraries/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/19UseExternalLibraries/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/1LogToConsole/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/1LogToConsole/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/1LogToConsole/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/1LogToConsole/types/controllers/DialogueController.d.ts b/TypeScript/1LogToConsole/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/1LogToConsole/types/controllers/DialogueController.d.ts +++ b/TypeScript/1LogToConsole/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/1LogToConsole/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/1LogToConsole/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/1LogToConsole/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/1LogToConsole/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/1LogToConsole/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/1LogToConsole/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/1LogToConsole/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/1LogToConsole/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/1LogToConsole/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/1LogToConsole/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/1LogToConsole/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/1LogToConsole/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/1LogToConsole/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/1LogToConsole/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/1LogToConsole/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/1LogToConsole/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/1LogToConsole/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/1LogToConsole/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/1LogToConsole/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/1LogToConsole/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/1LogToConsole/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/1LogToConsole/types/models/enums/ConfigTypes.d.ts b/TypeScript/1LogToConsole/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/1LogToConsole/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/1LogToConsole/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/1LogToConsole/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/1LogToConsole/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/1LogToConsole/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/1LogToConsole/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/1LogToConsole/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/20CustomChatBot/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/20CustomChatBot/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/20CustomChatBot/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/20CustomChatBot/types/controllers/DialogueController.d.ts b/TypeScript/20CustomChatBot/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/20CustomChatBot/types/controllers/DialogueController.d.ts +++ b/TypeScript/20CustomChatBot/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/20CustomChatBot/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/20CustomChatBot/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/20CustomChatBot/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/20CustomChatBot/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/20CustomChatBot/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/20CustomChatBot/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/20CustomChatBot/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/20CustomChatBot/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/20CustomChatBot/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/20CustomChatBot/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/20CustomChatBot/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/20CustomChatBot/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/20CustomChatBot/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/20CustomChatBot/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/20CustomChatBot/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/20CustomChatBot/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/20CustomChatBot/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/20CustomChatBot/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/20CustomChatBot/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/20CustomChatBot/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/20CustomChatBot/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/20CustomChatBot/types/models/enums/ConfigTypes.d.ts b/TypeScript/20CustomChatBot/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/20CustomChatBot/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/20CustomChatBot/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/20CustomChatBot/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/20CustomChatBot/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/20CustomChatBot/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/20CustomChatBot/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/20CustomChatBot/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/21CustomCommandoCommand/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/21CustomCommandoCommand/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/21CustomCommandoCommand/types/controllers/DialogueController.d.ts b/TypeScript/21CustomCommandoCommand/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/21CustomCommandoCommand/types/controllers/DialogueController.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/21CustomCommandoCommand/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/21CustomCommandoCommand/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/21CustomCommandoCommand/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/21CustomCommandoCommand/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/21CustomCommandoCommand/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/21CustomCommandoCommand/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/21CustomCommandoCommand/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/21CustomCommandoCommand/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/21CustomCommandoCommand/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/21CustomCommandoCommand/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/21CustomCommandoCommand/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/21CustomCommandoCommand/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/21CustomCommandoCommand/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/21CustomCommandoCommand/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/21CustomCommandoCommand/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/21CustomCommandoCommand/types/models/enums/ConfigTypes.d.ts b/TypeScript/21CustomCommandoCommand/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/21CustomCommandoCommand/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/21CustomCommandoCommand/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/21CustomCommandoCommand/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/21CustomCommandoCommand/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/21CustomCommandoCommand/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/21CustomCommandoCommand/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/22CustomSptCommand/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/22CustomSptCommand/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/22CustomSptCommand/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/22CustomSptCommand/types/controllers/DialogueController.d.ts b/TypeScript/22CustomSptCommand/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/22CustomSptCommand/types/controllers/DialogueController.d.ts +++ b/TypeScript/22CustomSptCommand/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/22CustomSptCommand/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/22CustomSptCommand/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/22CustomSptCommand/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/22CustomSptCommand/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/22CustomSptCommand/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/22CustomSptCommand/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/22CustomSptCommand/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/22CustomSptCommand/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/22CustomSptCommand/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/22CustomSptCommand/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/22CustomSptCommand/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/22CustomSptCommand/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/22CustomSptCommand/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/22CustomSptCommand/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/22CustomSptCommand/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/22CustomSptCommand/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/22CustomSptCommand/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/22CustomSptCommand/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/22CustomSptCommand/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/22CustomSptCommand/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/22CustomSptCommand/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/22CustomSptCommand/types/models/enums/ConfigTypes.d.ts b/TypeScript/22CustomSptCommand/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/22CustomSptCommand/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/22CustomSptCommand/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/22CustomSptCommand/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/22CustomSptCommand/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/22CustomSptCommand/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/22CustomSptCommand/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/22CustomSptCommand/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/23CustomAbstractChatBot/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/23CustomAbstractChatBot/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/23CustomAbstractChatBot/types/controllers/DialogueController.d.ts b/TypeScript/23CustomAbstractChatBot/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/23CustomAbstractChatBot/types/controllers/DialogueController.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/23CustomAbstractChatBot/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/23CustomAbstractChatBot/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/23CustomAbstractChatBot/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/23CustomAbstractChatBot/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/23CustomAbstractChatBot/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/23CustomAbstractChatBot/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/23CustomAbstractChatBot/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/23CustomAbstractChatBot/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/23CustomAbstractChatBot/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/23CustomAbstractChatBot/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/23CustomAbstractChatBot/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/23CustomAbstractChatBot/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/23CustomAbstractChatBot/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/23CustomAbstractChatBot/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/23CustomAbstractChatBot/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/23CustomAbstractChatBot/types/models/enums/ConfigTypes.d.ts b/TypeScript/23CustomAbstractChatBot/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/23CustomAbstractChatBot/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/23CustomAbstractChatBot/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/23CustomAbstractChatBot/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/24WebSocket/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/24WebSocket/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/24WebSocket/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/24WebSocket/types/controllers/DialogueController.d.ts b/TypeScript/24WebSocket/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/24WebSocket/types/controllers/DialogueController.d.ts +++ b/TypeScript/24WebSocket/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/24WebSocket/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/24WebSocket/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/24WebSocket/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/24WebSocket/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/24WebSocket/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/24WebSocket/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/24WebSocket/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/24WebSocket/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/24WebSocket/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/24WebSocket/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/24WebSocket/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/24WebSocket/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/24WebSocket/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/24WebSocket/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/24WebSocket/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/24WebSocket/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/24WebSocket/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/24WebSocket/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/24WebSocket/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/24WebSocket/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/24WebSocket/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/24WebSocket/types/models/enums/ConfigTypes.d.ts b/TypeScript/24WebSocket/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/24WebSocket/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/24WebSocket/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/24WebSocket/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/24WebSocket/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/24WebSocket/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/24WebSocket/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/24WebSocket/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/2EditDatabase/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/2EditDatabase/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/2EditDatabase/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/2EditDatabase/types/controllers/DialogueController.d.ts b/TypeScript/2EditDatabase/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/2EditDatabase/types/controllers/DialogueController.d.ts +++ b/TypeScript/2EditDatabase/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/2EditDatabase/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/2EditDatabase/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/2EditDatabase/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/2EditDatabase/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/2EditDatabase/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/2EditDatabase/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/2EditDatabase/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/2EditDatabase/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/2EditDatabase/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/2EditDatabase/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/2EditDatabase/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/2EditDatabase/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/2EditDatabase/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/2EditDatabase/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/2EditDatabase/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/2EditDatabase/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/2EditDatabase/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/2EditDatabase/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/2EditDatabase/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/2EditDatabase/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/2EditDatabase/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/2EditDatabase/types/models/enums/ConfigTypes.d.ts b/TypeScript/2EditDatabase/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/2EditDatabase/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/2EditDatabase/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/2EditDatabase/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/2EditDatabase/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/2EditDatabase/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/2EditDatabase/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/2EditDatabase/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/3GetSptConfigFile/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/3GetSptConfigFile/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/3GetSptConfigFile/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/3GetSptConfigFile/types/controllers/DialogueController.d.ts b/TypeScript/3GetSptConfigFile/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/3GetSptConfigFile/types/controllers/DialogueController.d.ts +++ b/TypeScript/3GetSptConfigFile/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/3GetSptConfigFile/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/3GetSptConfigFile/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/3GetSptConfigFile/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/3GetSptConfigFile/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/3GetSptConfigFile/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/3GetSptConfigFile/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/3GetSptConfigFile/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/3GetSptConfigFile/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/3GetSptConfigFile/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/3GetSptConfigFile/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/3GetSptConfigFile/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/3GetSptConfigFile/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/3GetSptConfigFile/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/3GetSptConfigFile/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/3GetSptConfigFile/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/3GetSptConfigFile/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/3GetSptConfigFile/types/models/enums/ConfigTypes.d.ts b/TypeScript/3GetSptConfigFile/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/3GetSptConfigFile/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/3GetSptConfigFile/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/3GetSptConfigFile/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/3GetSptConfigFile/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/DialogueController.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/DialogueController.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 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 @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/enums/ConfigTypes.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/4UseACustomConfigFile/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/4UseACustomConfigFile/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/4UseACustomConfigFile/types/controllers/DialogueController.d.ts b/TypeScript/4UseACustomConfigFile/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/4UseACustomConfigFile/types/controllers/DialogueController.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/4UseACustomConfigFile/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/4UseACustomConfigFile/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/4UseACustomConfigFile/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/4UseACustomConfigFile/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/4UseACustomConfigFile/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/4UseACustomConfigFile/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/4UseACustomConfigFile/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/4UseACustomConfigFile/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/4UseACustomConfigFile/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/4UseACustomConfigFile/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/4UseACustomConfigFile/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/4UseACustomConfigFile/types/models/enums/ConfigTypes.d.ts b/TypeScript/4UseACustomConfigFile/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/4UseACustomConfigFile/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/4UseACustomConfigFile/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/5ReplaceMethod/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/5ReplaceMethod/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/5ReplaceMethod/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/5ReplaceMethod/types/controllers/DialogueController.d.ts b/TypeScript/5ReplaceMethod/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/5ReplaceMethod/types/controllers/DialogueController.d.ts +++ b/TypeScript/5ReplaceMethod/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/5ReplaceMethod/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/5ReplaceMethod/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/5ReplaceMethod/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/5ReplaceMethod/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/5ReplaceMethod/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/5ReplaceMethod/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/5ReplaceMethod/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/5ReplaceMethod/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/5ReplaceMethod/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/5ReplaceMethod/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/5ReplaceMethod/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/5ReplaceMethod/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/5ReplaceMethod/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/5ReplaceMethod/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/5ReplaceMethod/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/5ReplaceMethod/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/5ReplaceMethod/types/models/enums/ConfigTypes.d.ts b/TypeScript/5ReplaceMethod/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/5ReplaceMethod/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/5ReplaceMethod/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/5ReplaceMethod/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/5ReplaceMethod/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/5ReplaceMethod/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/6ReferenceAnotherClass/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/6ReferenceAnotherClass/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/6ReferenceAnotherClass/types/controllers/DialogueController.d.ts b/TypeScript/6ReferenceAnotherClass/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/6ReferenceAnotherClass/types/controllers/DialogueController.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/6ReferenceAnotherClass/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/6ReferenceAnotherClass/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/6ReferenceAnotherClass/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/6ReferenceAnotherClass/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/6ReferenceAnotherClass/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/6ReferenceAnotherClass/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/6ReferenceAnotherClass/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/6ReferenceAnotherClass/types/models/enums/ConfigTypes.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/6ReferenceAnotherClass/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/6ReferenceAnotherClass/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/7OnLoadHook/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/7OnLoadHook/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/7OnLoadHook/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/7OnLoadHook/types/controllers/DialogueController.d.ts b/TypeScript/7OnLoadHook/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/7OnLoadHook/types/controllers/DialogueController.d.ts +++ b/TypeScript/7OnLoadHook/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/7OnLoadHook/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/7OnLoadHook/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/7OnLoadHook/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/7OnLoadHook/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/7OnLoadHook/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/7OnLoadHook/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/7OnLoadHook/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/7OnLoadHook/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/7OnLoadHook/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/7OnLoadHook/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/7OnLoadHook/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/7OnLoadHook/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/7OnLoadHook/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/7OnLoadHook/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/7OnLoadHook/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/7OnLoadHook/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/7OnLoadHook/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/7OnLoadHook/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/7OnLoadHook/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/7OnLoadHook/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/7OnLoadHook/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/7OnLoadHook/types/models/enums/ConfigTypes.d.ts b/TypeScript/7OnLoadHook/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/7OnLoadHook/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/7OnLoadHook/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/7OnLoadHook/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/7OnLoadHook/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/7OnLoadHook/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/7OnLoadHook/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/7OnLoadHook/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/8OnUpdateHook/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/8OnUpdateHook/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/8OnUpdateHook/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/8OnUpdateHook/types/controllers/DialogueController.d.ts b/TypeScript/8OnUpdateHook/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/8OnUpdateHook/types/controllers/DialogueController.d.ts +++ b/TypeScript/8OnUpdateHook/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/8OnUpdateHook/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/8OnUpdateHook/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/8OnUpdateHook/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/8OnUpdateHook/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/8OnUpdateHook/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/8OnUpdateHook/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/8OnUpdateHook/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/8OnUpdateHook/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/8OnUpdateHook/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/8OnUpdateHook/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/8OnUpdateHook/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/8OnUpdateHook/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/8OnUpdateHook/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/8OnUpdateHook/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/8OnUpdateHook/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/8OnUpdateHook/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/8OnUpdateHook/types/models/enums/ConfigTypes.d.ts b/TypeScript/8OnUpdateHook/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/8OnUpdateHook/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/8OnUpdateHook/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/8OnUpdateHook/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/8OnUpdateHook/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/8OnUpdateHook/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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/callbacks/SaveCallbacks.d.ts b/TypeScript/9RouterHooks/types/callbacks/SaveCallbacks.d.ts index 8f836cb..3d5f212 100644 --- a/TypeScript/9RouterHooks/types/callbacks/SaveCallbacks.d.ts +++ b/TypeScript/9RouterHooks/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/TypeScript/9RouterHooks/types/controllers/DialogueController.d.ts b/TypeScript/9RouterHooks/types/controllers/DialogueController.d.ts index 2f00b13..ded87cf 100644 --- a/TypeScript/9RouterHooks/types/controllers/DialogueController.d.ts +++ b/TypeScript/9RouterHooks/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } 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..87257ca 100644 --- a/TypeScript/9RouterHooks/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/9RouterHooks/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,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/helpers/ProfileHelper.d.ts b/TypeScript/9RouterHooks/types/helpers/ProfileHelper.d.ts index c2871b4..f68c580 100644 --- a/TypeScript/9RouterHooks/types/helpers/ProfileHelper.d.ts +++ b/TypeScript/9RouterHooks/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return 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..3d1e9e3 100644 --- a/TypeScript/9RouterHooks/types/models/eft/common/tables/IQuest.d.ts +++ b/TypeScript/9RouterHooks/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,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/eft/profile/ISearchFriendResponse.d.ts b/TypeScript/9RouterHooks/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7df..628b82c 100644 --- a/TypeScript/9RouterHooks/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/TypeScript/9RouterHooks/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/TypeScript/9RouterHooks/types/models/eft/profile/ISptProfile.d.ts b/TypeScript/9RouterHooks/types/models/eft/profile/ISptProfile.d.ts index aba539b..af8c92f 100644 --- a/TypeScript/9RouterHooks/types/models/eft/profile/ISptProfile.d.ts +++ b/TypeScript/9RouterHooks/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/TypeScript/9RouterHooks/types/models/eft/ws/IWsFriendsListAccept.d.ts b/TypeScript/9RouterHooks/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 0000000..4a96db3 --- /dev/null +++ b/TypeScript/9RouterHooks/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/TypeScript/9RouterHooks/types/models/eft/ws/IWsNotificationEvent.d.ts b/TypeScript/9RouterHooks/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3..de119c8 100644 --- a/TypeScript/9RouterHooks/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/TypeScript/9RouterHooks/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/TypeScript/9RouterHooks/types/models/enums/ConfigTypes.d.ts b/TypeScript/9RouterHooks/types/models/enums/ConfigTypes.d.ts index 2c4483a..5bed6f1 100644 --- a/TypeScript/9RouterHooks/types/models/enums/ConfigTypes.d.ts +++ b/TypeScript/9RouterHooks/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/TypeScript/9RouterHooks/types/models/spt/config/IBackupConfig.d.ts b/TypeScript/9RouterHooks/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 0000000..06bb747 --- /dev/null +++ b/TypeScript/9RouterHooks/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} 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/BackupService.d.ts b/TypeScript/9RouterHooks/types/services/BackupService.d.ts new file mode 100644 index 0000000..aeab6c1 --- /dev/null +++ b/TypeScript/9RouterHooks/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} 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. * From b82b84a5ebf6d5da1f1bf1ec9a28b9cf302bb9e2 Mon Sep 17 00:00:00 2001 From: Echo55 Date: Sun, 15 Dec 2024 11:53:45 +0000 Subject: [PATCH 2/3] Updated 13AddTrader mod example (#42) Co-authored-by: Echo-55 <82003117+Echo-55@users.noreply.github.com> Reviewed-on: https://dev.sp-tarkov.com/chomp/ModExamples/pulls/42 Co-authored-by: Echo55 Co-committed-by: Echo55 --- .../13.1AddTraderWithAssortJSON/db/base.json | 41 +++----------- .../13.1AddTraderWithAssortJSON/src/mod.ts | 6 +- .../src/traderHelpers.ts | 17 ------ TypeScript/13AddTrader/db/base.json | 41 +++----------- TypeScript/13AddTrader/src/mod.ts | 11 ++-- TypeScript/13AddTrader/src/traderHelpers.ts | 55 +++++++------------ 6 files changed, 45 insertions(+), 126 deletions(-) diff --git a/TypeScript/13.1AddTraderWithAssortJSON/db/base.json b/TypeScript/13.1AddTraderWithAssortJSON/db/base.json index d5a7c38..2f4fafb 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/db/base.json +++ b/TypeScript/13.1AddTraderWithAssortJSON/db/base.json @@ -55,39 +55,12 @@ } ], "sell_category": [ - "82e7fac0b7495d72d4083356", - "ac705d3440c1407645e33579", - "dc97aee367144dc03389405d", - "7ffcc96aa06c7e90940330c5", - "e8f46e3ad74b9d862121f9dc", - "5b47574386f77428ca22b33e", - "5b47574386f77428ca22b33f", - "5b5f78dc86f77409407a7f8e", - "5b47574386f77428ca22b346", - "5b47574386f77428ca22b340", - "5b47574386f77428ca22b344", - "5b47574386f77428ca22b342", - "5b47574386f77428ca22b341", - "5b47574386f77428ca22b345", - "5b47574386f77428ca22b343", - "5b5f71b386f774093f2ecf11", - "5b5f71c186f77409407a7ec0", - "5b5f71de86f774093f2ecf13", - "5b5f724186f77447ed5636ad", - "5b5f736886f774094242f193", - "5b5f73ec86f774093e6cb4fd", - "5b5f74cc86f77447ec5d770a", - "5b5f750686f774093e6cb503", - "5b5f751486f77447ec5d770c", - "5b5f752e86f774093e6cb505", - "5b5f754a86f774094242f19b", - "5b5f755f86f77447ec5d770e", - "5b5f757486f774093e6cb507", - "5b5f75b986f77447ec5d7710", - "5b5f75c686f774094242f19f", - "5b5f75e486f77447ec5d7712", - "5b5f760586f774093e6cb509", - "5b5f761f86f774094242f1a1", - "5b5f764186f77447ec5d7714" + "575146b724597720a27126d5", + "635a758bfefc88a93f021b8a", + "55d45d3f4bdc2d972f8b456c", + "5b363dd25acfc4001a598fd2", + "5d1b36a186f7742523398433", + "59e3577886f774176a362503", + "5d6e67fba4b9361bc73bc779" ] } diff --git a/TypeScript/13.1AddTraderWithAssortJSON/src/mod.ts b/TypeScript/13.1AddTraderWithAssortJSON/src/mod.ts index aeb305b..286e4cc 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/src/mod.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/src/mod.ts @@ -23,11 +23,13 @@ import { TraderHelper } from "./traderHelpers"; class SampleTrader implements IPreSptLoadMod, IPostDBLoadMod { private mod: string; + private traderImgPath: string; private logger: ILogger; private traderHelper: TraderHelper; constructor() { - this.mod = "acidphantasm-131AddTraderWithAssortJSON"; // Set name of mod so we can log it to console later - match this to your folder name that's built for \user\mods\ + this.mod = "131AddTraderWithAssortJSON"; // Set name of mod so we can log it to console later - match this to your folder name that's built for \user\mods\ + this.traderImgPath = "res/cat.jpg"; // Set path to trader image } /** @@ -49,7 +51,7 @@ class SampleTrader implements IPreSptLoadMod, IPostDBLoadMod // Create helper class and use it to register our traders image/icon + set its stock refresh time this.traderHelper = new TraderHelper(); - this.traderHelper.registerProfileImage(baseJson, this.mod, preSptModLoader, imageRouter, "cat.jpg"); + imageRouter.addRoute(baseJson.avatar.replace(".jpg", ""), `${preSptModLoader.getModPath(this.mod)}${this.traderImgPath}`); this.traderHelper.setTraderUpdateTime(traderConfig, baseJson, 3600, 4000); // Add trader to trader enum diff --git a/TypeScript/13.1AddTraderWithAssortJSON/src/traderHelpers.ts b/TypeScript/13.1AddTraderWithAssortJSON/src/traderHelpers.ts index dda8c83..60a35d3 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/src/traderHelpers.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/src/traderHelpers.ts @@ -7,23 +7,6 @@ import { JsonUtil } from "@spt/utils/JsonUtil"; export class TraderHelper { - /** - * Add profile picture to our trader - * @param baseJson json file for trader (db/base.json) - * @param modName mod folder name - * @param preSptModLoader mod loader class - used to get the mods file path - * @param imageRouter image router class - used to register the trader image path so we see their image on trader page - * @param traderImageName Filename of the trader icon to use - */ - public registerProfileImage(baseJson: any, modName: string, preSptModLoader: PreSptModLoader, imageRouter: ImageRouter, traderImageName: string): void - { - // Reference the mod "res" folder - const imageFilepath = `./${preSptModLoader.getModPath(modName)}res`; - - // Register a route to point to the profile picture - remember to remove the .jpg from it - imageRouter.addRoute(baseJson.avatar.replace(".jpg", ""), `${imageFilepath}/${traderImageName}`); - } - /** * Add record to trader config to set the refresh time of trader in seconds (default is 60 minutes) * @param traderConfig trader config to add our trader to diff --git a/TypeScript/13AddTrader/db/base.json b/TypeScript/13AddTrader/db/base.json index 53a94d7..6b636e2 100644 --- a/TypeScript/13AddTrader/db/base.json +++ b/TypeScript/13AddTrader/db/base.json @@ -55,39 +55,12 @@ } ], "sell_category": [ - "82e7fac0b7495d72d4083356", - "ac705d3440c1407645e33579", - "dc97aee367144dc03389405d", - "7ffcc96aa06c7e90940330c5", - "e8f46e3ad74b9d862121f9dc", - "5b47574386f77428ca22b33e", - "5b47574386f77428ca22b33f", - "5b5f78dc86f77409407a7f8e", - "5b47574386f77428ca22b346", - "5b47574386f77428ca22b340", - "5b47574386f77428ca22b344", - "5b47574386f77428ca22b342", - "5b47574386f77428ca22b341", - "5b47574386f77428ca22b345", - "5b47574386f77428ca22b343", - "5b5f71b386f774093f2ecf11", - "5b5f71c186f77409407a7ec0", - "5b5f71de86f774093f2ecf13", - "5b5f724186f77447ed5636ad", - "5b5f736886f774094242f193", - "5b5f73ec86f774093e6cb4fd", - "5b5f74cc86f77447ec5d770a", - "5b5f750686f774093e6cb503", - "5b5f751486f77447ec5d770c", - "5b5f752e86f774093e6cb505", - "5b5f754a86f774094242f19b", - "5b5f755f86f77447ec5d770e", - "5b5f757486f774093e6cb507", - "5b5f75b986f77447ec5d7710", - "5b5f75c686f774094242f19f", - "5b5f75e486f77447ec5d7712", - "5b5f760586f774093e6cb509", - "5b5f761f86f774094242f1a1", - "5b5f764186f77447ec5d7714" + "575146b724597720a27126d5", + "635a758bfefc88a93f021b8a", + "55d45d3f4bdc2d972f8b456c", + "5b363dd25acfc4001a598fd2", + "5d1b36a186f7742523398433", + "59e3577886f774176a362503", + "5d6e67fba4b9361bc73bc779" ] } diff --git a/TypeScript/13AddTrader/src/mod.ts b/TypeScript/13AddTrader/src/mod.ts index e284876..260f32e 100644 --- a/TypeScript/13AddTrader/src/mod.ts +++ b/TypeScript/13AddTrader/src/mod.ts @@ -4,7 +4,6 @@ import { DependencyContainer } from "tsyringe"; import { IPreSptLoadMod } from "@spt/models/external/IPreSptLoadMod"; import { IPostDBLoadMod } from "@spt/models/external/IPostDBLoadMod"; import { ILogger } from "@spt/models/spt/utils/ILogger"; -import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; import { DatabaseServer } from "@spt/servers/DatabaseServer"; import { ImageRouter } from "@spt/routers/ImageRouter"; import { ConfigServer } from "@spt/servers/ConfigServer"; @@ -25,6 +24,7 @@ import { ItemTpl } from "@spt/models/enums/ItemTpl"; class SampleTrader implements IPreSptLoadMod, IPostDBLoadMod { private mod: string; + private traderImgPath: string; private logger: ILogger; private traderHelper: TraderHelper; private fluentAssortCreator: FluentAssortCreator; @@ -34,6 +34,7 @@ class SampleTrader implements IPreSptLoadMod, IPostDBLoadMod { constructor() { this.mod = "13AddTrader"; // Set name of mod so we can log it to console later + this.traderImgPath = "res/cat.jpg"; // Set path to trader image // Get base json from /db/ folder this.traderBase = baseJson; this.traderNickname = "Cat" @@ -49,7 +50,6 @@ class SampleTrader implements IPreSptLoadMod, IPostDBLoadMod { this.logger.debug(`[${this.mod}] preSpt Loading... `); // Get SPT code/data we need later - const preSptModLoader: PreSptModLoader = container.resolve("PreSptModLoader"); const imageRouter: ImageRouter = container.resolve("ImageRouter"); const hashUtil: HashUtil = container.resolve("HashUtil"); const configServer = container.resolve("ConfigServer"); @@ -58,12 +58,15 @@ class SampleTrader implements IPreSptLoadMod, IPostDBLoadMod { // IMPORTANT - YOUR TRADER NEEDS A UNIQUE MONGO-ID, ASK IN DISCORD IF YOU DONT KNOW WHAT THAT IS // GOOGLE "mongoid generator" - this.traderBase._id = "66eeef8b2a166b73d2066a7e"; + this.traderBase = { + ...baseJson, + _id: "66eeef8b2a166b73d2066a7e" // This is a unique ID for your trader, also the first key in base.json + }; // Create helper class and use it to register our traders image/icon + set its stock refresh time this.traderHelper = new TraderHelper(); this.fluentAssortCreator = new FluentAssortCreator(hashUtil, this.logger); - this.traderHelper.registerProfileImage(this.traderBase, this.mod, preSptModLoader, imageRouter, "cat.jpg"); + imageRouter.addRoute(this.traderBase.avatar.replace(".jpg", ""), this.traderImgPath); this.traderHelper.setTraderUpdateTime(traderConfig, this.traderBase, 3600, 4000); // Add trader to trader enum diff --git a/TypeScript/13AddTrader/src/traderHelpers.ts b/TypeScript/13AddTrader/src/traderHelpers.ts index c4a8176..58026ad 100644 --- a/TypeScript/13AddTrader/src/traderHelpers.ts +++ b/TypeScript/13AddTrader/src/traderHelpers.ts @@ -1,28 +1,13 @@ -import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; -import { Item } from "@spt/models/eft/common/tables/IItem"; -import { ITraderBase, ITraderAssort } from "@spt/models/eft/common/tables/ITrader"; -import { ITraderConfig, UpdateTime } from "@spt/models/spt/config/ITraderConfig"; -import { IDatabaseTables } from "@spt/models/spt/server/IDatabaseTables"; -import { ImageRouter } from "@spt/routers/ImageRouter"; -import { JsonUtil } from "@spt/utils/JsonUtil"; -import { NewItemIds } from "./newitemIds"; +import {PreSptModLoader} from "@spt/loaders/PreSptModLoader"; +import {IItem} from "@spt/models/eft/common/tables/IItem"; +import {ITraderBase, ITraderAssort} from "@spt/models/eft/common/tables/ITrader"; +import {ITraderConfig, IUpdateTime} from "@spt/models/spt/config/ITraderConfig"; +import {IDatabaseTables} from "@spt/models/spt/server/IDatabaseTables"; +import {ImageRouter} from "@spt/routers/ImageRouter"; +import {JsonUtil} from "@spt/utils/JsonUtil"; +import {NewItemIds} from "./newItemIds"; export class TraderHelper { - /** - * Add profile picture to our trader - * @param baseJson json file for trader (db/base.json) - * @param modName mod folder name - * @param preSptModLoader mod loader class - used to get the mods file path - * @param imageRouter image router class - used to register the trader image path so we see their image on trader page - * @param traderImageName Filename of the trader icon to use - */ - public registerProfileImage(baseJson: any, modName: string, preSptModLoader: PreSptModLoader, imageRouter: ImageRouter, traderImageName: string): void { - // Reference the mod "res" folder - const imageFilepath = `./${preSptModLoader.getModPath(modName)}res`; - - // Register a route to point to the profile picture - remember to remove the .jpg from it - imageRouter.addRoute(baseJson.avatar.replace(".jpg", ""), `${imageFilepath}/${traderImageName}`); - } /** * Add record to trader config to set the refresh time of trader in seconds (default is 60 minutes) @@ -33,7 +18,7 @@ export class TraderHelper { */ public setTraderUpdateTime(traderConfig: ITraderConfig, baseJson: any, refreshTimeSecondsMin: number, refreshTimeSecondsMax: number): void { // Add refresh time in seconds to config - const traderRefreshRecord: UpdateTime = { + const traderRefreshRecord: IUpdateTime = { traderId: baseJson._id, seconds: { min: refreshTimeSecondsMin, @@ -83,9 +68,9 @@ export class TraderHelper { * Create a weapon from scratch, ready to be added to trader * @returns Item[] */ - public createGlock(): Item[] { + public createGlock(): IItem[] { // Create an array ready to hold weapon + all mods - const glock: Item[] = []; + const glock: IItem[] = []; // Add the base first glock.push({ // Add the base weapon first @@ -153,15 +138,15 @@ export class TraderHelper { } /** - * Add traders name/location/description to the locale table - * @param baseJson json file for trader (db/base.json) - * @param tables database tables - * @param fullName Complete name of trader - * @param firstName First name of trader - * @param nickName Nickname of trader - * @param location Location of trader (e.g. "Here in the cat shop") - * @param description Description of trader - */ + * Add traders name/location/description to the locale table + * @param baseJson json file for trader (db/base.json) + * @param tables database tables + * @param fullName Complete name of trader + * @param firstName First name of trader + * @param nickName Nickname of trader + * @param location Location of trader (e.g. "Here in the cat shop") + * @param description Description of trader + */ public addTraderToLocales(baseJson: any, tables: IDatabaseTables, fullName: string, firstName: string, nickName: string, location: string, description: string) { // For each language, add locale for the new trader const locales = Object.values(tables.locales.global); From 780be737ab54029f1d55d967994eb657291accb1 Mon Sep 17 00:00:00 2001 From: Chomp Date: Tue, 24 Dec 2024 09:48:16 +0000 Subject: [PATCH 3/3] Updated types --- .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- TypeScript/10ScopesAndTypes/types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- .../11BundleLoadingSample/types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- .../12ClassExtensionOverride/types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- .../types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../13AddTrader/types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../13AddTrader/types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../13AddTrader/types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- TypeScript/13AddTrader/types/utils/App.d.ts | 2 +- .../13AddTrader/types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- TypeScript/14AfterDBLoadHook/types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- .../15HttpListenerExample/types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- TypeScript/16ImporterUtil/types/utils/App.d.ts | 2 +- .../16ImporterUtil/types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- .../types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- .../types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- .../types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- .../18CustomItemService/types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- .../19UseExternalLibraries/types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- TypeScript/1LogToConsole/types/utils/App.d.ts | 2 +- .../1LogToConsole/types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- TypeScript/20CustomChatBot/types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- .../21CustomCommandoCommand/types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- TypeScript/22CustomSptCommand/types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- .../23CustomAbstractChatBot/types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../24WebSocket/types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../24WebSocket/types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../24WebSocket/types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- TypeScript/24WebSocket/types/utils/App.d.ts | 2 +- .../24WebSocket/types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- TypeScript/2EditDatabase/types/utils/App.d.ts | 2 +- .../2EditDatabase/types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- TypeScript/3GetSptConfigFile/types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- .../types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- .../4UseACustomConfigFile/types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- TypeScript/5ReplaceMethod/types/utils/App.d.ts | 2 +- .../5ReplaceMethod/types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- .../6ReferenceAnotherClass/types/utils/App.d.ts | 2 +- .../types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../7OnLoadHook/types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../7OnLoadHook/types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../7OnLoadHook/types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- TypeScript/7OnLoadHook/types/utils/App.d.ts | 2 +- .../7OnLoadHook/types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- TypeScript/8OnUpdateHook/types/utils/App.d.ts | 2 +- .../8OnUpdateHook/types/utils/ProgressWriter.d.ts | 13 +++++++++++++ .../types/generators/BotGenerator.d.ts | 12 ++++++++++-- .../types/helpers/RagfairOfferHelper.d.ts | 12 ++++++++++++ .../types/models/eft/common/tables/IBotBase.d.ts | 1 + .../types/models/spt/config/IInventoryConfig.d.ts | 2 ++ .../types/models/spt/config/IPmcConfig.d.ts | 2 ++ .../types/models/spt/config/IRagfairConfig.d.ts | 2 ++ .../models/spt/config/ISeasonalEventConfig.d.ts | 2 ++ .../types/services/BotNameService.d.ts | 14 +++++++++----- .../types/services/DatabaseService.d.ts | 4 ++-- .../types/services/InsuranceService.d.ts | 14 -------------- .../types/services/PaymentService.d.ts | 6 +++++- .../types/services/PostDbLoadService.d.ts | 2 ++ .../types/services/ProfileFixerService.d.ts | 6 ++++++ .../types/services/SeasonalEventService.d.ts | 13 ++++++++++++- TypeScript/9RouterHooks/types/utils/App.d.ts | 2 +- .../9RouterHooks/types/utils/ProgressWriter.d.ts | 13 +++++++++++++ 448 files changed, 2268 insertions(+), 728 deletions(-) create mode 100644 TypeScript/10ScopesAndTypes/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/11BundleLoadingSample/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/12ClassExtensionOverride/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/13.1AddTraderWithAssortJSON/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/13AddTrader/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/14AfterDBLoadHook/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/15HttpListenerExample/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/16ImporterUtil/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/17AsyncImporterWithDependency1/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/17AsyncImporterWithDependency2/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/18.1CustomItemServiceLootBox/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/18CustomItemService/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/19UseExternalLibraries/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/1LogToConsole/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/20CustomChatBot/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/21CustomCommandoCommand/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/22CustomSptCommand/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/23CustomAbstractChatBot/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/24WebSocket/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/2EditDatabase/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/3GetSptConfigFile/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/4UseACustomConfigFile/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/5ReplaceMethod/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/6ReferenceAnotherClass/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/7OnLoadHook/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/8OnUpdateHook/types/utils/ProgressWriter.d.ts create mode 100644 TypeScript/9RouterHooks/types/utils/ProgressWriter.d.ts diff --git a/TypeScript/10ScopesAndTypes/types/generators/BotGenerator.d.ts b/TypeScript/10ScopesAndTypes/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/10ScopesAndTypes/types/generators/BotGenerator.d.ts +++ b/TypeScript/10ScopesAndTypes/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/10ScopesAndTypes/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/10ScopesAndTypes/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/10ScopesAndTypes/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/10ScopesAndTypes/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/10ScopesAndTypes/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/10ScopesAndTypes/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/10ScopesAndTypes/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/10ScopesAndTypes/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/10ScopesAndTypes/types/services/BotNameService.d.ts b/TypeScript/10ScopesAndTypes/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/10ScopesAndTypes/types/services/BotNameService.d.ts +++ b/TypeScript/10ScopesAndTypes/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/10ScopesAndTypes/types/services/DatabaseService.d.ts b/TypeScript/10ScopesAndTypes/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/10ScopesAndTypes/types/services/DatabaseService.d.ts +++ b/TypeScript/10ScopesAndTypes/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/10ScopesAndTypes/types/services/InsuranceService.d.ts b/TypeScript/10ScopesAndTypes/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/10ScopesAndTypes/types/services/InsuranceService.d.ts +++ b/TypeScript/10ScopesAndTypes/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/10ScopesAndTypes/types/services/PaymentService.d.ts b/TypeScript/10ScopesAndTypes/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/10ScopesAndTypes/types/services/PaymentService.d.ts +++ b/TypeScript/10ScopesAndTypes/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/10ScopesAndTypes/types/services/PostDbLoadService.d.ts b/TypeScript/10ScopesAndTypes/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/10ScopesAndTypes/types/services/PostDbLoadService.d.ts +++ b/TypeScript/10ScopesAndTypes/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/10ScopesAndTypes/types/services/ProfileFixerService.d.ts b/TypeScript/10ScopesAndTypes/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/10ScopesAndTypes/types/services/ProfileFixerService.d.ts +++ b/TypeScript/10ScopesAndTypes/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/10ScopesAndTypes/types/services/SeasonalEventService.d.ts b/TypeScript/10ScopesAndTypes/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/10ScopesAndTypes/types/services/SeasonalEventService.d.ts +++ b/TypeScript/10ScopesAndTypes/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/10ScopesAndTypes/types/utils/App.d.ts b/TypeScript/10ScopesAndTypes/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/10ScopesAndTypes/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/10ScopesAndTypes/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/11BundleLoadingSample/types/generators/BotGenerator.d.ts b/TypeScript/11BundleLoadingSample/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/11BundleLoadingSample/types/generators/BotGenerator.d.ts +++ b/TypeScript/11BundleLoadingSample/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/11BundleLoadingSample/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/11BundleLoadingSample/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/11BundleLoadingSample/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/11BundleLoadingSample/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/11BundleLoadingSample/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/11BundleLoadingSample/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/11BundleLoadingSample/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/11BundleLoadingSample/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/11BundleLoadingSample/types/services/BotNameService.d.ts b/TypeScript/11BundleLoadingSample/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/11BundleLoadingSample/types/services/BotNameService.d.ts +++ b/TypeScript/11BundleLoadingSample/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/11BundleLoadingSample/types/services/DatabaseService.d.ts b/TypeScript/11BundleLoadingSample/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/11BundleLoadingSample/types/services/DatabaseService.d.ts +++ b/TypeScript/11BundleLoadingSample/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/11BundleLoadingSample/types/services/InsuranceService.d.ts b/TypeScript/11BundleLoadingSample/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/11BundleLoadingSample/types/services/InsuranceService.d.ts +++ b/TypeScript/11BundleLoadingSample/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/11BundleLoadingSample/types/services/PaymentService.d.ts b/TypeScript/11BundleLoadingSample/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/11BundleLoadingSample/types/services/PaymentService.d.ts +++ b/TypeScript/11BundleLoadingSample/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/11BundleLoadingSample/types/services/PostDbLoadService.d.ts b/TypeScript/11BundleLoadingSample/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/11BundleLoadingSample/types/services/PostDbLoadService.d.ts +++ b/TypeScript/11BundleLoadingSample/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/11BundleLoadingSample/types/services/ProfileFixerService.d.ts b/TypeScript/11BundleLoadingSample/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/11BundleLoadingSample/types/services/ProfileFixerService.d.ts +++ b/TypeScript/11BundleLoadingSample/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/11BundleLoadingSample/types/services/SeasonalEventService.d.ts b/TypeScript/11BundleLoadingSample/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/11BundleLoadingSample/types/services/SeasonalEventService.d.ts +++ b/TypeScript/11BundleLoadingSample/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/11BundleLoadingSample/types/utils/App.d.ts b/TypeScript/11BundleLoadingSample/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/11BundleLoadingSample/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/11BundleLoadingSample/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/12ClassExtensionOverride/types/generators/BotGenerator.d.ts b/TypeScript/12ClassExtensionOverride/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/12ClassExtensionOverride/types/generators/BotGenerator.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/12ClassExtensionOverride/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/12ClassExtensionOverride/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/12ClassExtensionOverride/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/12ClassExtensionOverride/types/services/BotNameService.d.ts b/TypeScript/12ClassExtensionOverride/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/12ClassExtensionOverride/types/services/BotNameService.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/12ClassExtensionOverride/types/services/DatabaseService.d.ts b/TypeScript/12ClassExtensionOverride/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/12ClassExtensionOverride/types/services/DatabaseService.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/12ClassExtensionOverride/types/services/InsuranceService.d.ts b/TypeScript/12ClassExtensionOverride/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/12ClassExtensionOverride/types/services/InsuranceService.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/12ClassExtensionOverride/types/services/PaymentService.d.ts b/TypeScript/12ClassExtensionOverride/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/12ClassExtensionOverride/types/services/PaymentService.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/12ClassExtensionOverride/types/services/PostDbLoadService.d.ts b/TypeScript/12ClassExtensionOverride/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/12ClassExtensionOverride/types/services/PostDbLoadService.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/12ClassExtensionOverride/types/services/ProfileFixerService.d.ts b/TypeScript/12ClassExtensionOverride/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/12ClassExtensionOverride/types/services/ProfileFixerService.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/12ClassExtensionOverride/types/services/SeasonalEventService.d.ts b/TypeScript/12ClassExtensionOverride/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/12ClassExtensionOverride/types/services/SeasonalEventService.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/12ClassExtensionOverride/types/utils/App.d.ts b/TypeScript/12ClassExtensionOverride/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/12ClassExtensionOverride/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/12ClassExtensionOverride/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/generators/BotGenerator.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/generators/BotGenerator.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/services/BotNameService.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/services/BotNameService.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/services/DatabaseService.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/services/DatabaseService.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/services/InsuranceService.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/services/InsuranceService.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/services/PaymentService.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/services/PaymentService.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/services/PostDbLoadService.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/services/PostDbLoadService.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/services/ProfileFixerService.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/services/ProfileFixerService.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/services/SeasonalEventService.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/13.1AddTraderWithAssortJSON/types/services/SeasonalEventService.d.ts +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/13.1AddTraderWithAssortJSON/types/utils/App.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/13.1AddTraderWithAssortJSON/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/13.1AddTraderWithAssortJSON/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/13AddTrader/types/generators/BotGenerator.d.ts b/TypeScript/13AddTrader/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/13AddTrader/types/generators/BotGenerator.d.ts +++ b/TypeScript/13AddTrader/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/13AddTrader/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/13AddTrader/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/13AddTrader/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/13AddTrader/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/13AddTrader/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/13AddTrader/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/13AddTrader/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/13AddTrader/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/13AddTrader/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/13AddTrader/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/13AddTrader/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/13AddTrader/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/13AddTrader/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/13AddTrader/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/13AddTrader/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/13AddTrader/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/13AddTrader/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/13AddTrader/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/13AddTrader/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/13AddTrader/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/13AddTrader/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/13AddTrader/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/13AddTrader/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/13AddTrader/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/13AddTrader/types/services/BotNameService.d.ts b/TypeScript/13AddTrader/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/13AddTrader/types/services/BotNameService.d.ts +++ b/TypeScript/13AddTrader/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/13AddTrader/types/services/DatabaseService.d.ts b/TypeScript/13AddTrader/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/13AddTrader/types/services/DatabaseService.d.ts +++ b/TypeScript/13AddTrader/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/13AddTrader/types/services/InsuranceService.d.ts b/TypeScript/13AddTrader/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/13AddTrader/types/services/InsuranceService.d.ts +++ b/TypeScript/13AddTrader/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/13AddTrader/types/services/PaymentService.d.ts b/TypeScript/13AddTrader/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/13AddTrader/types/services/PaymentService.d.ts +++ b/TypeScript/13AddTrader/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/13AddTrader/types/services/PostDbLoadService.d.ts b/TypeScript/13AddTrader/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/13AddTrader/types/services/PostDbLoadService.d.ts +++ b/TypeScript/13AddTrader/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/13AddTrader/types/services/ProfileFixerService.d.ts b/TypeScript/13AddTrader/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/13AddTrader/types/services/ProfileFixerService.d.ts +++ b/TypeScript/13AddTrader/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/13AddTrader/types/services/SeasonalEventService.d.ts b/TypeScript/13AddTrader/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/13AddTrader/types/services/SeasonalEventService.d.ts +++ b/TypeScript/13AddTrader/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/13AddTrader/types/utils/App.d.ts b/TypeScript/13AddTrader/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/13AddTrader/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/13AddTrader/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/14AfterDBLoadHook/types/generators/BotGenerator.d.ts b/TypeScript/14AfterDBLoadHook/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/14AfterDBLoadHook/types/generators/BotGenerator.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/14AfterDBLoadHook/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/14AfterDBLoadHook/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/14AfterDBLoadHook/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/14AfterDBLoadHook/types/services/BotNameService.d.ts b/TypeScript/14AfterDBLoadHook/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/14AfterDBLoadHook/types/services/BotNameService.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/14AfterDBLoadHook/types/services/DatabaseService.d.ts b/TypeScript/14AfterDBLoadHook/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/14AfterDBLoadHook/types/services/DatabaseService.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/14AfterDBLoadHook/types/services/InsuranceService.d.ts b/TypeScript/14AfterDBLoadHook/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/14AfterDBLoadHook/types/services/InsuranceService.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/14AfterDBLoadHook/types/services/PaymentService.d.ts b/TypeScript/14AfterDBLoadHook/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/14AfterDBLoadHook/types/services/PaymentService.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/14AfterDBLoadHook/types/services/PostDbLoadService.d.ts b/TypeScript/14AfterDBLoadHook/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/14AfterDBLoadHook/types/services/PostDbLoadService.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/14AfterDBLoadHook/types/services/ProfileFixerService.d.ts b/TypeScript/14AfterDBLoadHook/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/14AfterDBLoadHook/types/services/ProfileFixerService.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/14AfterDBLoadHook/types/services/SeasonalEventService.d.ts b/TypeScript/14AfterDBLoadHook/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/14AfterDBLoadHook/types/services/SeasonalEventService.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/14AfterDBLoadHook/types/utils/App.d.ts b/TypeScript/14AfterDBLoadHook/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/14AfterDBLoadHook/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/14AfterDBLoadHook/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/15HttpListenerExample/types/generators/BotGenerator.d.ts b/TypeScript/15HttpListenerExample/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/15HttpListenerExample/types/generators/BotGenerator.d.ts +++ b/TypeScript/15HttpListenerExample/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/15HttpListenerExample/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/15HttpListenerExample/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/15HttpListenerExample/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/15HttpListenerExample/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/15HttpListenerExample/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/15HttpListenerExample/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/15HttpListenerExample/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/15HttpListenerExample/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/15HttpListenerExample/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/15HttpListenerExample/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/15HttpListenerExample/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/15HttpListenerExample/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/15HttpListenerExample/types/services/BotNameService.d.ts b/TypeScript/15HttpListenerExample/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/15HttpListenerExample/types/services/BotNameService.d.ts +++ b/TypeScript/15HttpListenerExample/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/15HttpListenerExample/types/services/DatabaseService.d.ts b/TypeScript/15HttpListenerExample/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/15HttpListenerExample/types/services/DatabaseService.d.ts +++ b/TypeScript/15HttpListenerExample/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/15HttpListenerExample/types/services/InsuranceService.d.ts b/TypeScript/15HttpListenerExample/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/15HttpListenerExample/types/services/InsuranceService.d.ts +++ b/TypeScript/15HttpListenerExample/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/15HttpListenerExample/types/services/PaymentService.d.ts b/TypeScript/15HttpListenerExample/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/15HttpListenerExample/types/services/PaymentService.d.ts +++ b/TypeScript/15HttpListenerExample/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/15HttpListenerExample/types/services/PostDbLoadService.d.ts b/TypeScript/15HttpListenerExample/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/15HttpListenerExample/types/services/PostDbLoadService.d.ts +++ b/TypeScript/15HttpListenerExample/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/15HttpListenerExample/types/services/ProfileFixerService.d.ts b/TypeScript/15HttpListenerExample/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/15HttpListenerExample/types/services/ProfileFixerService.d.ts +++ b/TypeScript/15HttpListenerExample/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/15HttpListenerExample/types/services/SeasonalEventService.d.ts b/TypeScript/15HttpListenerExample/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/15HttpListenerExample/types/services/SeasonalEventService.d.ts +++ b/TypeScript/15HttpListenerExample/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/15HttpListenerExample/types/utils/App.d.ts b/TypeScript/15HttpListenerExample/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/15HttpListenerExample/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/15HttpListenerExample/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/16ImporterUtil/types/generators/BotGenerator.d.ts b/TypeScript/16ImporterUtil/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/16ImporterUtil/types/generators/BotGenerator.d.ts +++ b/TypeScript/16ImporterUtil/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/16ImporterUtil/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/16ImporterUtil/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/16ImporterUtil/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/16ImporterUtil/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/16ImporterUtil/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/16ImporterUtil/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/16ImporterUtil/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/16ImporterUtil/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/16ImporterUtil/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/16ImporterUtil/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/16ImporterUtil/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/16ImporterUtil/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/16ImporterUtil/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/16ImporterUtil/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/16ImporterUtil/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/16ImporterUtil/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/16ImporterUtil/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/16ImporterUtil/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/16ImporterUtil/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/16ImporterUtil/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/16ImporterUtil/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/16ImporterUtil/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/16ImporterUtil/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/16ImporterUtil/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/16ImporterUtil/types/services/BotNameService.d.ts b/TypeScript/16ImporterUtil/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/16ImporterUtil/types/services/BotNameService.d.ts +++ b/TypeScript/16ImporterUtil/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/16ImporterUtil/types/services/DatabaseService.d.ts b/TypeScript/16ImporterUtil/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/16ImporterUtil/types/services/DatabaseService.d.ts +++ b/TypeScript/16ImporterUtil/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/16ImporterUtil/types/services/InsuranceService.d.ts b/TypeScript/16ImporterUtil/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/16ImporterUtil/types/services/InsuranceService.d.ts +++ b/TypeScript/16ImporterUtil/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/16ImporterUtil/types/services/PaymentService.d.ts b/TypeScript/16ImporterUtil/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/16ImporterUtil/types/services/PaymentService.d.ts +++ b/TypeScript/16ImporterUtil/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/16ImporterUtil/types/services/PostDbLoadService.d.ts b/TypeScript/16ImporterUtil/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/16ImporterUtil/types/services/PostDbLoadService.d.ts +++ b/TypeScript/16ImporterUtil/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/16ImporterUtil/types/services/ProfileFixerService.d.ts b/TypeScript/16ImporterUtil/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/16ImporterUtil/types/services/ProfileFixerService.d.ts +++ b/TypeScript/16ImporterUtil/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/16ImporterUtil/types/services/SeasonalEventService.d.ts b/TypeScript/16ImporterUtil/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/16ImporterUtil/types/services/SeasonalEventService.d.ts +++ b/TypeScript/16ImporterUtil/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/16ImporterUtil/types/utils/App.d.ts b/TypeScript/16ImporterUtil/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/16ImporterUtil/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/16ImporterUtil/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/17AsyncImporterWithDependency1/types/generators/BotGenerator.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/generators/BotGenerator.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/17AsyncImporterWithDependency1/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/services/BotNameService.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/services/BotNameService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/17AsyncImporterWithDependency1/types/services/DatabaseService.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/services/DatabaseService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/17AsyncImporterWithDependency1/types/services/InsuranceService.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/services/InsuranceService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/17AsyncImporterWithDependency1/types/services/PaymentService.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/services/PaymentService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/17AsyncImporterWithDependency1/types/services/PostDbLoadService.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/services/PostDbLoadService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/17AsyncImporterWithDependency1/types/services/ProfileFixerService.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/services/ProfileFixerService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/17AsyncImporterWithDependency1/types/services/SeasonalEventService.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/services/SeasonalEventService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/17AsyncImporterWithDependency1/types/utils/App.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/17AsyncImporterWithDependency1/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/17AsyncImporterWithDependency2/types/generators/BotGenerator.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/generators/BotGenerator.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/17AsyncImporterWithDependency2/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/services/BotNameService.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/services/BotNameService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/17AsyncImporterWithDependency2/types/services/DatabaseService.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/services/DatabaseService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/17AsyncImporterWithDependency2/types/services/InsuranceService.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/services/InsuranceService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/17AsyncImporterWithDependency2/types/services/PaymentService.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/services/PaymentService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/17AsyncImporterWithDependency2/types/services/PostDbLoadService.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/services/PostDbLoadService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/17AsyncImporterWithDependency2/types/services/ProfileFixerService.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/services/ProfileFixerService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/17AsyncImporterWithDependency2/types/services/SeasonalEventService.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/services/SeasonalEventService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/17AsyncImporterWithDependency2/types/utils/App.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/17AsyncImporterWithDependency2/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/generators/BotGenerator.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/generators/BotGenerator.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/services/BotNameService.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/services/BotNameService.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/services/DatabaseService.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/services/DatabaseService.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/services/InsuranceService.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/services/InsuranceService.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/services/PaymentService.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/services/PaymentService.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/services/PostDbLoadService.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/services/PostDbLoadService.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/services/ProfileFixerService.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/services/ProfileFixerService.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/services/SeasonalEventService.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/18.1CustomItemServiceLootBox/types/services/SeasonalEventService.d.ts +++ b/TypeScript/18.1CustomItemServiceLootBox/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/18.1CustomItemServiceLootBox/types/utils/App.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/18.1CustomItemServiceLootBox/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/18.1CustomItemServiceLootBox/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/18CustomItemService/types/generators/BotGenerator.d.ts b/TypeScript/18CustomItemService/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/18CustomItemService/types/generators/BotGenerator.d.ts +++ b/TypeScript/18CustomItemService/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/18CustomItemService/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/18CustomItemService/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/18CustomItemService/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/18CustomItemService/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/18CustomItemService/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/18CustomItemService/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/18CustomItemService/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/18CustomItemService/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/18CustomItemService/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/18CustomItemService/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/18CustomItemService/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/18CustomItemService/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/18CustomItemService/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/18CustomItemService/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/18CustomItemService/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/18CustomItemService/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/18CustomItemService/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/18CustomItemService/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/18CustomItemService/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/18CustomItemService/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/18CustomItemService/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/18CustomItemService/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/18CustomItemService/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/18CustomItemService/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/18CustomItemService/types/services/BotNameService.d.ts b/TypeScript/18CustomItemService/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/18CustomItemService/types/services/BotNameService.d.ts +++ b/TypeScript/18CustomItemService/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/18CustomItemService/types/services/DatabaseService.d.ts b/TypeScript/18CustomItemService/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/18CustomItemService/types/services/DatabaseService.d.ts +++ b/TypeScript/18CustomItemService/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/18CustomItemService/types/services/InsuranceService.d.ts b/TypeScript/18CustomItemService/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/18CustomItemService/types/services/InsuranceService.d.ts +++ b/TypeScript/18CustomItemService/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/18CustomItemService/types/services/PaymentService.d.ts b/TypeScript/18CustomItemService/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/18CustomItemService/types/services/PaymentService.d.ts +++ b/TypeScript/18CustomItemService/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/18CustomItemService/types/services/PostDbLoadService.d.ts b/TypeScript/18CustomItemService/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/18CustomItemService/types/services/PostDbLoadService.d.ts +++ b/TypeScript/18CustomItemService/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/18CustomItemService/types/services/ProfileFixerService.d.ts b/TypeScript/18CustomItemService/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/18CustomItemService/types/services/ProfileFixerService.d.ts +++ b/TypeScript/18CustomItemService/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/18CustomItemService/types/services/SeasonalEventService.d.ts b/TypeScript/18CustomItemService/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/18CustomItemService/types/services/SeasonalEventService.d.ts +++ b/TypeScript/18CustomItemService/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/18CustomItemService/types/utils/App.d.ts b/TypeScript/18CustomItemService/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/18CustomItemService/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/18CustomItemService/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/19UseExternalLibraries/types/generators/BotGenerator.d.ts b/TypeScript/19UseExternalLibraries/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/19UseExternalLibraries/types/generators/BotGenerator.d.ts +++ b/TypeScript/19UseExternalLibraries/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/19UseExternalLibraries/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/19UseExternalLibraries/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/19UseExternalLibraries/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/19UseExternalLibraries/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/19UseExternalLibraries/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/19UseExternalLibraries/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/19UseExternalLibraries/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/19UseExternalLibraries/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/19UseExternalLibraries/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/19UseExternalLibraries/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/19UseExternalLibraries/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/19UseExternalLibraries/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/19UseExternalLibraries/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/19UseExternalLibraries/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/19UseExternalLibraries/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/19UseExternalLibraries/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/19UseExternalLibraries/types/services/BotNameService.d.ts b/TypeScript/19UseExternalLibraries/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/19UseExternalLibraries/types/services/BotNameService.d.ts +++ b/TypeScript/19UseExternalLibraries/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/19UseExternalLibraries/types/services/DatabaseService.d.ts b/TypeScript/19UseExternalLibraries/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/19UseExternalLibraries/types/services/DatabaseService.d.ts +++ b/TypeScript/19UseExternalLibraries/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/19UseExternalLibraries/types/services/InsuranceService.d.ts b/TypeScript/19UseExternalLibraries/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/19UseExternalLibraries/types/services/InsuranceService.d.ts +++ b/TypeScript/19UseExternalLibraries/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/19UseExternalLibraries/types/services/PaymentService.d.ts b/TypeScript/19UseExternalLibraries/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/19UseExternalLibraries/types/services/PaymentService.d.ts +++ b/TypeScript/19UseExternalLibraries/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/19UseExternalLibraries/types/services/PostDbLoadService.d.ts b/TypeScript/19UseExternalLibraries/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/19UseExternalLibraries/types/services/PostDbLoadService.d.ts +++ b/TypeScript/19UseExternalLibraries/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/19UseExternalLibraries/types/services/ProfileFixerService.d.ts b/TypeScript/19UseExternalLibraries/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/19UseExternalLibraries/types/services/ProfileFixerService.d.ts +++ b/TypeScript/19UseExternalLibraries/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/19UseExternalLibraries/types/services/SeasonalEventService.d.ts b/TypeScript/19UseExternalLibraries/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/19UseExternalLibraries/types/services/SeasonalEventService.d.ts +++ b/TypeScript/19UseExternalLibraries/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/19UseExternalLibraries/types/utils/App.d.ts b/TypeScript/19UseExternalLibraries/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/19UseExternalLibraries/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/19UseExternalLibraries/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/1LogToConsole/types/generators/BotGenerator.d.ts b/TypeScript/1LogToConsole/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/1LogToConsole/types/generators/BotGenerator.d.ts +++ b/TypeScript/1LogToConsole/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/1LogToConsole/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/1LogToConsole/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/1LogToConsole/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/1LogToConsole/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/1LogToConsole/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/1LogToConsole/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/1LogToConsole/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/1LogToConsole/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/1LogToConsole/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/1LogToConsole/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/1LogToConsole/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/1LogToConsole/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/1LogToConsole/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/1LogToConsole/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/1LogToConsole/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/1LogToConsole/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/1LogToConsole/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/1LogToConsole/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/1LogToConsole/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/1LogToConsole/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/1LogToConsole/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/1LogToConsole/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/1LogToConsole/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/1LogToConsole/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/1LogToConsole/types/services/BotNameService.d.ts b/TypeScript/1LogToConsole/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/1LogToConsole/types/services/BotNameService.d.ts +++ b/TypeScript/1LogToConsole/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/1LogToConsole/types/services/DatabaseService.d.ts b/TypeScript/1LogToConsole/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/1LogToConsole/types/services/DatabaseService.d.ts +++ b/TypeScript/1LogToConsole/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/1LogToConsole/types/services/InsuranceService.d.ts b/TypeScript/1LogToConsole/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/1LogToConsole/types/services/InsuranceService.d.ts +++ b/TypeScript/1LogToConsole/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/1LogToConsole/types/services/PaymentService.d.ts b/TypeScript/1LogToConsole/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/1LogToConsole/types/services/PaymentService.d.ts +++ b/TypeScript/1LogToConsole/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/1LogToConsole/types/services/PostDbLoadService.d.ts b/TypeScript/1LogToConsole/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/1LogToConsole/types/services/PostDbLoadService.d.ts +++ b/TypeScript/1LogToConsole/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/1LogToConsole/types/services/ProfileFixerService.d.ts b/TypeScript/1LogToConsole/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/1LogToConsole/types/services/ProfileFixerService.d.ts +++ b/TypeScript/1LogToConsole/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/1LogToConsole/types/services/SeasonalEventService.d.ts b/TypeScript/1LogToConsole/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/1LogToConsole/types/services/SeasonalEventService.d.ts +++ b/TypeScript/1LogToConsole/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/1LogToConsole/types/utils/App.d.ts b/TypeScript/1LogToConsole/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/1LogToConsole/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/1LogToConsole/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/20CustomChatBot/types/generators/BotGenerator.d.ts b/TypeScript/20CustomChatBot/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/20CustomChatBot/types/generators/BotGenerator.d.ts +++ b/TypeScript/20CustomChatBot/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/20CustomChatBot/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/20CustomChatBot/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/20CustomChatBot/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/20CustomChatBot/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/20CustomChatBot/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/20CustomChatBot/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/20CustomChatBot/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/20CustomChatBot/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/20CustomChatBot/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/20CustomChatBot/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/20CustomChatBot/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/20CustomChatBot/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/20CustomChatBot/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/20CustomChatBot/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/20CustomChatBot/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/20CustomChatBot/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/20CustomChatBot/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/20CustomChatBot/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/20CustomChatBot/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/20CustomChatBot/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/20CustomChatBot/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/20CustomChatBot/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/20CustomChatBot/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/20CustomChatBot/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/20CustomChatBot/types/services/BotNameService.d.ts b/TypeScript/20CustomChatBot/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/20CustomChatBot/types/services/BotNameService.d.ts +++ b/TypeScript/20CustomChatBot/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/20CustomChatBot/types/services/DatabaseService.d.ts b/TypeScript/20CustomChatBot/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/20CustomChatBot/types/services/DatabaseService.d.ts +++ b/TypeScript/20CustomChatBot/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/20CustomChatBot/types/services/InsuranceService.d.ts b/TypeScript/20CustomChatBot/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/20CustomChatBot/types/services/InsuranceService.d.ts +++ b/TypeScript/20CustomChatBot/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/20CustomChatBot/types/services/PaymentService.d.ts b/TypeScript/20CustomChatBot/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/20CustomChatBot/types/services/PaymentService.d.ts +++ b/TypeScript/20CustomChatBot/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/20CustomChatBot/types/services/PostDbLoadService.d.ts b/TypeScript/20CustomChatBot/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/20CustomChatBot/types/services/PostDbLoadService.d.ts +++ b/TypeScript/20CustomChatBot/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/20CustomChatBot/types/services/ProfileFixerService.d.ts b/TypeScript/20CustomChatBot/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/20CustomChatBot/types/services/ProfileFixerService.d.ts +++ b/TypeScript/20CustomChatBot/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/20CustomChatBot/types/services/SeasonalEventService.d.ts b/TypeScript/20CustomChatBot/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/20CustomChatBot/types/services/SeasonalEventService.d.ts +++ b/TypeScript/20CustomChatBot/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/20CustomChatBot/types/utils/App.d.ts b/TypeScript/20CustomChatBot/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/20CustomChatBot/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/20CustomChatBot/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/21CustomCommandoCommand/types/generators/BotGenerator.d.ts b/TypeScript/21CustomCommandoCommand/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/21CustomCommandoCommand/types/generators/BotGenerator.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/21CustomCommandoCommand/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/21CustomCommandoCommand/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/21CustomCommandoCommand/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/21CustomCommandoCommand/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/21CustomCommandoCommand/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/21CustomCommandoCommand/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/21CustomCommandoCommand/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/21CustomCommandoCommand/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/21CustomCommandoCommand/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/21CustomCommandoCommand/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/21CustomCommandoCommand/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/21CustomCommandoCommand/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/21CustomCommandoCommand/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/21CustomCommandoCommand/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/21CustomCommandoCommand/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/21CustomCommandoCommand/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/21CustomCommandoCommand/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/21CustomCommandoCommand/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/21CustomCommandoCommand/types/services/BotNameService.d.ts b/TypeScript/21CustomCommandoCommand/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/21CustomCommandoCommand/types/services/BotNameService.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/21CustomCommandoCommand/types/services/DatabaseService.d.ts b/TypeScript/21CustomCommandoCommand/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/21CustomCommandoCommand/types/services/DatabaseService.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/21CustomCommandoCommand/types/services/InsuranceService.d.ts b/TypeScript/21CustomCommandoCommand/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/21CustomCommandoCommand/types/services/InsuranceService.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/21CustomCommandoCommand/types/services/PaymentService.d.ts b/TypeScript/21CustomCommandoCommand/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/21CustomCommandoCommand/types/services/PaymentService.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/21CustomCommandoCommand/types/services/PostDbLoadService.d.ts b/TypeScript/21CustomCommandoCommand/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/21CustomCommandoCommand/types/services/PostDbLoadService.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/21CustomCommandoCommand/types/services/ProfileFixerService.d.ts b/TypeScript/21CustomCommandoCommand/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/21CustomCommandoCommand/types/services/ProfileFixerService.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/21CustomCommandoCommand/types/services/SeasonalEventService.d.ts b/TypeScript/21CustomCommandoCommand/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/21CustomCommandoCommand/types/services/SeasonalEventService.d.ts +++ b/TypeScript/21CustomCommandoCommand/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/21CustomCommandoCommand/types/utils/App.d.ts b/TypeScript/21CustomCommandoCommand/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/21CustomCommandoCommand/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/21CustomCommandoCommand/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/22CustomSptCommand/types/generators/BotGenerator.d.ts b/TypeScript/22CustomSptCommand/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/22CustomSptCommand/types/generators/BotGenerator.d.ts +++ b/TypeScript/22CustomSptCommand/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/22CustomSptCommand/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/22CustomSptCommand/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/22CustomSptCommand/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/22CustomSptCommand/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/22CustomSptCommand/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/22CustomSptCommand/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/22CustomSptCommand/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/22CustomSptCommand/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/22CustomSptCommand/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/22CustomSptCommand/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/22CustomSptCommand/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/22CustomSptCommand/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/22CustomSptCommand/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/22CustomSptCommand/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/22CustomSptCommand/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/22CustomSptCommand/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/22CustomSptCommand/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/22CustomSptCommand/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/22CustomSptCommand/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/22CustomSptCommand/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/22CustomSptCommand/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/22CustomSptCommand/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/22CustomSptCommand/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/22CustomSptCommand/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/22CustomSptCommand/types/services/BotNameService.d.ts b/TypeScript/22CustomSptCommand/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/22CustomSptCommand/types/services/BotNameService.d.ts +++ b/TypeScript/22CustomSptCommand/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/22CustomSptCommand/types/services/DatabaseService.d.ts b/TypeScript/22CustomSptCommand/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/22CustomSptCommand/types/services/DatabaseService.d.ts +++ b/TypeScript/22CustomSptCommand/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/22CustomSptCommand/types/services/InsuranceService.d.ts b/TypeScript/22CustomSptCommand/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/22CustomSptCommand/types/services/InsuranceService.d.ts +++ b/TypeScript/22CustomSptCommand/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/22CustomSptCommand/types/services/PaymentService.d.ts b/TypeScript/22CustomSptCommand/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/22CustomSptCommand/types/services/PaymentService.d.ts +++ b/TypeScript/22CustomSptCommand/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/22CustomSptCommand/types/services/PostDbLoadService.d.ts b/TypeScript/22CustomSptCommand/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/22CustomSptCommand/types/services/PostDbLoadService.d.ts +++ b/TypeScript/22CustomSptCommand/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/22CustomSptCommand/types/services/ProfileFixerService.d.ts b/TypeScript/22CustomSptCommand/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/22CustomSptCommand/types/services/ProfileFixerService.d.ts +++ b/TypeScript/22CustomSptCommand/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/22CustomSptCommand/types/services/SeasonalEventService.d.ts b/TypeScript/22CustomSptCommand/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/22CustomSptCommand/types/services/SeasonalEventService.d.ts +++ b/TypeScript/22CustomSptCommand/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/22CustomSptCommand/types/utils/App.d.ts b/TypeScript/22CustomSptCommand/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/22CustomSptCommand/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/22CustomSptCommand/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/23CustomAbstractChatBot/types/generators/BotGenerator.d.ts b/TypeScript/23CustomAbstractChatBot/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/23CustomAbstractChatBot/types/generators/BotGenerator.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/23CustomAbstractChatBot/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/23CustomAbstractChatBot/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/23CustomAbstractChatBot/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/23CustomAbstractChatBot/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/23CustomAbstractChatBot/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/23CustomAbstractChatBot/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/23CustomAbstractChatBot/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/23CustomAbstractChatBot/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/23CustomAbstractChatBot/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/23CustomAbstractChatBot/types/services/BotNameService.d.ts b/TypeScript/23CustomAbstractChatBot/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/23CustomAbstractChatBot/types/services/BotNameService.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/23CustomAbstractChatBot/types/services/DatabaseService.d.ts b/TypeScript/23CustomAbstractChatBot/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/23CustomAbstractChatBot/types/services/DatabaseService.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/23CustomAbstractChatBot/types/services/InsuranceService.d.ts b/TypeScript/23CustomAbstractChatBot/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/23CustomAbstractChatBot/types/services/InsuranceService.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/23CustomAbstractChatBot/types/services/PaymentService.d.ts b/TypeScript/23CustomAbstractChatBot/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/23CustomAbstractChatBot/types/services/PaymentService.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/23CustomAbstractChatBot/types/services/PostDbLoadService.d.ts b/TypeScript/23CustomAbstractChatBot/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/23CustomAbstractChatBot/types/services/PostDbLoadService.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/23CustomAbstractChatBot/types/services/ProfileFixerService.d.ts b/TypeScript/23CustomAbstractChatBot/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/23CustomAbstractChatBot/types/services/ProfileFixerService.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/23CustomAbstractChatBot/types/services/SeasonalEventService.d.ts b/TypeScript/23CustomAbstractChatBot/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/23CustomAbstractChatBot/types/services/SeasonalEventService.d.ts +++ b/TypeScript/23CustomAbstractChatBot/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/23CustomAbstractChatBot/types/utils/App.d.ts b/TypeScript/23CustomAbstractChatBot/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/23CustomAbstractChatBot/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/23CustomAbstractChatBot/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/24WebSocket/types/generators/BotGenerator.d.ts b/TypeScript/24WebSocket/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/24WebSocket/types/generators/BotGenerator.d.ts +++ b/TypeScript/24WebSocket/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/24WebSocket/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/24WebSocket/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/24WebSocket/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/24WebSocket/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/24WebSocket/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/24WebSocket/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/24WebSocket/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/24WebSocket/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/24WebSocket/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/24WebSocket/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/24WebSocket/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/24WebSocket/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/24WebSocket/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/24WebSocket/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/24WebSocket/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/24WebSocket/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/24WebSocket/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/24WebSocket/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/24WebSocket/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/24WebSocket/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/24WebSocket/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/24WebSocket/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/24WebSocket/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/24WebSocket/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/24WebSocket/types/services/BotNameService.d.ts b/TypeScript/24WebSocket/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/24WebSocket/types/services/BotNameService.d.ts +++ b/TypeScript/24WebSocket/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/24WebSocket/types/services/DatabaseService.d.ts b/TypeScript/24WebSocket/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/24WebSocket/types/services/DatabaseService.d.ts +++ b/TypeScript/24WebSocket/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/24WebSocket/types/services/InsuranceService.d.ts b/TypeScript/24WebSocket/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/24WebSocket/types/services/InsuranceService.d.ts +++ b/TypeScript/24WebSocket/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/24WebSocket/types/services/PaymentService.d.ts b/TypeScript/24WebSocket/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/24WebSocket/types/services/PaymentService.d.ts +++ b/TypeScript/24WebSocket/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/24WebSocket/types/services/PostDbLoadService.d.ts b/TypeScript/24WebSocket/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/24WebSocket/types/services/PostDbLoadService.d.ts +++ b/TypeScript/24WebSocket/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/24WebSocket/types/services/ProfileFixerService.d.ts b/TypeScript/24WebSocket/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/24WebSocket/types/services/ProfileFixerService.d.ts +++ b/TypeScript/24WebSocket/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/24WebSocket/types/services/SeasonalEventService.d.ts b/TypeScript/24WebSocket/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/24WebSocket/types/services/SeasonalEventService.d.ts +++ b/TypeScript/24WebSocket/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/24WebSocket/types/utils/App.d.ts b/TypeScript/24WebSocket/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/24WebSocket/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/24WebSocket/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/2EditDatabase/types/generators/BotGenerator.d.ts b/TypeScript/2EditDatabase/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/2EditDatabase/types/generators/BotGenerator.d.ts +++ b/TypeScript/2EditDatabase/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/2EditDatabase/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/2EditDatabase/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/2EditDatabase/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/2EditDatabase/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/2EditDatabase/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/2EditDatabase/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/2EditDatabase/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/2EditDatabase/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/2EditDatabase/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/2EditDatabase/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/2EditDatabase/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/2EditDatabase/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/2EditDatabase/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/2EditDatabase/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/2EditDatabase/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/2EditDatabase/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/2EditDatabase/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/2EditDatabase/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/2EditDatabase/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/2EditDatabase/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/2EditDatabase/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/2EditDatabase/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/2EditDatabase/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/2EditDatabase/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/2EditDatabase/types/services/BotNameService.d.ts b/TypeScript/2EditDatabase/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/2EditDatabase/types/services/BotNameService.d.ts +++ b/TypeScript/2EditDatabase/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/2EditDatabase/types/services/DatabaseService.d.ts b/TypeScript/2EditDatabase/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/2EditDatabase/types/services/DatabaseService.d.ts +++ b/TypeScript/2EditDatabase/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/2EditDatabase/types/services/InsuranceService.d.ts b/TypeScript/2EditDatabase/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/2EditDatabase/types/services/InsuranceService.d.ts +++ b/TypeScript/2EditDatabase/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/2EditDatabase/types/services/PaymentService.d.ts b/TypeScript/2EditDatabase/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/2EditDatabase/types/services/PaymentService.d.ts +++ b/TypeScript/2EditDatabase/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/2EditDatabase/types/services/PostDbLoadService.d.ts b/TypeScript/2EditDatabase/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/2EditDatabase/types/services/PostDbLoadService.d.ts +++ b/TypeScript/2EditDatabase/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/2EditDatabase/types/services/ProfileFixerService.d.ts b/TypeScript/2EditDatabase/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/2EditDatabase/types/services/ProfileFixerService.d.ts +++ b/TypeScript/2EditDatabase/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/2EditDatabase/types/services/SeasonalEventService.d.ts b/TypeScript/2EditDatabase/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/2EditDatabase/types/services/SeasonalEventService.d.ts +++ b/TypeScript/2EditDatabase/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/2EditDatabase/types/utils/App.d.ts b/TypeScript/2EditDatabase/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/2EditDatabase/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/2EditDatabase/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/3GetSptConfigFile/types/generators/BotGenerator.d.ts b/TypeScript/3GetSptConfigFile/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/3GetSptConfigFile/types/generators/BotGenerator.d.ts +++ b/TypeScript/3GetSptConfigFile/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/3GetSptConfigFile/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/3GetSptConfigFile/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/3GetSptConfigFile/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/3GetSptConfigFile/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/3GetSptConfigFile/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/3GetSptConfigFile/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/3GetSptConfigFile/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/3GetSptConfigFile/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/3GetSptConfigFile/types/services/BotNameService.d.ts b/TypeScript/3GetSptConfigFile/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/3GetSptConfigFile/types/services/BotNameService.d.ts +++ b/TypeScript/3GetSptConfigFile/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/3GetSptConfigFile/types/services/DatabaseService.d.ts b/TypeScript/3GetSptConfigFile/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/3GetSptConfigFile/types/services/DatabaseService.d.ts +++ b/TypeScript/3GetSptConfigFile/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/3GetSptConfigFile/types/services/InsuranceService.d.ts b/TypeScript/3GetSptConfigFile/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/3GetSptConfigFile/types/services/InsuranceService.d.ts +++ b/TypeScript/3GetSptConfigFile/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/3GetSptConfigFile/types/services/PaymentService.d.ts b/TypeScript/3GetSptConfigFile/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/3GetSptConfigFile/types/services/PaymentService.d.ts +++ b/TypeScript/3GetSptConfigFile/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/3GetSptConfigFile/types/services/PostDbLoadService.d.ts b/TypeScript/3GetSptConfigFile/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/3GetSptConfigFile/types/services/PostDbLoadService.d.ts +++ b/TypeScript/3GetSptConfigFile/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/3GetSptConfigFile/types/services/ProfileFixerService.d.ts b/TypeScript/3GetSptConfigFile/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/3GetSptConfigFile/types/services/ProfileFixerService.d.ts +++ b/TypeScript/3GetSptConfigFile/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/3GetSptConfigFile/types/services/SeasonalEventService.d.ts b/TypeScript/3GetSptConfigFile/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/3GetSptConfigFile/types/services/SeasonalEventService.d.ts +++ b/TypeScript/3GetSptConfigFile/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/3GetSptConfigFile/types/utils/App.d.ts b/TypeScript/3GetSptConfigFile/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/3GetSptConfigFile/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/3GetSptConfigFile/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/generators/BotGenerator.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/generators/BotGenerator.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/BotNameService.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/BotNameService.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/DatabaseService.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/DatabaseService.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/InsuranceService.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/InsuranceService.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/PaymentService.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/PaymentService.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/PostDbLoadService.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/PostDbLoadService.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/ProfileFixerService.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/ProfileFixerService.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/SeasonalEventService.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/SeasonalEventService.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/App.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/4UseACustomConfigFile/types/generators/BotGenerator.d.ts b/TypeScript/4UseACustomConfigFile/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/4UseACustomConfigFile/types/generators/BotGenerator.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/4UseACustomConfigFile/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/4UseACustomConfigFile/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/4UseACustomConfigFile/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/4UseACustomConfigFile/types/services/BotNameService.d.ts b/TypeScript/4UseACustomConfigFile/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/4UseACustomConfigFile/types/services/BotNameService.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/4UseACustomConfigFile/types/services/DatabaseService.d.ts b/TypeScript/4UseACustomConfigFile/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/4UseACustomConfigFile/types/services/DatabaseService.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/4UseACustomConfigFile/types/services/InsuranceService.d.ts b/TypeScript/4UseACustomConfigFile/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/4UseACustomConfigFile/types/services/InsuranceService.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/4UseACustomConfigFile/types/services/PaymentService.d.ts b/TypeScript/4UseACustomConfigFile/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/4UseACustomConfigFile/types/services/PaymentService.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/4UseACustomConfigFile/types/services/PostDbLoadService.d.ts b/TypeScript/4UseACustomConfigFile/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/4UseACustomConfigFile/types/services/PostDbLoadService.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/4UseACustomConfigFile/types/services/ProfileFixerService.d.ts b/TypeScript/4UseACustomConfigFile/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/4UseACustomConfigFile/types/services/ProfileFixerService.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/4UseACustomConfigFile/types/services/SeasonalEventService.d.ts b/TypeScript/4UseACustomConfigFile/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/4UseACustomConfigFile/types/services/SeasonalEventService.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/4UseACustomConfigFile/types/utils/App.d.ts b/TypeScript/4UseACustomConfigFile/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/4UseACustomConfigFile/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/4UseACustomConfigFile/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/5ReplaceMethod/types/generators/BotGenerator.d.ts b/TypeScript/5ReplaceMethod/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/5ReplaceMethod/types/generators/BotGenerator.d.ts +++ b/TypeScript/5ReplaceMethod/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/5ReplaceMethod/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/5ReplaceMethod/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/5ReplaceMethod/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/5ReplaceMethod/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/5ReplaceMethod/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/5ReplaceMethod/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/5ReplaceMethod/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/5ReplaceMethod/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/5ReplaceMethod/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/5ReplaceMethod/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/5ReplaceMethod/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/5ReplaceMethod/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/5ReplaceMethod/types/services/BotNameService.d.ts b/TypeScript/5ReplaceMethod/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/5ReplaceMethod/types/services/BotNameService.d.ts +++ b/TypeScript/5ReplaceMethod/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/5ReplaceMethod/types/services/DatabaseService.d.ts b/TypeScript/5ReplaceMethod/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/5ReplaceMethod/types/services/DatabaseService.d.ts +++ b/TypeScript/5ReplaceMethod/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/5ReplaceMethod/types/services/InsuranceService.d.ts b/TypeScript/5ReplaceMethod/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/5ReplaceMethod/types/services/InsuranceService.d.ts +++ b/TypeScript/5ReplaceMethod/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/5ReplaceMethod/types/services/PaymentService.d.ts b/TypeScript/5ReplaceMethod/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/5ReplaceMethod/types/services/PaymentService.d.ts +++ b/TypeScript/5ReplaceMethod/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/5ReplaceMethod/types/services/PostDbLoadService.d.ts b/TypeScript/5ReplaceMethod/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/5ReplaceMethod/types/services/PostDbLoadService.d.ts +++ b/TypeScript/5ReplaceMethod/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/5ReplaceMethod/types/services/ProfileFixerService.d.ts b/TypeScript/5ReplaceMethod/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/5ReplaceMethod/types/services/ProfileFixerService.d.ts +++ b/TypeScript/5ReplaceMethod/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/5ReplaceMethod/types/services/SeasonalEventService.d.ts b/TypeScript/5ReplaceMethod/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/5ReplaceMethod/types/services/SeasonalEventService.d.ts +++ b/TypeScript/5ReplaceMethod/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/5ReplaceMethod/types/utils/App.d.ts b/TypeScript/5ReplaceMethod/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/5ReplaceMethod/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/5ReplaceMethod/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/6ReferenceAnotherClass/types/generators/BotGenerator.d.ts b/TypeScript/6ReferenceAnotherClass/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/6ReferenceAnotherClass/types/generators/BotGenerator.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/6ReferenceAnotherClass/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/6ReferenceAnotherClass/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/6ReferenceAnotherClass/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/6ReferenceAnotherClass/types/services/BotNameService.d.ts b/TypeScript/6ReferenceAnotherClass/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/6ReferenceAnotherClass/types/services/BotNameService.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/6ReferenceAnotherClass/types/services/DatabaseService.d.ts b/TypeScript/6ReferenceAnotherClass/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/6ReferenceAnotherClass/types/services/DatabaseService.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/6ReferenceAnotherClass/types/services/InsuranceService.d.ts b/TypeScript/6ReferenceAnotherClass/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/6ReferenceAnotherClass/types/services/InsuranceService.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/6ReferenceAnotherClass/types/services/PaymentService.d.ts b/TypeScript/6ReferenceAnotherClass/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/6ReferenceAnotherClass/types/services/PaymentService.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/6ReferenceAnotherClass/types/services/PostDbLoadService.d.ts b/TypeScript/6ReferenceAnotherClass/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/6ReferenceAnotherClass/types/services/PostDbLoadService.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/6ReferenceAnotherClass/types/services/ProfileFixerService.d.ts b/TypeScript/6ReferenceAnotherClass/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/6ReferenceAnotherClass/types/services/ProfileFixerService.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/6ReferenceAnotherClass/types/services/SeasonalEventService.d.ts b/TypeScript/6ReferenceAnotherClass/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/6ReferenceAnotherClass/types/services/SeasonalEventService.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/6ReferenceAnotherClass/types/utils/App.d.ts b/TypeScript/6ReferenceAnotherClass/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/6ReferenceAnotherClass/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/6ReferenceAnotherClass/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/7OnLoadHook/types/generators/BotGenerator.d.ts b/TypeScript/7OnLoadHook/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/7OnLoadHook/types/generators/BotGenerator.d.ts +++ b/TypeScript/7OnLoadHook/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/7OnLoadHook/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/7OnLoadHook/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/7OnLoadHook/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/7OnLoadHook/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/7OnLoadHook/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/7OnLoadHook/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/7OnLoadHook/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/7OnLoadHook/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/7OnLoadHook/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/7OnLoadHook/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/7OnLoadHook/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/7OnLoadHook/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/7OnLoadHook/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/7OnLoadHook/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/7OnLoadHook/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/7OnLoadHook/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/7OnLoadHook/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/7OnLoadHook/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/7OnLoadHook/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/7OnLoadHook/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/7OnLoadHook/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/7OnLoadHook/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/7OnLoadHook/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/7OnLoadHook/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/7OnLoadHook/types/services/BotNameService.d.ts b/TypeScript/7OnLoadHook/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/7OnLoadHook/types/services/BotNameService.d.ts +++ b/TypeScript/7OnLoadHook/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/7OnLoadHook/types/services/DatabaseService.d.ts b/TypeScript/7OnLoadHook/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/7OnLoadHook/types/services/DatabaseService.d.ts +++ b/TypeScript/7OnLoadHook/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/7OnLoadHook/types/services/InsuranceService.d.ts b/TypeScript/7OnLoadHook/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/7OnLoadHook/types/services/InsuranceService.d.ts +++ b/TypeScript/7OnLoadHook/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/7OnLoadHook/types/services/PaymentService.d.ts b/TypeScript/7OnLoadHook/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/7OnLoadHook/types/services/PaymentService.d.ts +++ b/TypeScript/7OnLoadHook/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/7OnLoadHook/types/services/PostDbLoadService.d.ts b/TypeScript/7OnLoadHook/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/7OnLoadHook/types/services/PostDbLoadService.d.ts +++ b/TypeScript/7OnLoadHook/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/7OnLoadHook/types/services/ProfileFixerService.d.ts b/TypeScript/7OnLoadHook/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/7OnLoadHook/types/services/ProfileFixerService.d.ts +++ b/TypeScript/7OnLoadHook/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/7OnLoadHook/types/services/SeasonalEventService.d.ts b/TypeScript/7OnLoadHook/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/7OnLoadHook/types/services/SeasonalEventService.d.ts +++ b/TypeScript/7OnLoadHook/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/7OnLoadHook/types/utils/App.d.ts b/TypeScript/7OnLoadHook/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/7OnLoadHook/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/7OnLoadHook/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/8OnUpdateHook/types/generators/BotGenerator.d.ts b/TypeScript/8OnUpdateHook/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/8OnUpdateHook/types/generators/BotGenerator.d.ts +++ b/TypeScript/8OnUpdateHook/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/8OnUpdateHook/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/8OnUpdateHook/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/8OnUpdateHook/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/8OnUpdateHook/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/8OnUpdateHook/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/8OnUpdateHook/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/8OnUpdateHook/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/8OnUpdateHook/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/8OnUpdateHook/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/8OnUpdateHook/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/8OnUpdateHook/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/8OnUpdateHook/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/8OnUpdateHook/types/services/BotNameService.d.ts b/TypeScript/8OnUpdateHook/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/8OnUpdateHook/types/services/BotNameService.d.ts +++ b/TypeScript/8OnUpdateHook/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/8OnUpdateHook/types/services/DatabaseService.d.ts b/TypeScript/8OnUpdateHook/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/8OnUpdateHook/types/services/DatabaseService.d.ts +++ b/TypeScript/8OnUpdateHook/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/8OnUpdateHook/types/services/InsuranceService.d.ts b/TypeScript/8OnUpdateHook/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/8OnUpdateHook/types/services/InsuranceService.d.ts +++ b/TypeScript/8OnUpdateHook/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/8OnUpdateHook/types/services/PaymentService.d.ts b/TypeScript/8OnUpdateHook/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/8OnUpdateHook/types/services/PaymentService.d.ts +++ b/TypeScript/8OnUpdateHook/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/8OnUpdateHook/types/services/PostDbLoadService.d.ts b/TypeScript/8OnUpdateHook/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/8OnUpdateHook/types/services/PostDbLoadService.d.ts +++ b/TypeScript/8OnUpdateHook/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/8OnUpdateHook/types/services/ProfileFixerService.d.ts b/TypeScript/8OnUpdateHook/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/8OnUpdateHook/types/services/ProfileFixerService.d.ts +++ b/TypeScript/8OnUpdateHook/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/8OnUpdateHook/types/services/SeasonalEventService.d.ts b/TypeScript/8OnUpdateHook/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/8OnUpdateHook/types/services/SeasonalEventService.d.ts +++ b/TypeScript/8OnUpdateHook/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/8OnUpdateHook/types/utils/App.d.ts b/TypeScript/8OnUpdateHook/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/8OnUpdateHook/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/8OnUpdateHook/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +} diff --git a/TypeScript/9RouterHooks/types/generators/BotGenerator.d.ts b/TypeScript/9RouterHooks/types/generators/BotGenerator.d.ts index 2c7bba6..a2291f4 100644 --- a/TypeScript/9RouterHooks/types/generators/BotGenerator.d.ts +++ b/TypeScript/9RouterHooks/types/generators/BotGenerator.d.ts @@ -5,6 +5,7 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { MinMax } from "@spt/models/common/MinMax"; +import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IBaseJsonSkills, IBaseSkill, IBotBase, IInfo, IHealth as PmcHealth, ISkills as botSkills } from "@spt/models/eft/common/tables/IBotBase"; import { IAppearance, IBodyPart, IBotType, IHealth, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; @@ -47,9 +48,10 @@ export declare class BotGenerator { * @param role e.g. assault / pmcbot * @param difficulty easy/normal/hard/impossible * @param botTemplate base bot template to use (e.g. assault/pmcbot) - * @returns + * profile PMC profile of player generating pscav + * @returns IBotBase */ - generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase; + generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType, profile: IPmcData): IBotBase; /** * Create 1 bot of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id @@ -79,6 +81,12 @@ export declare class BotGenerator { * @returns IBotBase object */ protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails): IBotBase; + /** + * Should this bot have a name like "name (Pmc Name)" and be alterd by client patch to be hostile to player + * @param botRole Role bot has + * @returns True if name should be simulated pscav + */ + protected shouldSimulatePlayerScav(botRole: string): boolean; /** * Get exp for kill by bot difficulty * @param experience Dict of difficulties and experience diff --git a/TypeScript/9RouterHooks/types/helpers/RagfairOfferHelper.d.ts b/TypeScript/9RouterHooks/types/helpers/RagfairOfferHelper.d.ts index 9dd5be3..0ff9c66 100644 --- a/TypeScript/9RouterHooks/types/helpers/RagfairOfferHelper.d.ts +++ b/TypeScript/9RouterHooks/types/helpers/RagfairOfferHelper.d.ts @@ -91,6 +91,12 @@ export declare class RagfairOfferHelper { * @returns IRagfairOffer array */ getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData): IRagfairOffer[]; + /** + * Get offers that have not exceeded buy limits + * @param possibleOffers offers to process + * @returns Offers + */ + protected getOffersInsideBuyRestrictionLimits(possibleOffers: IRagfairOffer[]): IRagfairOffer[]; /** * Check if offer is from trader standing the player does not have * @param offer Offer to check @@ -209,4 +215,10 @@ export declare class RagfairOfferHelper { * @returns True if in range */ protected itemQualityInRange(item: IItem, min: number, max: number): boolean; + /** + * Does this offer come from a trader + * @param offer Offer to check + * @returns True = from trader + */ + offerIsFromTrader(offer: IRagfairOffer): boolean; } diff --git a/TypeScript/9RouterHooks/types/models/eft/common/tables/IBotBase.d.ts b/TypeScript/9RouterHooks/types/models/eft/common/tables/IBotBase.d.ts index d3fd87e..8609573 100644 --- a/TypeScript/9RouterHooks/types/models/eft/common/tables/IBotBase.d.ts +++ b/TypeScript/9RouterHooks/types/models/eft/common/tables/IBotBase.d.ts @@ -60,6 +60,7 @@ export interface IUnlockedInfo { export interface IInfo { EntryPoint: string; Nickname: string; + MainProfileNickname?: string; LowerNickname: string; Side: string; SquadInviteRestriction: boolean; diff --git a/TypeScript/9RouterHooks/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/9RouterHooks/types/models/spt/config/IInventoryConfig.d.ts index af0ec79..00ba5b1 100644 --- a/TypeScript/9RouterHooks/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/9RouterHooks/types/models/spt/config/IInventoryConfig.d.ts @@ -10,6 +10,8 @@ export interface IInventoryConfig extends IBaseConfig { customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ skillGainMultiplers: Record; + /** Container Tpls that shoud be deprioritised when choosing where to take money from for payments */ + deprioritisedMoneyContainers: string[]; } export interface IRewardDetails { rewardCount: number; diff --git a/TypeScript/9RouterHooks/types/models/spt/config/IPmcConfig.d.ts b/TypeScript/9RouterHooks/types/models/spt/config/IPmcConfig.d.ts index 2e68219..02c9c5b 100644 --- a/TypeScript/9RouterHooks/types/models/spt/config/IPmcConfig.d.ts +++ b/TypeScript/9RouterHooks/types/models/spt/config/IPmcConfig.d.ts @@ -66,7 +66,9 @@ export interface IPmcTypes { bear: string; } export interface ISlotLootSettings { + /** Item Type whitelist */ whitelist: string[]; + /** item tpl blacklist */ blacklist: string[]; } export interface IMinMaxLootValue extends MinMax { diff --git a/TypeScript/9RouterHooks/types/models/spt/config/IRagfairConfig.d.ts b/TypeScript/9RouterHooks/types/models/spt/config/IRagfairConfig.d.ts index 36122c5..805a6b2 100644 --- a/TypeScript/9RouterHooks/types/models/spt/config/IRagfairConfig.d.ts +++ b/TypeScript/9RouterHooks/types/models/spt/config/IRagfairConfig.d.ts @@ -75,6 +75,8 @@ export interface IDynamic { blacklist: IRagfairBlacklist; /** Dict of price limits keyed by item type */ unreasonableModPrices: Record; + /** Custom rouble prices for items to override values from prices.json */ + itemPriceOverrideRouble: Record; } export interface IPriceRanges { default: MinMax; diff --git a/TypeScript/9RouterHooks/types/models/spt/config/ISeasonalEventConfig.d.ts b/TypeScript/9RouterHooks/types/models/spt/config/ISeasonalEventConfig.d.ts index 5e119fa..bf93685 100644 --- a/TypeScript/9RouterHooks/types/models/spt/config/ISeasonalEventConfig.d.ts +++ b/TypeScript/9RouterHooks/types/models/spt/config/ISeasonalEventConfig.d.ts @@ -6,6 +6,8 @@ export interface ISeasonalEventConfig extends IBaseConfig { enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ eventGear: Record>>>; + /** event / bot type / equipSlot / itemid */ + eventLoot: Record>>>; events: ISeasonalEvent[]; eventBotMapping: Record; eventBossSpawns: Record>; diff --git a/TypeScript/9RouterHooks/types/services/BotNameService.d.ts b/TypeScript/9RouterHooks/types/services/BotNameService.d.ts index 056bd0f..349964d 100644 --- a/TypeScript/9RouterHooks/types/services/BotNameService.d.ts +++ b/TypeScript/9RouterHooks/types/services/BotNameService.d.ts @@ -1,5 +1,6 @@ import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; @@ -38,10 +39,13 @@ export declare class BotNameService { */ generateUniqueBotNickname(botJsonTemplate: IBotType, botGenerationDetails: IBotGenerationDetails, botRole: string, uniqueRoles?: string[]): string; /** - * Should this bot have a name like "name (Pmc Name)" - * @param botRole Role bot has - * @returns True if name should be simulated pscav + * Add random PMC name to bots MainProfileNickname property + * @param bot Bot to update */ - protected shouldSimulatePlayerScavName(botRole: string): boolean; - protected addPlayerScavNameSimulationSuffix(nickname: string): string; + addRandomPmcNameToBotMainProfileNicknameProperty(bot: IBotBase): void; + /** + * Choose a random PMC name from bear or usec bot jsons + * @returns PMC name as string + */ + protected getRandomPMCName(): string; } diff --git a/TypeScript/9RouterHooks/types/services/DatabaseService.d.ts b/TypeScript/9RouterHooks/types/services/DatabaseService.d.ts index 934617a..73575b1 100644 --- a/TypeScript/9RouterHooks/types/services/DatabaseService.d.ts +++ b/TypeScript/9RouterHooks/types/services/DatabaseService.d.ts @@ -85,7 +85,7 @@ export declare class DatabaseService { */ getCustomization(): Record; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/handbook.json */ getHandbook(): IHandbookBase; /** @@ -101,7 +101,7 @@ export declare class DatabaseService { */ getProfiles(): IProfileTemplates; /** - * @returns assets/database/templates/items.json + * @returns assets/database/templates/quests.json */ getQuests(): Record; /** diff --git a/TypeScript/9RouterHooks/types/services/InsuranceService.d.ts b/TypeScript/9RouterHooks/types/services/InsuranceService.d.ts index ac9cff5..e52fa59 100644 --- a/TypeScript/9RouterHooks/types/services/InsuranceService.d.ts +++ b/TypeScript/9RouterHooks/types/services/InsuranceService.d.ts @@ -62,14 +62,6 @@ export declare class InsuranceService { * @returns Timestamp to return items to player in seconds */ protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number; - /** - * Take the insurance item packages within a profile session and ensure that each of the items in that package are - * not orphaned from their parent ID. - * - * @param sessionID The session ID to update insurance equipment packages in. - * @returns void - */ - protected adoptOrphanedInsEquipment(sessionID: string): void; protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number; /** * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it @@ -127,10 +119,4 @@ export declare class InsuranceService { * @returns price in roubles */ getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: IItem, traderId: string): number; - /** - * Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance. - * @param sessionID Players id - * @returns The root item Id. - */ - getRootItemParentID(sessionID: string): string; } diff --git a/TypeScript/9RouterHooks/types/services/PaymentService.d.ts b/TypeScript/9RouterHooks/types/services/PaymentService.d.ts index f6ec79d..78fdfb6 100644 --- a/TypeScript/9RouterHooks/types/services/PaymentService.d.ts +++ b/TypeScript/9RouterHooks/types/services/PaymentService.d.ts @@ -8,7 +8,9 @@ import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; +import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; @@ -24,7 +26,9 @@ export declare class PaymentService { protected inventoryHelper: InventoryHelper; protected localisationService: LocalisationService; protected paymentHelper: PaymentHelper; - constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper); + protected configServer: ConfigServer; + protected inventoryConfig: IInventoryConfig; + constructor(logger: ILogger, hashUtil: HashUtil, httpResponse: HttpResponseUtil, databaseService: DatabaseService, handbookHelper: HandbookHelper, traderHelper: TraderHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, localisationService: LocalisationService, paymentHelper: PaymentHelper, configServer: ConfigServer); /** * Take money and insert items into return to server request * @param pmcData Pmc profile diff --git a/TypeScript/9RouterHooks/types/services/PostDbLoadService.d.ts b/TypeScript/9RouterHooks/types/services/PostDbLoadService.d.ts index c9e4bbe..cc51311 100644 --- a/TypeScript/9RouterHooks/types/services/PostDbLoadService.d.ts +++ b/TypeScript/9RouterHooks/types/services/PostDbLoadService.d.ts @@ -74,4 +74,6 @@ export declare class PostDbLoadService { */ protected validateQuestAssortUnlocksExist(): void; protected setAllDbItemsAsSellableOnFlea(): void; + protected addMissingTraderBuyRestrictionMaxValue(): void; + protected applyFleaPriceOverrides(): void; } diff --git a/TypeScript/9RouterHooks/types/services/ProfileFixerService.d.ts b/TypeScript/9RouterHooks/types/services/ProfileFixerService.d.ts index 4a3a5ff..cbbe1d0 100644 --- a/TypeScript/9RouterHooks/types/services/ProfileFixerService.d.ts +++ b/TypeScript/9RouterHooks/types/services/ProfileFixerService.d.ts @@ -47,6 +47,12 @@ export declare class ProfileFixerService { * @param pmcProfile profile to check and fix */ checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void; + /** + * Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + * the stash root object ID + * @param fullProfile + */ + checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void; /** * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix diff --git a/TypeScript/9RouterHooks/types/services/SeasonalEventService.d.ts b/TypeScript/9RouterHooks/types/services/SeasonalEventService.d.ts index 446cccc..26b74ef 100644 --- a/TypeScript/9RouterHooks/types/services/SeasonalEventService.d.ts +++ b/TypeScript/9RouterHooks/types/services/SeasonalEventService.d.ts @@ -88,6 +88,12 @@ export declare class SeasonalEventService { * @returns bots with equipment changes */ protected getEventBotGear(eventType: SeasonalEventType): Record>>; + /** + * Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + * @param eventName Name of event to get gear changes for + * @returns bots with loot changes + */ + protected getEventBotLoot(eventType: SeasonalEventType): Record>>; /** * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date @@ -108,7 +114,7 @@ export declare class SeasonalEventService { /** * Store active events inside class array property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive */ - protected cacheActiveEvents(): void; + cacheActiveEvents(): void; /** * Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER * @returns Season enum value @@ -171,6 +177,11 @@ export declare class SeasonalEventService { * @param eventName Name of the event to read equipment in from config */ protected addEventGearToBots(eventType: SeasonalEventType): void; + /** + * Read in data from seasonalEvents.json and add found loot items to bots + * @param eventName Name of the event to read loot in from config + */ + protected addEventLootToBots(eventType: SeasonalEventType): void; /** * Add pumpkin loot boxes to scavs */ diff --git a/TypeScript/9RouterHooks/types/utils/App.d.ts b/TypeScript/9RouterHooks/types/utils/App.d.ts index db46d2c..0e4850e 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/ProgressWriter.d.ts b/TypeScript/9RouterHooks/types/utils/ProgressWriter.d.ts new file mode 100644 index 0000000..2641d3a --- /dev/null +++ b/TypeScript/9RouterHooks/types/utils/ProgressWriter.d.ts @@ -0,0 +1,13 @@ +export declare class ProgressWriter { + private count; + private total?; + private done; + private barFillChar; + private barEmptyChar; + private maxBarLength; + constructor(total: number, maxBarLength?: number, barFillChar?: string, barEmptyChar?: string); + /** + * Increment the progress counter and update the progress bar display. + */ + increment(): void; +}