diff --git a/Core/Models/Enums/GiftSentResult.cs b/Core/Models/Enums/GiftSentResult.cs new file mode 100644 index 00000000..4c953436 --- /dev/null +++ b/Core/Models/Enums/GiftSentResult.cs @@ -0,0 +1,9 @@ +namespace Core.Models.Enums; + +public enum GiftSentResult +{ + FAILED_UNKNOWN = 1, + FAILED_GIFT_ALREADY_RECEIVED = 2, + FAILED_GIFT_DOESNT_EXIST = 3, + SUCCESS = 4, +} diff --git a/Core/Models/Spt/Config/HideoutConfig.cs b/Core/Models/Spt/Config/HideoutConfig.cs index 74e3060b..57b66589 100644 --- a/Core/Models/Spt/Config/HideoutConfig.cs +++ b/Core/Models/Spt/Config/HideoutConfig.cs @@ -81,7 +81,7 @@ public class CultistCircleSettings public int HideoutCraftSacrificeThresholdRub { get; set; } [JsonPropertyName("craftTimeThreshholds")] - public List CraftTimeThreshholds { get; set; } + public List CraftTimeThreshholds { get; set; } /// /// -1 means no override, value in seconds @@ -117,7 +117,7 @@ public class CultistCircleSettings public Dictionary CurrencyRewards { get; set; } } -public class CraftTimeThreshhold : MinMax +public class CraftTimeThreshold : MinMax { [JsonPropertyName("craftTimeSeconds")] public int CraftTimeSeconds { get; set; } diff --git a/Core/Models/Spt/Hideout/CircleCraftDetails.cs b/Core/Models/Spt/Hideout/CircleCraftDetails.cs index 6a33e68e..30434621 100644 --- a/Core/Models/Spt/Hideout/CircleCraftDetails.cs +++ b/Core/Models/Spt/Hideout/CircleCraftDetails.cs @@ -16,5 +16,5 @@ public class CircleCraftDetails public int? RewardAmountRoubles { get; set; } [JsonPropertyName("rewardDetails")] - public CraftTimeThreshhold? RewardDetails { get; set; } + public CraftTimeThreshold? RewardDetails { get; set; } } \ No newline at end of file diff --git a/Core/Services/AirdropService.cs b/Core/Services/AirdropService.cs new file mode 100644 index 00000000..44ac1a2e --- /dev/null +++ b/Core/Services/AirdropService.cs @@ -0,0 +1,55 @@ +using Core.Models.Eft.Common.Tables; +using Core.Models.Eft.Location; +using Core.Models.Enums; +using Core.Models.Spt.Services; + +namespace Core.Services; + +public class AirdropService +{ + public GetAirdropLootResponse GenerateCustomAirdropLoot(GetAirdropLootRequest request) + { + throw new NotImplementedException(); + } + + /// + /// Handle client/location/getAirdropLoot + /// Get loot for an airdrop container + /// Generates it randomly based on config/airdrop.json values + /// + /// OPTIONAL - Desired airdrop type, randomised when not provided + /// List of LootItem objects + public GetAirdropLootResponse GenerateAirdropLoot(string forcedAirdropType = null) + { + throw new NotImplementedException(); + } + + /// + /// Create a container create item based on passed in airdrop type + /// + /// What type of container: weapon/common etc + /// Item + protected Item GetAirdropCrateItem(SptAirdropTypeEnum airdropType) + { + throw new NotImplementedException(); + } + + /// + /// Randomly pick a type of airdrop loot using weighted values from config + /// + /// airdrop type value + protected SptAirdropTypeEnum ChooseAirdropType() + { + throw new NotImplementedException(); + } + + /// + /// Get the configuration for a specific type of airdrop + /// + /// Type of airdrop to get settings for + /// LootRequest + protected LootRequest GetAirdropLootConfigByType(AirdropTypeEnum airdropType) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/BackupService.cs b/Core/Services/BackupService.cs new file mode 100644 index 00000000..f06ed2fc --- /dev/null +++ b/Core/Services/BackupService.cs @@ -0,0 +1,137 @@ +namespace Core.Services; + +public class BackupService +{ + /** + * 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. + */ + public async Task InitAsync() + { + throw new NotImplementedException(); + } + + /** + * 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 a List of JSON file names. + */ + protected async Task> FetchProfileFilesAsync() + { + throw new NotImplementedException(); + } + + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected bool IsEnabled() + { + throw new NotImplementedException(); + } + + /** + * 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 string GenerateBackupTargetDir() + { + throw new NotImplementedException(); + } + + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected string GenerateBackupDate() + { + throw new NotImplementedException(); + } + + /** + * 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 async Task CleanBackupsAsync() + { + throw new NotImplementedException(); + } + + /** + * 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 a List of sorted backup file paths. + */ + private async Task> GetBackupPathsAsync(string dir) + { + throw new NotImplementedException(); + } + + /** + * 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 long? CompareBackupDates(string a, string b) + { + throw new NotImplementedException(); + } + + /** + * 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 DateTime object if the folder name is in the correct format, otherwise null. + */ + private DateTime? ExtractDateFromFolderName(string folderName) + { + throw new NotImplementedException(); + } + + /** + * Removes excess backups from the backup directory. + * + * @param backups - A List of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private async Task RemoveExcessBackupsAsync(List backups) + { + throw new NotImplementedException(); + } + + /** + * Start the backup interval if enabled in the configuration. + */ + protected void StartBackupInterval() + { + throw new NotImplementedException(); + } + + /** + * Get a List of active server mod details. + * + * @returns A List of mod names. + */ + protected List GetActiveServerMods() + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/BotEquipmentFilterService.cs b/Core/Services/BotEquipmentFilterService.cs new file mode 100644 index 00000000..ad9f407e --- /dev/null +++ b/Core/Services/BotEquipmentFilterService.cs @@ -0,0 +1,156 @@ +using Core.Models.Eft.Common.Tables; +using Core.Models.Spt.Bots; +using Core.Models.Spt.Config; + +namespace Core.Services; + +public class BotEquipmentFilterService +{ + /// + /// Filter a bots data to exclude equipment and cartridges defines in the botConfig + /// + /// Players id + /// bots json data to filter + /// Level of the bot + /// details on how to generate a bot + public void FilterBotEquipment( + string sessionId, + BotType baseBotNode, + int botLevel, + BotGenerationDetails botGenerationDetails) + { + throw new NotImplementedException(); + } + + /// + /// Iterate over the changes passed in and apply them to baseValues parameter + /// + /// Changes to apply + /// data to update + protected void AdjustChances( + Dictionary equipmentChanges, + EquipmentChances baseValues) + { + throw new NotImplementedException(); + } + + /// + /// Iterate over the Generation changes and alter data in baseValues.Generation + /// + /// Changes to apply + /// dictionary to update + protected void AdjustGenerationChances( + Dictionary generationChanges, + Generation baseBotGeneration) + { + throw new NotImplementedException(); + } + + /// + /// Get equipment settings for bot + /// + /// equipment role to return + /// EquipmentFilters object + public EquipmentFilters GetBotEquipmentSettings(string botEquipmentRole) + { + throw new NotImplementedException(); + } + + /// + /// Get weapon sight whitelist for a specific bot type + /// + /// equipment role of bot to look up + /// Dictionary of weapon type and their whitelisted scope types + public Dictionary> GetBotWeaponSightWhitelist(string botEquipmentRole) + { + throw new NotImplementedException(); + } + + /// + /// Get an object that contains equipment and cartridge blacklists for a specified bot type + /// + /// Role of the bot we want the blacklist for + /// Level of the player + /// EquipmentBlacklistDetails object + public EquipmentFilterDetails GetBotEquipmentBlacklist(string botRole, int playerLevel) + { + throw new NotImplementedException(); + } + + /// + /// Get the whitelist for a specific bot type that's within the players level + /// + /// Bot type + /// Players level + /// EquipmentFilterDetails object + protected EquipmentFilterDetails GetBotEquipmentWhitelist(string botRole, int playerLevel) + { + throw new NotImplementedException(); + } + + /// + /// Retrieve item weighting adjustments from bot.json config based on bot level + /// + /// Bot type to get adjustments for + /// Level of bot + /// Weighting adjustments for bot items + protected WeightingAdjustmentDetails GetBotWeightingAdjustments(string botRole, int botLevel) + { + throw new NotImplementedException(); + } + + /// + /// Retrieve item weighting adjustments from bot.json config based on player level + /// + /// Bot type to get adjustments for + /// Level of bot + /// Weighting adjustments for bot items + protected WeightingAdjustmentDetails GetBotWeightingAdjustmentsByPlayerLevel(string botRole, int playerlevel) + { + throw new NotImplementedException(); + } + + /// + /// Filter bot equipment based on blacklist and whitelist from config/bot.json + /// Prioritizes whitelist first, if one is found blacklist is ignored + /// + /// bot .json file to update + /// equipment blacklist + /// Filtered bot file + protected void FilterEquipment( + BotType baseBotNode, + EquipmentFilterDetails blacklist, + EquipmentFilterDetails whitelist) + { + throw new NotImplementedException(); + } + + /// + /// Filter bot cartridges based on blacklist and whitelist from config/bot.json + /// Prioritizes whitelist first, if one is found blacklist is ignored + /// + /// bot .json file to update + /// equipment on this list should be excluded from the bot + /// equipment on this list should be used exclusively + /// Filtered bot file + protected void FilterCartridges( + BotType baseBotNode, + EquipmentFilterDetails blacklist, + EquipmentFilterDetails whitelist) + { + throw new NotImplementedException(); + } + + /// + /// Add/Edit weighting changes to bot items using values from config/bot.json/equipment + /// + /// Weighting change to apply to bot + /// Bot item dictionary to adjust + protected void AdjustWeighting( + AdjustmentDetails weightingAdjustments, + Dictionary botItemPool, + bool showEditWarnings = true) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/BotEquipmentModPoolService.cs b/Core/Services/BotEquipmentModPoolService.cs new file mode 100644 index 00000000..799bc57d --- /dev/null +++ b/Core/Services/BotEquipmentModPoolService.cs @@ -0,0 +1,81 @@ +using Core.Models.Eft.Common.Tables; + +namespace Core.Services; + +public class BotEquipmentModPoolService +{ + /** + * Store dictionary of mods for each item passed in + * @param items items to find related mods and store in modPool + */ + protected void GeneratePool(List items, string poolType) + { + throw new NotImplementedException(); + } + + /** + * Empty the mod pool + */ + public void ResetPool() + { + throw new NotImplementedException(); + } + + /** + * Get array of compatible mods for an items mod slot (generate pool if it doesnt exist already) + * @param itemTpl item to look up + * @param slotName slot to get compatible mods for + * @returns tpls that fit the slot + */ + public List GetCompatibleModsForWeaponSlot(string itemTpl, string slotName) + { + throw new NotImplementedException(); + } + + /** + * Get array of compatible mods for an items mod slot (generate pool if it doesnt exist already) + * @param itemTpl item to look up + * @param slotName slot to get compatible mods for + * @returns tpls that fit the slot + */ + public List GetCompatibleModsForGearSlot(string itemTpl, string slotName) + { + throw new NotImplementedException(); + } + + /** + * Get mods for a piece of gear by its tpl + * @param itemTpl items tpl to look up mods for + * @returns Dictionary of mods (keys are mod slot names) with array of compatible mod tpls as value + */ + public Dictionary> GetModsForGearSlot(string itemTpl) + { + throw new NotImplementedException(); + } + + /** + * Get mods for a weapon by its tpl + * @param itemTpl Weapons tpl to look up mods for + * @returns Dictionary of mods (keys are mod slot names) with array of compatible mod tpls as value + */ + public Dictionary> GetModsForWeaponSlot(string itemTpl) + { + throw new NotImplementedException(); + } + + /** + * Create weapon mod pool and set generated flag to true + */ + protected void GenerateWeaponPool() + { + throw new NotImplementedException(); + } + + /** + * Create gear mod pool and set generated flag to true + */ + protected void GenerateGearPool() + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/BotGenerationCacheService.cs b/Core/Services/BotGenerationCacheService.cs new file mode 100644 index 00000000..a0ce0645 --- /dev/null +++ b/Core/Services/BotGenerationCacheService.cs @@ -0,0 +1,73 @@ +using Core.Models.Eft.Common.Tables; + +namespace Core.Services; + +public class BotGenerationCacheService +{ + /** + * Store list of bots in cache, shuffle results before storage + * @param botsToStore Bots we want to store in the cache + */ + public void StoreBots(string key, List botsToStore) + { + throw new NotImplementedException(); + } + + /** + * Find and return a bot based on its role + * Remove bot from internal list so it can't be retrieved again + * @param key role to retrieve (assault/bossTagilla etc) + * @returns BotBase object + */ + public BotBase GetBot(string key) + { + throw new NotImplementedException(); + } + + /** + * Cache a bot that has been sent to the client in memory for later use post-raid to determine if player killed a traitor scav + * @param botToStore Bot object to store + */ + public void StoreUsedBot(BotBase botToStore) + { + throw new NotImplementedException(); + } + + /** + * Get a bot by its profileId that has been generated and sent to client for current raid + * Cache is wiped post-raid in client/match/offline/end endOfflineRaid() + * @param profileId Id of bot to get + * @returns BotBase + */ + public BotBase GetUsedBot(string profileId) + { + throw new NotImplementedException(); + } + + /** + * Remove all cached bot profiles from memory + */ + public void ClearStoredBots() + { + throw new NotImplementedException(); + } + + /** + * Does cache have a bot with requested key + * @returns false if empty + */ + public bool CacheHasBotWithKey(string key, int size = 0) + { + throw new NotImplementedException(); + } + + public int GetCachedBotCount(string key) + { + throw new NotImplementedException(); + } + + public string CreateCacheKey(string role, string difficulty) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/BotLootCacheService.cs b/Core/Services/BotLootCacheService.cs new file mode 100644 index 00000000..b07ba153 --- /dev/null +++ b/Core/Services/BotLootCacheService.cs @@ -0,0 +1,144 @@ +using Core.Models.Eft.Common.Tables; +using Core.Models.Spt.Bots; +using Props = Core.Models.Eft.Common.Props; + +namespace Core.Services; + +public class BotLootCacheService +{ + /// + /// Remove cached bot loot data + /// + public void ClearCache() + { + throw new NotImplementedException(); + } + + /// + /// Get the fully created loot array, ordered by price low to high + /// + /// bot to get loot for + /// is the bot a pmc + /// what type of loot is needed (backpack/pocket/stim/vest etc) + /// Base json db file for the bot having its loot generated + /// Dictionary + public Dictionary GetLootFromCache( + string botRole, + bool isPmc, + string lootType, + BotType botJsonTemplate) + { + throw new NotImplementedException(); + } + + /// + /// Generate loot for a bot and store inside a private class property + /// + /// bots role (assault / pmcBot etc) + /// Is the bot a PMC (alteres what loot is cached) + /// db template for bot having its loot generated + protected void AddLootToCache(string botRole, bool isPmc, BotType botJsonTemplate) + { + throw new NotImplementedException(); + } + + /// + /// Add unique items into combined pool + /// + /// Pool of items to add to + /// items to add to combined pool if unique + protected void AddUniqueItemsToPool(List poolToAddTo, List itemsToAdd) + { + throw new NotImplementedException(); + } + + protected void AddItemsToPool(Dictionary poolToAddTo, Dictionary poolOfItemsToAdd) + { + throw new NotImplementedException(); + } + + /// + /// Ammo/grenades have this property + /// + /// + /// + protected bool IsBulletOrGrenade(Props props) + { + throw new NotImplementedException(); + } + + /// + /// Internal and external magazine have this property + /// + /// + /// + protected bool IsMagazine(Props props) + { + throw new NotImplementedException(); + } + + /// + /// Medical use items (e.g. morphine/lip balm/grizzly) + /// + /// + /// + protected bool IsMedicalItem(Props props) + { + throw new NotImplementedException(); + } + + /// + /// Grenades have this property (e.g. smoke/frag/flash grenades) + /// + /// + /// + protected bool IsGrenade(Props props) + { + throw new NotImplementedException(); + } + + protected bool IsFood(string tpl) + { + throw new NotImplementedException(); + } + + protected bool IsDrink(string tpl) + { + throw new NotImplementedException(); + } + + protected bool IsCurrency(string tpl) + { + throw new NotImplementedException(); + } + + /// + /// Check if a bot type exists inside the loot cache + /// + /// role to check for + /// true if they exist + protected bool BotRoleExistsInCache(string botRole) + { + throw new NotImplementedException(); + } + + /// + /// If lootcache is undefined, init with empty property arrays + /// + /// Bot role to hydrate + protected void InitCacheForBotRole(string botRole) + { + throw new NotImplementedException(); + } + + /// + /// Compares two item prices by their flea (or handbook if that doesnt exist) price + /// + /// + /// + /// + protected int CompareByValue(int itemAPrice, int itemBPrice) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/BotNameService.cs b/Core/Services/BotNameService.cs new file mode 100644 index 00000000..b6d87f9d --- /dev/null +++ b/Core/Services/BotNameService.cs @@ -0,0 +1,51 @@ +using Core.Models.Eft.Common.Tables; +using Core.Models.Spt.Bots; + +namespace Core.Services; + +public class BotNameService +{ + /// + /// Clear out any entries in Name Set + /// + public void ClearNameCache() + { + throw new NotImplementedException(); + } + + /// + /// Create a unique bot nickname + /// + /// bot JSON data from db + /// + /// role of bot e.g. assault + /// Lowercase roles to always make unique + /// OPTIONAL: profile session id + /// Nickname for bot + public string GenerateUniqueBotNickname( + BotType botJsonTemplate, + BotGenerationDetails botGenerationDetails, + string botRole, + List uniqueRoles = null) + { + throw new NotImplementedException(); + } + + /// + /// Add random PMC name to bots MainProfileNickname property + /// + /// Bot to update + public void AddRandomPmcNameToBotMainProfileNicknameProperty(BotBase bot) + { + throw new NotImplementedException(); + } + + /// + /// Choose a random PMC name from bear or usec bot jsons + /// + /// PMC name as string + protected string GetRandomPMCName() + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/BotWeaponModLimitService.cs b/Core/Services/BotWeaponModLimitService.cs new file mode 100644 index 00000000..976e3d8b --- /dev/null +++ b/Core/Services/BotWeaponModLimitService.cs @@ -0,0 +1,57 @@ +using Core.Models.Eft.Common.Tables; +using Core.Models.Spt.Bots; + +namespace Core.Services; + +public class BotWeaponModLimitService +{ + /// + /// Initalise mod limits to be used when generating a weapon + /// + /// "assault", "bossTagilla" or "pmc" + /// BotModLimits object + public BotModLimits GetWeaponModLimits(string botRole) + { + throw new NotImplementedException(); + } + + /// + /// Check if weapon mod item is on limited list + has surpassed the limit set for it + /// Exception: Always allow ncstar backup mount + /// Exception: Always allow scopes with a scope for a parent + /// Exception: Always disallow mounts that hold only scopes once scope limit reached + /// Exception: Always disallow mounts that hold only flashlights once flashlight limit reached + /// + /// role the bot has e.g. assault + /// mods template data + /// limits set for weapon being generated for this bot + /// The parent of the mod to be checked + /// Array of IItem + /// true if over item limit + public bool WeaponModHasReachedLimit( + string botRole, + TemplateItem modTemplate, + BotModLimits modLimits, + TemplateItem modsParent, + List weapon) + { + throw new NotImplementedException(); + } + + /// + /// Check if the specific item type on the weapon has reached the set limit + /// + /// log mod tpl if over type limit + /// current number of this item on gun + /// mod limit allowed + /// role of bot we're checking weapon of + /// true if limit reached + protected bool WeaponModLimitReached( + string modTpl, + object currentCount, + int maxLimit, + string botRole) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/Cache/BundleHashCacheService.cs b/Core/Services/Cache/BundleHashCacheService.cs new file mode 100644 index 00000000..cac505af --- /dev/null +++ b/Core/Services/Cache/BundleHashCacheService.cs @@ -0,0 +1,29 @@ +namespace Core.Services.Cache; + +public class BundleHashCacheService +{ + public int GetStoredValue(string key) + { + throw new NotImplementedException(); + } + + public void StoreValue(string key, int value) + { + throw new NotImplementedException(); + } + + public bool MatchWithStoredHash(string bundlePath, int hash) + { + throw new NotImplementedException(); + } + + public bool CalculateAndMatchHash(string bundlePath) + { + throw new NotImplementedException(); + } + + public void CalculateAndStoreHash(string bundlePath) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/Cache/ModHashCacheService.cs b/Core/Services/Cache/ModHashCacheService.cs new file mode 100644 index 00000000..1c18158d --- /dev/null +++ b/Core/Services/Cache/ModHashCacheService.cs @@ -0,0 +1,29 @@ +namespace Core.Services.Cache; + +public class ModHashCacheService +{ + public string GetStoredValue(string key) + { + throw new NotImplementedException(); + } + + public void StoreValue(string key, string value) + { + throw new NotImplementedException(); + } + + public bool MatchWithStoredHash(string modName, string hash) + { + throw new NotImplementedException(); + } + + public bool CalculateAndCompareHash(string modName, string modContent) + { + throw new NotImplementedException(); + } + + public void CalculateAndStoreHash(string modName, string modContent) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/CircleOfCultistService.cs b/Core/Services/CircleOfCultistService.cs new file mode 100644 index 00000000..df49080b --- /dev/null +++ b/Core/Services/CircleOfCultistService.cs @@ -0,0 +1,298 @@ +using Core.Models.Eft.Common; +using Core.Models.Eft.Common.Tables; +using Core.Models.Eft.Hideout; +using Core.Models.Eft.ItemEvent; +using Core.Models.Spt.Config; +using Core.Models.Spt.Hideout; +using Hideout = Core.Models.Eft.Common.Tables.Hideout; + +namespace Core.Services; + +public class CircleOfCultistService +{ + /// + /// Start a sacrifice event + /// Generate rewards + /// Delete sacrificed items + /// + /// Session id + /// Player profile doing sacrifice + /// Client request + /// ItemEventRouterResponse + public ItemEventRouterResponse StartSacrifice( + string sessionId, + PmcData pmcData, + HideoutCircleOfCultistProductionStartRequestData request + ) + { + throw new NotImplementedException(); + } + + /// + /// Attempt to add all rewards to cultist circle, if they don't fit remove one and try again until they fit + /// + /// Session id + /// Player profile + /// Rewards to send to player + /// Cultist grid to add rewards to + /// Stash id + /// Client output + protected void AddRewardsToCircleContainer( + string sessionId, + PmcData pmcData, + List> rewards, + List> containerGrid, + string cultistCircleStashId, + ItemEventRouterResponse output + ) + { + throw new NotImplementedException(); + } + + /// + /// Create a map of the possible direct rewards, keyed by the items needed to be sacrificed + /// + /// Direct rewards array from hideout config + /// Dictionary + protected Dictionary GenerateSacrificedItemsCache(List directRewards) + { + throw new NotImplementedException(); + } + + /// + /// Get the reward amount multiple value based on players hideout management skill + configs rewardPriceMultiplerMinMax values + /// + /// Player profile + /// Circle config settings + /// Reward Amount Multiplier + protected double GetRewardAmountMultiplier(PmcData pmcData, CultistCircleSettings cultistCircleSettings) + { + throw new NotImplementedException(); + } + + /// + /// Register production inside player profile + /// + /// Session id + /// Player profile + /// Recipe id + /// Items player sacrificed + /// How long the ritual should take + protected void RegisterCircleOfCultistProduction( + string sessionId, + PmcData pmcData, + string recipeId, + List sacrificedItems, + double craftingTime + ) + { + throw new NotImplementedException(); + } + + /// + /// Get the circle craft time as seconds, value is based on reward item value + /// And get the bonus status to determine what tier of reward is given + /// + /// Value of rewards in roubles + /// Circle config values + /// OPTIONAL - Values related to direct reward being given + /// craft time + type of reward + reward details + protected CircleCraftDetails GetCircleCraftingInfo( + double rewardAmountRoubles, + CultistCircleSettings circleConfig, + DirectRewardSettings directRewardSettings = null + ) + { + throw new NotImplementedException(); + } + + protected CraftTimeThreshold GetMatchingThreshold( + List thresholds, + double rewardAmountRoubles + ) + { + throw new NotImplementedException(); + } + + /// + /// Get the items player sacrificed in circle + /// + /// Player profile + /// Array of items from player inventory + protected List GetSacrificedItems(PmcData pmcData) + { + throw new NotImplementedException(); + } + + /// + /// Given a pool of items + rouble budget, pick items until the budget is reached + /// + /// Items that can be picked + /// Rouble budget to reach + /// Id of stash item + /// Array of item arrays + protected List> GetRewardsWithinBudget( + List rewardItemTplPool, + double rewardBudget, + string cultistCircleStashId, + CultistCircleSettings circleConfig + ) + { + throw new NotImplementedException(); + } + + /// + /// Get direct rewards + /// + /// sessionId + /// Items sacrificed + /// Id of stash item + /// The reward object + protected List> GetDirectRewards( + string sessionId, + DirectRewardSettings directReward, + string cultistCircleStashId + ) + { + throw new NotImplementedException(); + } + + /// + /// Check for direct rewards from what player sacrificed + /// + /// sessionId + /// Items sacrificed + /// Direct reward items to send to player + protected DirectRewardSettings CheckForDirectReward( + string sessionId, + List sacrificedItems, + Dictionary directRewardsCache + ) + { + throw new NotImplementedException(); + } + + /// + /// Create an md5 key of the sacrificed + reward items + /// + /// Direct reward to create key for + /// Key + protected string GetDirectRewardHashKey(DirectRewardSettings directReward) + { + throw new NotImplementedException(); + } + + /// + /// Explicit rewards have their own stack sizes as they don't use a reward rouble pool + /// + /// Item being rewarded to get stack size of + /// stack size of item + protected int GetDirectRewardBaseTypeStackSize(string rewardTpl) + { + throw new NotImplementedException(); + } + + /// + /// Add a record to the player's profile to signal they have accepted a non-repeatable direct reward + /// + /// Session id + /// Reward sent to player + protected void FlagDirectRewardAsAcceptedInProfile(string sessionId, DirectRewardSettings directReward) + { + throw new NotImplementedException(); + } + + /// + /// Get the size of a reward item's stack + /// 1 for everything except ammo, ammo can be between min stack and max stack + /// + /// Item chosen + /// Rouble amount of pool remaining to fill + /// Size of stack + protected int GetRewardStackSize(string itemTpl, int rewardPoolRemaining) + { + throw new NotImplementedException(); + } + + /// + /// Get a pool of tpl IDs of items the player needs to complete hideout crafts/upgrade areas + /// + /// Session id + /// Profile of player who will be getting the rewards + /// Do we return bonus items (hideout/task items) + /// Circle config + /// Array of tpls + protected string[] GetCultistCircleRewardPool( + string sessionId, + PmcData pmcData, + CircleCraftDetails craftingInfo, + CultistCircleSettings cultistCircleConfig) + { + throw new NotImplementedException(); + } + + /// + /// Check player's profile for quests with hand-in requirements and add those required items to the pool + /// + /// Player profile + /// Items not to add to pool + /// Pool to add items to + protected void AddTaskItemRequirementsToRewardPool( + PmcData pmcData, + HashSet itemRewardBlacklist, + HashSet rewardPool) + { + throw new NotImplementedException(); + } + + /// + /// Adds items the player needs to complete hideout crafts/upgrades to the reward pool + /// + /// Hideout area data + /// Player profile + /// Items not to add to pool + /// Pool to add items to + protected void AddHideoutUpgradeRequirementsToRewardPool( + Hideout hideoutDbData, + PmcData pmcData, + HashSet itemRewardBlacklist, + HashSet rewardPool) + { + throw new NotImplementedException(); + } + + /// + /// Get all active hideout areas + /// + /// Hideout areas to iterate over + /// Active area array + protected BotHideoutArea[] GetPlayerAccessibleHideoutAreas(BotHideoutArea[] areas) + { + throw new NotImplementedException(); + } + + /// + /// Get array of random reward items + /// + /// Reward pool to add to + /// Item tpls to ignore + /// Should these items meet the valuable threshold + /// Set of item tpls + protected HashSet GenerateRandomisedItemsAndAddToRewardPool( + HashSet rewardPool, + HashSet itemRewardBlacklist, + bool itemsShouldBeHighValue) + { + throw new NotImplementedException(); + } + + /// + /// Iterate over passed in hideout requirements and return the Item + /// + /// Requirements to iterate over + /// Array of item requirements + protected (StageRequirement[] StageRequirement, Requirement[] Requirement) GetItemRequirements(RequirementBase[] requirements) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/CustomLocationWaveService.cs b/Core/Services/CustomLocationWaveService.cs new file mode 100644 index 00000000..3301a1c7 --- /dev/null +++ b/Core/Services/CustomLocationWaveService.cs @@ -0,0 +1,52 @@ +using Core.Models.Eft.Common; + +namespace Core.Services; + +public class CustomLocationWaveService +{ + /// + /// Add a boss wave to a map + /// + /// e.g. factory4_day, bigmap + /// Boss wave to add to map + public void AddBossWaveToMap(string locationId, BossLocationSpawn waveToAdd) + { + throw new NotImplementedException(); + } + + /// + /// Add a normal bot wave to a map + /// + /// e.g. factory4_day, bigmap + /// Wave to add to map + public void AddNormalWaveToMap(string locationId, Wave waveToAdd) + { + throw new NotImplementedException(); + } + + /// + /// Clear all custom boss waves from a map + /// + /// e.g. factory4_day, bigmap + public void ClearBossWavesForMap(string locationId) + { + throw new NotImplementedException(); + } + + /// + /// Clear all custom normal waves from a map + /// + /// e.g. factory4_day, bigmap + public void ClearNormalWavesForMap(string locationId) + { + throw new NotImplementedException(); + } + + /// + /// Add custom boss and normal waves to maps found in config/location.json to db + /// + public void ApplyWaveChangesToAllMaps() + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/FenceService.cs b/Core/Services/FenceService.cs new file mode 100644 index 00000000..d4537fe9 --- /dev/null +++ b/Core/Services/FenceService.cs @@ -0,0 +1,512 @@ +using Core.Models.Eft.Common; +using Core.Models.Eft.Common.Tables; +using Core.Models.Spt.Config; +using Core.Models.Spt.Fence; + +namespace Core.Services; + +public class FenceService +{ + /// + /// Replace main fence assort with new assort + /// + /// New assorts to replace old with + public void SetFenceAssort(TraderAssort assort) + { + throw new NotImplementedException(); + } + + /// + /// Replace discount fence assort with new assort + /// + /// New assorts to replace old with + public void SetDiscountFenceAssort(TraderAssort assort) + { + throw new NotImplementedException(); + } + + /// + /// Get main fence assort + /// + /// TraderAssort + public TraderAssort GetMainFenceAssort() + { + throw new NotImplementedException(); + } + + /// + /// Get discount fence assort + /// + /// TraderAssort + public TraderAssort GetDiscountFenceAssort() + { + throw new NotImplementedException(); + } + + /// + /// Replace high rep level fence assort with new assort + /// + /// New assorts to replace old with + public void SetFenceDiscountAssort(TraderAssort discountAssort) + { + throw new NotImplementedException(); + } + + /// + /// Get assorts player can purchase + /// Adjust prices based on fence level of player + /// + /// Player profile + /// TraderAssort + public TraderAssort GetFenceAssorts(PmcData pmcProfile) + { + throw new NotImplementedException(); + } + + /// + /// Adds to fence assort a single item (with its children) + /// + /// the items to add with all its childrens + /// the most parent item of the array + public void AddItemsToFenceAssort(List items, Item mainItem) + { + throw new NotImplementedException(); + } + + /// + /// Calculates the overall price for an item (with all its children) + /// + /// the item tpl to calculate the fence price for + /// the items (with its children) to calculate fence price for + /// the fence price of the item + public double GetItemPrice(string itemTpl, List items) + { + throw new NotImplementedException(); + } + + /// + /// Calculate the overall price for an ammo box, where only one item is + /// the ammo box itself and every other items are the bullets in that box + /// + /// the ammo box (and all its children ammo items) + /// the price of the ammo box + protected double GetAmmoBoxPrice(List items) + { + throw new NotImplementedException(); + } + + /// + /// Adjust all items contained inside an assort by a multiplier + /// + /// (clone)Assort that contains items with prices to adjust + /// multipler to use on items + /// preset multipler to use on presets + protected void AdjustAssortItemPricesByConfigMultiplier( + TraderAssort assort, + double itemMultipler, + double presetMultiplier) + { + throw new NotImplementedException(); + } + + /// + /// Merge two trader assort files together + /// + /// assort 1# + /// assort #2 + /// merged assort + protected TraderAssort MergeAssorts(TraderAssort firstAssort, TraderAssort secondAssort) + { + throw new NotImplementedException(); + } + + /// + /// Adjust assorts price by a modifier + /// + /// assort item details + /// assort to be modified + /// value to multiply item price by + /// value to multiply preset price by + protected void AdjustItemPriceByModifier( + Item item, + TraderAssort assort, + double modifier, + double presetModifier) + { + throw new NotImplementedException(); + } + + /// + /// Get fence assorts with no price adjustments based on fence rep + /// + /// TraderAssort + public TraderAssort GetRawFenceAssorts() + { + throw new NotImplementedException(); + } + + /// + /// Does fence need to perform a partial refresh because its passed the refresh timer defined in trader.json + /// + /// true if it needs a partial refresh + public bool NeedsPartialRefresh() + { + throw new NotImplementedException(); + } + + /// + /// Replace a percentage of fence assorts with freshly generated items + /// + public void PerformPartialRefresh() + { + throw new NotImplementedException(); + } + + /// + /// Handle the process of folding new assorts into existing assorts, when a new assort exists already, increment its StackObjectsCount instead + /// + /// Assorts to fold into existing fence assorts + /// Current fence assorts new assorts will be added to + protected void UpdateFenceAssorts( + CreateFenceAssortsResult newFenceAssorts, + TraderAssort existingFenceAssorts + ) + { + throw new NotImplementedException(); + } + + /// + /// Increment fence next refresh timestamp by current timestamp + partialRefreshTimeSeconds from config + /// + protected void IncrementPartialRefreshTime() + { + throw new NotImplementedException(); + } + + /// + /// Get values that will hydrate the passed in assorts back to the desired counts + /// + /// Current assorts after items have been removed + /// Base counts assorts should be adjusted to + /// GenerationAssortValues object with adjustments needed to reach desired state + protected GenerationAssortValues GetItemCountsToGenerate( + Item[] assortItems, + GenerationAssortValues generationValues + ) + { + throw new NotImplementedException(); + } + + /// + /// Delete desired number of items from assort (including children) + /// + /// + /// + protected void DeleteRandomAssorts(int itemCountToReplace, TraderAssort assort) + { + throw new NotImplementedException(); + } + + /// + /// Choose an item at random and remove it + mods from assorts + /// + /// Trader assort to remove item from + /// Pool of root items to pick from to remove + protected void RemoveRandomItemFromAssorts(TraderAssort assort, Item[] rootItems) + { + throw new NotImplementedException(); + } + + /// + /// Get an integer rounded count of items to replace based on percentrage from traderConfig value + /// + /// total item count + /// rounded int of items to replace + protected int GetCountOfItemsToReplace(int totalItemCount) + { + throw new NotImplementedException(); + } + + /// + /// Get the count of items fence offers + /// + /// int + public int GetOfferCount() + { + throw new NotImplementedException(); + } + + /// + /// Create trader assorts for fence and store in fenceService cache + /// Uses fence base cache generated on server start as a base + /// + public void GenerateFenceAssorts() + { + throw new NotImplementedException(); + } + + /// + /// Convert the intermediary assort data generated into format client can process + /// + /// Generated assorts that will be converted + /// TraderAssort + protected TraderAssort ConvertIntoFenceAssort(CreateFenceAssortsResult intermediaryAssorts) + { + throw new NotImplementedException(); + } + + /// + /// Create object that contains calculated fence assort item values to make based on config + /// Stored in this.DesiredAssortCounts + /// + protected void CreateInitialFenceAssortGenerationValues() + { + throw new NotImplementedException(); + } + + /// + /// Create skeleton to hold assort items + /// + /// TraderAssort object + protected TraderAssort CreateFenceAssortSkeleton() + { + throw new NotImplementedException(); + } + + /// + /// Hydrate assorts parameter object with generated assorts + /// + /// Number of assorts to generate + /// Loyalty level to set new item to + /// CreateFenceAssortsResult + protected CreateFenceAssortsResult CreateAssorts(GenerationAssortValues itemCounts, int loyaltyLevel) + { + throw new NotImplementedException(); + } + + /// + /// Add item assorts to existing assort data + /// + /// Number to add + /// Assorts data to add to + /// Base data to draw from + /// + /// Loyalty level to set new item to + protected void AddItemAssorts( + int assortCount, + CreateFenceAssortsResult assorts, + TraderAssort baseFenceAssortClone, + Dictionary itemTypeLimits, + int loyaltyLevel + ) + { + throw new NotImplementedException(); + } + + /// + /// Find an assort item that matches the first parameter, also matches based on upd properties + /// e.g. salewa hp resource units left + /// + /// item to look for a match against + /// Db details of matching item + /// Items to search through + /// Matching assort item + protected virtual Item GetMatchingItem( + Item rootItemBeingAdded, + TemplateItem itemDbDetails, + List> itemsWithChildren) + { + throw new NotImplementedException(); + } + + /// + /// Should this item be forced into only 1 stack on fence + /// + /// Existing item from fence assort + /// Item we want to add db details + /// True item should be force stacked + protected virtual bool ItemShouldBeForceStacked(Item existingItem, TemplateItem itemDbDetails) + { + throw new NotImplementedException(); + } + + protected virtual bool ItemInPreventDupeCategoryList(string tpl) + { + throw new NotImplementedException(); + } + + /// + /// Adjust price of item based on what is left to buy (resource/uses left) + /// + /// All barter scheme for item having price adjusted + /// Root item having price adjusted + /// Db template of item + protected virtual void AdjustItemPriceByQuality( + Dictionary>> barterSchemes, + Item itemRoot, + TemplateItem itemTemplate) + { + throw new NotImplementedException(); + } + + protected virtual Dictionary GetMatchingItemLimit( + Dictionary itemTypeLimits, + string itemTpl) + { + throw new NotImplementedException(); + } + + /// + /// Find presets in base fence assort and add desired number to 'assorts' parameter + /// + /// + /// Assorts to add preset to + /// Base data to draw from + /// Which loyalty level is required to see/buy item + protected virtual void AddPresetsToAssort( + int desiredWeaponPresetsCount, + int desiredEquipmentPresetsCount, + CreateFenceAssortsResult assorts, + TraderAssort baseFenceAssort, + int loyaltyLevel) + { + throw new NotImplementedException(); + } + + /// + /// Adjust plate / soft insert durability values + /// + /// Armor item array to add mods into + /// Armor items db template + protected virtual void RandomiseArmorModDurability(List armor, TemplateItem itemDbDetails) + { + throw new NotImplementedException(); + } + + /// + /// Randomise the durability values of items on armor with a passed in slot + /// + /// Slots of items to randomise + /// Array of armor + inserts to get items from + protected virtual void RandomiseArmorSoftInsertDurabilities(List softInsertSlots, List armorItemAndMods) + { + throw new NotImplementedException(); + } + + /// + /// Randomise the durability values of plate items in armor + /// Has chance to remove plate + /// + /// Slots of items to randomise + /// Array of armor + inserts to get items from + protected virtual void RandomiseArmorInsertsDurabilities(List plateSlots, List armorItemAndMods) + { + throw new NotImplementedException(); + } + + /// + /// Get stack size of a singular item (no mods) + /// + /// item being added to fence + /// Stack size + protected virtual int GetSingleItemStackCount(TemplateItem itemDbDetails) + { + throw new NotImplementedException(); + } + + /// + /// Remove parts of a weapon prior to being listed on flea + /// + /// Weapon to remove parts from + protected virtual void RemoveRandomModsOfItem(List itemAndMods) + { + throw new NotImplementedException(); + } + + /// + /// Roll % chance check to see if item should be removed + /// + /// Weapon mod being checked + /// Current list of items on weapon being deleted + /// True if item will be removed + protected virtual bool PresetModItemWillBeRemoved(Item weaponMod, List itemsBeingDeleted) + { + throw new NotImplementedException(); + } + + /// + /// Randomise items' upd properties e.g. med packs/weapons/armor + /// + /// Item being randomised + /// Item being edited + protected virtual void RandomiseItemUpdProperties(TemplateItem itemDetails, Item itemToAdjust) + { + throw new NotImplementedException(); + } + + /// + /// Generate a randomised current and max durabiltiy value for an armor item + /// + /// Item to create values for + /// Max durabiltiy percent min/max values + /// Durability + MaxDurability values + protected virtual UpdRepairable GetRandomisedArmorDurabilityValues( + TemplateItem itemDetails, + ItemDurabilityCurrentMax equipmentDurabilityLimits) + { + throw new NotImplementedException(); + } + + /// + /// Construct item limit record to hold max and current item count + /// + /// limits as defined in config + /// record, key: item tplId, value: current/max item count allowed + protected Dictionary InitItemLimitCounter(Dictionary limits) + { + throw new NotImplementedException(); + } + + /// + /// Get the next update timestamp for fence + /// + /// future timestamp + public int GetNextFenceUpdateTimestamp() + { + throw new NotImplementedException(); + } + + /// + /// Get fence refresh time in seconds + /// + /// Refresh time in seconds + protected int GetFenceRefreshTime() + { + throw new NotImplementedException(); + } + + /// + /// Get fence level the passed in profile has + /// + /// Player profile + /// FenceLevel object + public FenceLevel GetFenceInfo(PmcData pmcData) + { + throw new NotImplementedException(); + } + + /// + /// Remove or lower stack size of an assort from fence by id + /// + /// assort id to adjust + /// Count of items bought + public void AmendOrRemoveFenceOffer(string assortId, int buyCount) + { + throw new NotImplementedException(); + } + + protected void DeleteOffer(string assortId, List assorts) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/GiftService.cs b/Core/Services/GiftService.cs new file mode 100644 index 00000000..11a2d3d0 --- /dev/null +++ b/Core/Services/GiftService.cs @@ -0,0 +1,81 @@ +using Core.Models.Enums; +using Core.Models.Spt.Config; + +namespace Core.Services; + +public class GiftService +{ + /** + * Does a gift with a specific ID exist in db + * @param giftId Gift id to check for + * @returns True if it exists in db + */ + public bool GiftExists(string giftId) + { + throw new NotImplementedException(); + } + + public Gift GetGiftById(string giftId) + { + throw new NotImplementedException(); + } + + /** + * Get dictionary of all gifts + * @returns Dict keyed by gift id + */ + public Dictionary GetGifts() + { + throw new NotImplementedException(); + } + + /** + * Get an array of all gift ids + * @returns string array of gift ids + */ + public List GetGiftIds() + { + throw new NotImplementedException(); + } + + /** + * Send player a gift from a range of sources + * @param playerId Player to send gift to / sessionId + * @param giftId Id of gift in configs/gifts.json to send player + * @returns outcome of sending gift to player + */ + public GiftSentResult SendGiftToPlayer(string playerId, string giftId) + { + throw new NotImplementedException(); + } + + /** + * Get sender id based on gifts sender type enum + * @param giftData Gift to send player + * @returns trader/user/system id + */ + protected string? GetSenderId(Gift giftData) + { + throw new NotImplementedException(); + } + + /** + * Convert GiftSenderType into a dialog MessageType + * @param giftData Gift to send player + * @returns MessageType enum value + */ + protected MessageType? GetMessageType(Gift giftData) + { + throw new NotImplementedException(); + } + + /** + * Prapor sends gifts to player for first week after profile creation + * @param sessionId Player id + * @param day What day to give gift for + */ + public void SendPraporStartingGift(string sessionId, int day) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/InMemoryCacheService.cs b/Core/Services/InMemoryCacheService.cs new file mode 100644 index 00000000..5e891ddf --- /dev/null +++ b/Core/Services/InMemoryCacheService.cs @@ -0,0 +1,35 @@ +namespace Core.Services; + +public class InMemoryCacheService +{ + // Store data into an in-memory object + // key to store data against + // Data to store in cache + public void StoreByKey(string key, object dataToCache) + { + throw new NotImplementedException(); + } + + // Retreve data stored by a key + // key + // Stored data + public T GetDataByKey(string key) + { + throw new NotImplementedException(); + } + + // Does data exists against the provided key + // Key to check for data against + // true if exists + public bool HasStoredDataByKey(string key) + { + throw new NotImplementedException(); + } + + // Remove data stored against key + // Key to remove data against + public void ClearDataStoredByKey(string key) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/InsuranceService.cs b/Core/Services/InsuranceService.cs new file mode 100644 index 00000000..71005a82 --- /dev/null +++ b/Core/Services/InsuranceService.cs @@ -0,0 +1,150 @@ +using Core.Models.Eft.Common; +using Core.Models.Eft.Common.Tables; +using Core.Models.Spt.Services; + +namespace Core.Services; + +public class InsuranceService +{ + /// + /// Does player have insurance dictionary exists + /// + /// Player id + /// True if exists + public bool InsuranceDictionaryExists(string sessionId) + { + throw new NotImplementedException(); + } + + /// + /// Get all insured items by all traders for a profile + /// + /// Profile id (session id) + /// Item list + public Dictionary> GetInsurance(string sessionId) + { + throw new NotImplementedException(); + } + + public void ResetInsurance(string sessionId) + { + throw new NotImplementedException(); + } + + /// + /// Sends 'I will go look for your stuff' trader message + + /// Store lost insurance items inside profile for later retrieval + /// + /// Profile to send insured items to + /// SessionId of current player + /// Id of the location player died/exited that caused the insurance to be issued on + public void StartPostRaidInsuranceLostProcess(PmcData pmcData, string sessionID, string mapId) + { + throw new NotImplementedException(); + } + + /// + /// Get a timestamp of when insurance items should be sent to player based on trader used to insure + /// Apply insurance return bonus if found in profile + /// + /// Player profile + /// Trader base used to insure items + /// Timestamp to return items to player in seconds + protected double GetInsuranceReturnTimestamp(PmcData pmcData, TraderBase trader) + { + throw new NotImplementedException(); + } + + protected double GetMaxInsuranceStorageTime(TraderBase traderBase) + { + throw new NotImplementedException(); + } + + /// + /// Store lost gear post-raid inside profile, ready for later code to pick it up and mail it + /// + /// Gear to store - generated by GetGearLostInRaid() + public void StoreGearLostInRaidToSendLater(string sessionID, List equipmentPkg) + { + throw new NotImplementedException(); + } + + /// + /// For the passed in items, find the trader it was insured against + /// + /// Session id + /// Insured items lost in a raid + /// Player profile + /// InsuranceEquipmentPkg list + public List MapInsuredItemsToTrader( + string sessionId, + List lostInsuredItems, + PmcData pmcProfile) + { + throw new NotImplementedException(); + } + + /// + /// Some items should never be returned in insurance but BSG send them in the request + /// + /// Item being returned in insurance + /// Player inventory + /// True if item + protected bool ItemCannotBeLostOnDeath(Item lostItem, List inventoryItems) + { + throw new NotImplementedException(); + } + + /// + /// Add gear item to InsuredItems list in player profile + /// + /// Gear to send + protected void AddGearToSend(InsuranceEquipmentPkg gear) + { + throw new NotImplementedException(); + } + + /// + /// Does insurance exist for a player and by trader + /// + /// Player id (session id) + /// Trader items insured with + /// True if exists + protected bool InsuranceTraderArrayExists(string sessionId, string traderId) + { + throw new NotImplementedException(); + } + + /// + /// Empty out list holding insured items by sessionid + traderid + /// + /// Player id (session id) + /// Trader items insured with + public void ResetInsuranceTraderArray(string sessionId, string traderId) + { + throw new NotImplementedException(); + } + + /// + /// Store insured item + /// + /// Player id (session id) + /// Trader item insured with + /// Insured item (with children) + public void AddInsuranceItemToArray(string sessionId, string traderId, Item itemToAdd) + { + throw new NotImplementedException(); + } + + /// + /// Get price of insurance * multiplier from config + /// + /// Player profile + /// Item to be insured + /// Trader item is insured with + /// price in roubles + public double GetRoublePriceToInsureItemWithTrader(PmcData pmcData, Item inventoryItem, string traderId) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/ItemBaseClassService.cs b/Core/Services/ItemBaseClassService.cs new file mode 100644 index 00000000..a9efa4c0 --- /dev/null +++ b/Core/Services/ItemBaseClassService.cs @@ -0,0 +1,56 @@ +using Core.Models.Eft.Common.Tables; + +namespace Core.Services; + +public class ItemBaseClassService +{ + /** + * Create cache and store inside ItemBaseClassService + * Store a dict of an items tpl to the base classes it and its parents have + */ + public void HydrateItemBaseClassCache() + { + throw new NotImplementedException(); + } + + /** + * Helper method, recursively iterate through items parent items, finding and adding ids to dictionary + * @param itemIdToUpdate item tpl to store base ids against in dictionary + * @param item item being checked + */ + protected void AddBaseItems(string itemIdToUpdate, TemplateItem item) + { + throw new NotImplementedException(); + } + + /** + * Does item tpl inherit from the requested base class + * @param itemTpl item to check base classes of + * @param baseClass base class to check for + * @returns true if item inherits from base class passed in + */ + public bool ItemHasBaseClass(string itemTpl, List baseClasses) + { + throw new NotImplementedException(); + } + + /** + * Check if cached item template is of type Item + * @param itemTemplateId item to check + * @returns true if item is of type Item + */ + private bool CachedItemIsOfItemType(string itemTemplateId) + { + throw new NotImplementedException(); + } + + /** + * Get base classes item inherits from + * @param itemTpl item to get base classes for + * @returns array of base classes + */ + public List GetItemBaseClasses(string itemTpl) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/ItemFilterService.cs b/Core/Services/ItemFilterService.cs new file mode 100644 index 00000000..cd11223d --- /dev/null +++ b/Core/Services/ItemFilterService.cs @@ -0,0 +1,89 @@ +namespace Core.Services; + +public class ItemFilterService +{ + /** + * Check if the provided template id is blacklisted in config/item.json/blacklist + * @param tpl template id + * @returns true if blacklisted + */ + public bool ItemBlacklisted(string tpl) + { + throw new NotImplementedException(); + } + + /** + * Check if the provided template id is blacklisted in config/item.json/lootableItemBlacklist + * @param tpl template id + * @returns true if blacklisted + */ + public bool LootableItemBlacklisted(string tpl) + { + throw new NotImplementedException(); + } + + /** + * Check if item is blacklisted from being a reward for player + * @param tpl item tpl to check is on blacklist + * @returns True when blacklisted + */ + public bool ItemRewardBlacklisted(string tpl) + { + throw new NotImplementedException(); + } + + /** + * Get an array of items that should never be given as a reward to player + * @returns string array of item tpls + */ + public List GetItemRewardBlacklist() + { + throw new NotImplementedException(); + } + + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + public List GetItemRewardBaseTypeBlacklist() + { + throw new NotImplementedException(); + } + + /** + * Return every template id blacklisted in config/item.json + * @returns string array of blacklisted template ids + */ + public List GetBlacklistedItems() + { + throw new NotImplementedException(); + } + + /** + * Return every template id blacklisted in config/item.json/lootableItemBlacklist + * @returns string array of blacklisted template ids + */ + public List GetBlacklistedLootableItems() + { + throw new NotImplementedException(); + } + + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + public bool BossItem(string tpl) + { + throw new NotImplementedException(); + } + + /** + * Return boss items in config/item.json + * @returns string array of boss item template ids + */ + public List GetBossItems() + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/LegacyLocationLifecycleService.cs b/Core/Services/LegacyLocationLifecycleService.cs new file mode 100644 index 00000000..54675638 --- /dev/null +++ b/Core/Services/LegacyLocationLifecycleService.cs @@ -0,0 +1,75 @@ +using System.Text.Json.Serialization; +using Core.Models.Eft.Common; +using Core.Models.Eft.Match; + +namespace Core.Services; + +public class LegacyLocationLifecycleService +{ + /// + /// Handle client/match/offline/end + /// + public void endOfflineRaid(EndOfflineRaidRequestData info, string sessionId) + { + throw new NotImplementedException(); + } + + /// + /// Handle when a player extracts using a car - Add rep to fence + /// + /// name of the extract used + /// Player profile + /// Session id + protected void handleCarExtract(string extractName, PmcData pmcData, string sessionId) + { + throw new NotImplementedException(); + } + + /// + /// Get the fence rep gain from using a car or coop extract + /// + /// Profile + /// amount gained for the first extract + /// Number of times extract was taken + /// Fence standing after taking extract + protected int getFenceStandingAfterExtract(PmcData pmcData, int baseGain, int extractCount) + { + throw new NotImplementedException(); + } + + /// + /// Was extract by car + /// + /// name of extract + /// true if car extract + protected bool extractWasViaCar(string extractName) + { + throw new NotImplementedException(); + } + + /// + /// Did player take a COOP extract + /// + /// Name of extract player took + /// True if coop extract + protected bool extractWasViaCoop(string extractName) + { + throw new NotImplementedException(); + } + + /// + /// Handle when a player extracts using a coop extract - add rep to fence + /// + /// Session/player id + /// Profile + /// Name of extract taken + protected void handleCoopExtract(string sessionId, PmcData pmcData, string extractName) + { + throw new NotImplementedException(); + } + + protected void sendCoopTakenFenceMessage(string sessionId) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/LocationLifecycleService.cs b/Core/Services/LocationLifecycleService.cs new file mode 100644 index 00000000..4fe65e52 --- /dev/null +++ b/Core/Services/LocationLifecycleService.cs @@ -0,0 +1,255 @@ +using Core.Models.Eft.Common; +using Core.Models.Eft.Common.Tables; +using Core.Models.Eft.Match; + +namespace Core.Services; + +public class LocationLifecycleService +{ + /** Handle client/match/local/start */ + public void StartLocalRaid(string sessionId, StartLocalRaidRequestData request) + { + throw new NotImplementedException(); + } + + /** + * Replace map exits with scav exits when player is scavving + * @param playerSide Players side (savage/usec/bear) + * @param location id of map being loaded + * @param locationData Maps location base data + */ + protected void AdjustExtracts(string playerSide, string location, LocationBase locationData) + { + throw new NotImplementedException(); + } + + /** + * Adjust the bot hostility values prior to entering a raid + * @param location map to adjust values of + */ + protected void AdjustBotHostilitySettings(LocationBase location) + { + throw new NotImplementedException(); + } + + /** + * Generate a maps base location (cloned) and loot + * @param name Map name + * @param generateLoot OPTIONAL - Should loot be generated for the map before being returned + * @returns LocationBase + */ + protected LocationBase GenerateLocationAndLoot(string name, bool generateLoot = true) + { + throw new NotImplementedException(); + } + + /** Handle client/match/local/end */ + public void EndLocalRaid(string sessionId, EndLocalRaidRequestData request) + { + throw new NotImplementedException(); + } + + /** + * Was extract by car + * @param extractName name of extract + * @returns True if extract was by car + */ + protected bool ExtractWasViaCar(string extractName) + { + throw new NotImplementedException(); + } + + /** + * Handle when a player extracts using a car - Add rep to fence + * @param extractName name of the extract used + * @param pmcData Player profile + * @param sessionId Session id + */ + protected void HandleCarExtract(string extractName, PmcData pmcData, string sessionId) + { + throw new NotImplementedException(); + } + + /** + * Handle when a player extracts using a coop extract - add rep to fence + * @param sessionId Session/player id + * @param pmcData Profile + * @param extractName Name of extract taken + */ + protected void HandleCoopExtract(string sessionId, PmcData pmcData, string extractName) + { + throw new NotImplementedException(); + } + + /** + * Get the fence rep gain from using a car or coop extract + * @param pmcData Profile + * @param baseGain amount gained for the first extract + * @param extractCount Number of times extract was taken + * @returns Fence standing after taking extract + */ + protected int GetFenceStandingAfterExtract(PmcData pmcData, int baseGain, int extractCount) + { + throw new NotImplementedException(); + } + + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected bool ExtractTakenWasCoop(string extractName) + { + throw new NotImplementedException(); + } + + protected void HandlePostRaidPlayerScav( + string sessionId, + PmcData pmcProfile, + PmcData scavProfile, + bool isDead, + bool isTransfer, + EndLocalRaidRequestData request) + { + throw new NotImplementedException(); + } + + /** + * + * @param sessionId Player id + * @param pmcProfile Pmc profile + * @param scavProfile Scav profile + * @param isDead Player died/got left behind in raid + * @param isSurvived Not same as opposite of `isDead`, specific status + * @param request + * @param locationName + */ + protected void HandlePostRaidPmc( + string sessionId, + PmcData pmcProfile, + PmcData scavProfile, + bool isDead, + bool isSurvived, + bool isTransfer, + EndLocalRaidRequestData request, + string locationName) + { + throw new NotImplementedException(); + } + + protected void CheckForAndFixPickupQuestsAfterDeath( + string sessionId, + List lostQuestItems, + List profileQuests + ) + { + throw new NotImplementedException(); + } + +/* + * In 0.15 Lightkeeper quests do not give rewards in PvE, this issue also occurs in spt + * We check for newly completed Lk quests and run them through the servers `CompleteQuest` process + * This rewards players with items + craft unlocks + new trader assorts + */ + protected void LightkeeperQuestWorkaround( + string sessionId, + List postRaidQuests, + List preRaidQuests, + PmcData pmcProfile + ) + { + throw new NotImplementedException(); + } + +/* + * Convert post-raid quests into correct format + * Quest status comes back as a string version of the enum `Success`, not the expected value of 1 + */ + protected List ProcessPostRaidQuests(List questsToProcess) + { + throw new NotImplementedException(); + } + +/* + * Adjust server trader settings if they differ from data sent by client + */ + protected void ApplyTraderStandingAdjustments( + Dictionary tradersServerProfile, + Dictionary tradersClientProfile + ) + { + throw new NotImplementedException(); + } + +/* + * Check if player used BTR or transit item sending service and send items to player via mail if found + */ + protected void HandleItemTransferEvent(string sessionId, EndLocalRaidRequestData request) + { + throw new NotImplementedException(); + } + + protected void TransferItemDelivery(string sessionId, string traderId, List items) + { + throw new NotImplementedException(); + } + + protected void HandleInsuredItemLostEvent( + string sessionId, + PmcData preRaidPmcProfile, + EndLocalRaidRequestData request, + string locationName + ) + { + throw new NotImplementedException(); + } + +/* + * Return the equipped items from a players inventory + */ + protected List GetEquippedGear(List items) + { + throw new NotImplementedException(); + } + +/* + * Checks to see if player survives. run through will return false + */ + protected bool IsPlayerSurvived(EndRaidResult results) + { + throw new NotImplementedException(); + } + +/* + * Is the player dead after a raid - dead = anything other than "survived" / "runner" + */ + protected bool IsPlayerDead(EndRaidResult results) + { + throw new NotImplementedException(); + } + +/* + * Has the player moved from one map to another + */ + protected bool IsMapToMapTransfer(EndRaidResult results) + { + throw new NotImplementedException(); + } + +/* + * Reset the skill points earned in a raid to 0, ready for next raid + */ + protected void ResetSkillPointsEarnedDuringRaid(List commonSkills) + { + throw new NotImplementedException(); + } + +/* + * merge two dictionaries together + * Prioritise pair that has true as a value + */ + protected void MergePmcAndScavEncyclopedias(PmcData primary, PmcData secondary) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/MapMarkerService.cs b/Core/Services/MapMarkerService.cs new file mode 100644 index 00000000..e516ef5a --- /dev/null +++ b/Core/Services/MapMarkerService.cs @@ -0,0 +1,240 @@ +using Core.Models.Eft.Common; +using Core.Models.Eft.Common.Tables; +using Core.Models.Eft.Inventory; +using Core.Models.Eft.Profile; +using Core.Models.Enums; +using Core.Models.Spt.Dialog; + +namespace Core.Services; + +public class MapMarkerService +{ + /// + /// Add note to a map item in player inventory + /// + /// Player profile + /// Add marker request + /// Item + public Item CreateMarkerOnMap(PmcData pmcData, InventoryCreateMarkerRequestData request) + { + throw new NotImplementedException(); + } + + /// + /// Delete a map marker + /// + /// Player profile + /// Delete marker request + /// Item + public Item DeleteMarkerFromMap(PmcData pmcData, InventoryDeleteMarkerRequestData request) + { + throw new NotImplementedException(); + } + + /// + /// Edit an existing map marker + /// + /// Player profile + /// Edit marker request + /// Item + public Item EditMarkerOnMap(PmcData pmcData, InventoryEditMarkerRequestData request) + { + throw new NotImplementedException(); + } + + /// + /// Strip out characters from note string that are not: letter/numbers/unicode/spaces + /// + /// Marker text to sanitise + /// Sanitised map marker text + protected string SanitiseMapMarkerText(string mapNoteText) + { + throw new NotImplementedException(); + } + + /// + /// Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale + /// + /// The session ID to send the message to + /// The trader sending the message + /// What type the message will assume (e.g. QUEST_SUCCESS) + /// Text to send to the player + /// Optional items to send to player + /// Optional time to collect items before they expire + public void SendDirectNpcMessageToPlayer( + string sessionId, + object trader, + MessageType messageType, + string message, + List items = null, + int? maxStorageTimeSeconds = null, + SystemData systemData = null, + MessageContentRagfair ragfair = null) + { + throw new NotImplementedException(); + } + + /// + /// Send a message from an NPC (e.g. prapor) to the player with or without items + /// + /// The session ID to send the message to + /// The trader sending the message + /// What type the message will assume (e.g. QUEST_SUCCESS) + /// The localised text to send to player + /// Optional items to send to player + /// Optional time to collect items before they expire + public void SendLocalisedNpcMessageToPlayer( + string sessionId, + object trader, + MessageType messageType, + string messageLocaleId, + List items = null, + int? maxStorageTimeSeconds = null, + SystemData systemData = null, + MessageContentRagfair ragfair = null) + { + throw new NotImplementedException(); + } + + /// + /// Send a message from SYSTEM to the player with or without items + /// + /// The session ID to send the message to + /// The text to send to player + /// Optional items to send to player + /// Optional time to collect items before they expire + public void SendSystemMessageToPlayer( + string sessionId, + string message, + List items = null, + int? maxStorageTimeSeconds = null, + List profileChangeEvents = null) + { + throw new NotImplementedException(); + } + + /// + /// Send a message from SYSTEM to the player with or without items with localised text + /// + /// The session ID to send the message to + /// Id of key from locale file to send to player + /// Optional items to send to player + /// Optional time to collect items before they expire + public void SendLocalisedSystemMessageToPlayer( + string sessionId, + string messageLocaleId, + List items = null, + List profileChangeEvents = null, + int? maxStorageTimeSeconds = null) + { + throw new NotImplementedException(); + } + + /// + /// Send a USER message to a player with or without items + /// + /// The session ID to send the message to + /// Who is sending the message + /// The text to send to player + /// Optional items to send to player + /// Optional time to collect items before they expire + public void SendUserMessageToPlayer( + string sessionId, + UserDialogInfo senderDetails, + string message, + List items = null, + int? maxStorageTimeSeconds = null) + { + throw new NotImplementedException(); + } + + /// + /// Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) + /// Helper functions in this class are available to simplify common actions + /// + /// Details needed to send a message to the player + public void SendMessageToPlayer(SendMessageDetails messageDetails) + { + throw new NotImplementedException(); + } + + /// + /// Send a message from the player to an NPC + /// + /// Player id + /// NPC message is sent to + /// Text to send to NPC + public void SendPlayerMessageToNpc(string sessionId, string targetNpcId, string message) + { + throw new NotImplementedException(); + } + + /// + /// Create a message for storage inside a dialog in the player profile + /// + /// Id of dialog that will hold the message + /// Various details on what the message must contain/do + /// Message + protected Message CreateDialogMessage(string dialogId, SendMessageDetails messageDetails) + { + throw new NotImplementedException(); + } + + /// + /// Add items to message and adjust various properties to reflect the items being added + /// + /// Message to add items to + /// Items to add to message + /// total time items are stored in mail before being deleted + protected void AddRewardItemsToMessage( + Message message, + List itemsToSendToPlayer, + int? maxStorageTimeSeconds) + { + throw new NotImplementedException(); + } + + /// + /// perform various sanitising actions on the items before they're considered ready for insertion into message + /// + /// The type of the dialog that will hold the reward items being processed + /// + /// Sanitised items + protected List ProcessItemsBeforeAddingToMail( + MessageType dialogType, + SendMessageDetails messageDetails) + { + throw new NotImplementedException(); + } + + /// + /// Try to find the most correct item to be the 'primary' item in a reward mail + /// + /// Possible items to choose from + /// Chosen 'primary' item + protected Item GetBaseItemFromRewards(List items) + { + throw new NotImplementedException(); + } + + /// + /// Get a dialog with a specified entity (user/trader) + /// Create and store empty dialog if none exists in profile + /// + /// Data on what message should do + /// Relevant Dialogue + protected Dialogue GetDialog(SendMessageDetails messageDetails) + { + throw new NotImplementedException(); + } + + /// + /// Get the appropriate sender id by the sender enum type + /// + /// + /// gets an id of the individual sending it + protected string GetMessageSenderIdByType(SendMessageDetails messageDetails) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/MatchBotDeatilsCacheService.cs b/Core/Services/MatchBotDeatilsCacheService.cs new file mode 100644 index 00000000..a7d4fd21 --- /dev/null +++ b/Core/Services/MatchBotDeatilsCacheService.cs @@ -0,0 +1,34 @@ +using Core.Models.Eft.Common.Tables; + +namespace Core.Services; + +public class MatchBotDeatilsCacheService +{ + /// + /// Store a bot in the cache, keyed by its name + /// + /// Bot details to cache + public void CacheBot(BotBase botToCache) + { + throw new NotImplementedException(); + } + + /// + /// Clean the cache of all bot details + /// + public void ClearCache() + { + throw new NotImplementedException(); + } + + /// + /// Find a bot in the cache by its name and side + /// + /// Name of bot to find + /// Side of the bot to find + /// Bot details + public BotBase GetBotByNameAndSide(string botName, string botSide) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/MatchLocationService.cs b/Core/Services/MatchLocationService.cs new file mode 100644 index 00000000..bf53194c --- /dev/null +++ b/Core/Services/MatchLocationService.cs @@ -0,0 +1,9 @@ +namespace Core.Services; + +public class MatchLocationService +{ + public void DeleteGroup(object info) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/Mod/CustomItemService.cs b/Core/Services/Mod/CustomItemService.cs new file mode 100644 index 00000000..b40555a1 --- /dev/null +++ b/Core/Services/Mod/CustomItemService.cs @@ -0,0 +1,124 @@ +using Core.Models.Eft.Common.Tables; +using Core.Models.Spt.Mod; + +namespace Core.Services.Mod; + +public class CustomItemService +{ + /** + * Create a new item from a cloned item base + * WARNING - If no item id is supplied, an id will be generated, this id will be random every time you add an item and will not be the same on each subsequent server start + * Add to the items db + * Add to the flea market + * Add to the handbook + * Add to the locales + * @param newItemDetails Item details for the new item to be created + * @returns tplId of the new item created + */ + public CreateItemResult CreateItemFromClone(NewItemFromCloneDetails newItemDetails) + { + throw new NotImplementedException(); + } + + /** + * Create a new item without using an existing item as a template + * Add to the items db + * Add to the flea market + * Add to the handbook + * Add to the locales + * @param newItemDetails Details on what the item to be created + * @returns CreateItemResult containing the completed items Id + */ + public CreateItemResult CreateItem(NewItemDetails newItemDetails) + { + throw new NotImplementedException(); + } + + /** + * If the id provided is an empty string, return a randomly generated guid, otherwise return the newId parameter + * @param newId id supplied to code + * @returns item id + */ + protected string GetOrGenerateIdForItem(string newId) + { + throw new NotImplementedException(); + } + + /** + * Iterates through supplied properties and updates the cloned items properties with them + * Complex objects cannot have overrides, they must be fully hydrated with values if they are to be used + * @param overrideProperties new properties to apply + * @param itemClone item to update + */ + protected void UpdateBaseItemPropertiesWithOverrides(Props overrideProperties, TemplateItem itemClone) + { + throw new NotImplementedException(); + } + + /** + * Addd a new item object to the in-memory representation of items.json + * @param newItemId id of the item to add to items.json + * @param itemToAdd Item to add against the new id + */ + protected void AddToItemsDb(string newItemId, TemplateItem itemToAdd) + { + throw new NotImplementedException(); + } + + /** + * Add a handbook price for an item + * @param newItemId id of the item being added + * @param parentId parent id of the item being added + * @param priceRoubles price of the item being added + */ + protected void AddToHandbookDb(string newItemId, string parentId, decimal priceRoubles) + { + throw new NotImplementedException(); + } + + /** + * Iterate through the passed in locale data and add to each locale in turn + * If data is not provided for each langauge eft uses, the first object will be used in its place + * e.g. + * en[0] + * fr[1] + * + * No jp provided, so english will be used as a substitute + * @param localeDetails key is language, value are the new locale details + * @param newItemId id of the item being created + */ + protected void AddToLocaleDbs(Dictionary localeDetails, string newItemId) + { + throw new NotImplementedException(); + } + + /** + * Add a price to the in-memory representation of prices.json, used to inform the flea of an items price on the market + * @param newItemId id of the new item + * @param fleaPriceRoubles Price of the new item + */ + protected void AddToFleaPriceDb(string newItemId, decimal fleaPriceRoubles) + { + throw new NotImplementedException(); + } + + /** + * Add a weapon to the hideout weapon shelf whitelist + * @param newItemId Weapon id to add + */ + protected void AddToWeaponShelf(string newItemId) + { + throw new NotImplementedException(); + } + + /** + * Add a custom weapon to PMCs loadout + * @param weaponTpl Custom weapon tpl to add to PMCs + * @param weaponWeight The weighting for the weapon to be picked vs other weapons + * @param weaponSlot The slot the weapon should be added to (e.g. FirstPrimaryWeapon/SecondPrimaryWeapon/Holster) + */ + public void AddCustomWeaponToPMCs(string weaponTpl, decimal weaponWeight, string weaponSlot) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/Mod/DynamicRouter/DynamicRouterMod.cs b/Core/Services/Mod/DynamicRouter/DynamicRouterMod.cs new file mode 100644 index 00000000..99adad23 --- /dev/null +++ b/Core/Services/Mod/DynamicRouter/DynamicRouterMod.cs @@ -0,0 +1,9 @@ +namespace Core.Services.Mod.DynamicRouter; + +public class DynamicRouterMod +{ + public string GetTopLevelRoute() + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/Mod/DynamicRouter/DynamicRouterModService.cs b/Core/Services/Mod/DynamicRouter/DynamicRouterModService.cs new file mode 100644 index 00000000..1fd3ebb8 --- /dev/null +++ b/Core/Services/Mod/DynamicRouter/DynamicRouterModService.cs @@ -0,0 +1,11 @@ +namespace Core.Services.Mod.DynamicRouter; + +public class DynamicRouterModService +{ + public void RegisterDynamicRouter(string name, List routes, string topLevelRoute) + { + throw new NotImplementedException(); + } + + +} diff --git a/Core/Services/Mod/HttpListener/HttpListenerMod.cs b/Core/Services/Mod/HttpListener/HttpListenerMod.cs new file mode 100644 index 00000000..a6b65c30 --- /dev/null +++ b/Core/Services/Mod/HttpListener/HttpListenerMod.cs @@ -0,0 +1,14 @@ +namespace Core.Services.Mod.HttpListener; + +public class HttpListenerMod +{ + public bool CanHandle(string sessionId, object req) + { + throw new NotImplementedException(); + } + + public async Task Handle(string sessionId, object req, object resp) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/Mod/HttpListener/HttpListenerModService.cs b/Core/Services/Mod/HttpListener/HttpListenerModService.cs new file mode 100644 index 00000000..dc15a5a3 --- /dev/null +++ b/Core/Services/Mod/HttpListener/HttpListenerModService.cs @@ -0,0 +1,9 @@ +namespace Core.Services.Mod.HttpListener; + +public class HttpListenerModService +{ + public void RegisterHttpListener(string name, object canHandleOverride, object handleOverride) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/Mod/OnLoad/OnLoadMod.cs b/Core/Services/Mod/OnLoad/OnLoadMod.cs new file mode 100644 index 00000000..727a01d6 --- /dev/null +++ b/Core/Services/Mod/OnLoad/OnLoadMod.cs @@ -0,0 +1,14 @@ +namespace Core.Services.Mod.OnLoad; + +public class OnLoadMod +{ + public async Task OnLoad() + { + throw new NotImplementedException(); + } + + public string GetRoute() + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/Mod/OnLoad/OnLoadModService.cs b/Core/Services/Mod/OnLoad/OnLoadModService.cs new file mode 100644 index 00000000..fdee76c4 --- /dev/null +++ b/Core/Services/Mod/OnLoad/OnLoadModService.cs @@ -0,0 +1,9 @@ +namespace Core.Services.Mod.OnLoad; + +public class OnLoadModService +{ + public void RegisterOnLoad(string name, object onLoad, object getRoute) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/Mod/OnUpdate/OnUpdateMod.cs b/Core/Services/Mod/OnUpdate/OnUpdateMod.cs new file mode 100644 index 00000000..181536a9 --- /dev/null +++ b/Core/Services/Mod/OnUpdate/OnUpdateMod.cs @@ -0,0 +1,14 @@ +namespace Core.Services.Mod.OnUpdate; + +public class OnUpdateMod +{ + public async Task OnUpdate(double timeSinceLastRun) + { + throw new NotImplementedException(); + } + + public string GetRoute() + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/Mod/OnUpdate/OnUpdateModService.cs b/Core/Services/Mod/OnUpdate/OnUpdateModService.cs new file mode 100644 index 00000000..8b0a6ba9 --- /dev/null +++ b/Core/Services/Mod/OnUpdate/OnUpdateModService.cs @@ -0,0 +1,9 @@ +namespace Core.Services.Mod.OnUpdate; + +public class OnUpdateModService +{ + public void RegisterOnUpdate(string name, object onUpdate, object getRoute) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/Mod/StaticRouter/StaticRouterMod.cs b/Core/Services/Mod/StaticRouter/StaticRouterMod.cs new file mode 100644 index 00000000..c30f1a62 --- /dev/null +++ b/Core/Services/Mod/StaticRouter/StaticRouterMod.cs @@ -0,0 +1,9 @@ +namespace Core.Services.Mod.StaticRouter; + +public class StaticRouterMod // TODO: : StaticRouter +{ + public string GetTopLevelRoute() + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/Mod/StaticRouter/StaticRouterModService.cs b/Core/Services/Mod/StaticRouter/StaticRouterModService.cs new file mode 100644 index 00000000..7584c1da --- /dev/null +++ b/Core/Services/Mod/StaticRouter/StaticRouterModService.cs @@ -0,0 +1,9 @@ +namespace Core.Services.Mod.StaticRouter; + +public class StaticRouterModService +{ + public void RegisterStaticRouter(string name, List routes, string topLevelRoute) // TODO: was List routes + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/ModCompilerService.cs b/Core/Services/ModCompilerService.cs new file mode 100644 index 00000000..ed90b969 --- /dev/null +++ b/Core/Services/ModCompilerService.cs @@ -0,0 +1,50 @@ +namespace Core.Services; + +public class ModCompilerService +{ + /// + /// Convert a mods TS into JS + /// + /// Name of mod + /// Dir path to mod + /// + /// + public async Task CompileMod(string modName, string modPath, List modTypeScriptFiles) + { + throw new NotImplementedException(); + } + + /// + /// Convert a TS file into JS + /// + /// Paths to TS files + /// Compiler options + /// + protected async Task Compile(List fileNames, object options) + { + throw new NotImplementedException(); + } + + /// + /// Do the files at the provided paths exist + /// + /// + /// + protected bool AreFilesReady(List fileNames) + { + throw new NotImplementedException(); + } + + /// + /// Wait the provided number of milliseconds + /// + /// Milliseconds + /// + protected async Task Delay(int ms) + { + throw new NotImplementedException(); + } +} + + +// TODO: this probably isnt needed but AI go brr so i did diff --git a/Core/Services/NotificationService.cs b/Core/Services/NotificationService.cs new file mode 100644 index 00000000..526c78b8 --- /dev/null +++ b/Core/Services/NotificationService.cs @@ -0,0 +1,51 @@ +using Core.Models.Eft.Ws; + +namespace Core.Services; + +public class NotificationService +{ + public Dictionary> GetMessageQueue() + { + throw new NotImplementedException(); + } + + public List GetMessageFromQueue(string sessionId) + { + throw new NotImplementedException(); + } + + public void UpdateMessageOnQueue(string sessionId, List value) + { + throw new NotImplementedException(); + } + + public bool Has(string sessionID) + { + throw new NotImplementedException(); + } + + /// + /// Pop first message from queue. + /// + public object Pop(string sessionID) + { + throw new NotImplementedException(); + } + + /// + /// Add message to queue + /// + public void Add(string sessionID, WsNotificationEvent message) + { + throw new NotImplementedException(); + } + + /// + /// Get message queue for session + /// + /// + public List Get(string sessionID) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/OpenZoneService.cs b/Core/Services/OpenZoneService.cs new file mode 100644 index 00000000..94fbd849 --- /dev/null +++ b/Core/Services/OpenZoneService.cs @@ -0,0 +1,22 @@ +namespace Core.Services; + +public class OpenZoneService +{ + /// + /// Add open zone to specified map + /// + /// map location (e.g. factory4_day) + /// zone to add + public void AddZoneToMap(string locationId, string zoneToAdd) + { + throw new NotImplementedException(); + } + + /// + /// Add open zones to all maps found in config/location.json to db + /// + public void ApplyZoneChangesToAllMaps() + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/PaymentService.cs b/Core/Services/PaymentService.cs new file mode 100644 index 00000000..6d3ab622 --- /dev/null +++ b/Core/Services/PaymentService.cs @@ -0,0 +1,66 @@ +using Core.Models.Eft.Common; +using Core.Models.Eft.Common.Tables; +using Core.Models.Eft.ItemEvent; + +namespace Core.Services; + +public class PaymentService +{ + /** + * Remove currency from player stash/inventory and update client object with changes + * @param pmcData Player profile to find and remove currency from + * @param currencyTpl Type of currency to pay + * @param amountToPay money value to pay + * @param sessionID Session id + * @param output output object to send to client + */ + public void AddPaymentToOutput( + PmcData pmcData, + string currencyTpl, + decimal amountToPay, + string sessionID, + ItemEventRouterResponse output + ) + { + throw new NotImplementedException(); + } + + /** + * TODO - ensure money in containers inside secure container are LAST + * Get all money stacks in inventory and prioritise items in stash + * @param pmcData Player profile + * @param currencyTpl + * @param playerStashId Players stash id + * @returns Sorting money items + */ + protected List GetSortedMoneyItemsInInventory(PmcData pmcData, string currencyTpl, string playerStashId) + { + throw new NotImplementedException(); + } + + /** + * Prioritise player stash first over player inventory + * Post-raid healing would often take money out of the players pockets/secure container + * @param a First money stack item + * @param b Second money stack item + * @param inventoryItems players inventory items + * @param playerStashId Players stash id + * @returns sort order + */ + protected int PrioritiseStashSort(Item a, Item b, List inventoryItems, string playerStashId) + { + throw new NotImplementedException(); + } + + /** + * Recursively check items parents to see if it is inside the players inventory, not stash + * @param itemId item id to check + * @param inventoryItems player inventory + * @param playerStashId Players stash id + * @returns true if its in inventory + */ + protected bool IsInStash(string itemId, List inventoryItems, string playerStashId) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/PlayerService.cs b/Core/Services/PlayerService.cs new file mode 100644 index 00000000..f1ae9f2d --- /dev/null +++ b/Core/Services/PlayerService.cs @@ -0,0 +1,11 @@ +using Core.Models.Eft.Common; + +namespace Core.Services; + +public class PlayerService +{ + public int CalculateLevel(PmcData pmcData) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/PmcChatResponseService.cs b/Core/Services/PmcChatResponseService.cs new file mode 100644 index 00000000..a6571bd4 --- /dev/null +++ b/Core/Services/PmcChatResponseService.cs @@ -0,0 +1,133 @@ +using Core.Models.Eft.Common; +using Core.Models.Eft.Common.Tables; +using Core.Models.Eft.Profile; + +namespace Core.Services; + +public class PmcChatResponseService +{ + /** + * For each PMC victim of the player, have a chance to send a message to the player, can be positive or negative + * @param sessionId Session id + * @param pmcVictims List of bots killed by player + * @param pmcData Player profile + */ + public void SendVictimResponse(string sessionId, List pmcVictims, PmcData pmcData) + { + throw new System.NotImplementedException(); + } + + /** + * Not fully implemented yet, needs method of acquiring killers details after raid + * @param sessionId Session id + * @param pmcData Players profile + * @param killer The bot who killed the player + */ + public void SendKillerResponse(string sessionId, PmcData pmcData, Aggressor killer) + { + throw new System.NotImplementedException(); + } + + /** + * Choose a localised message to send the player (different if sender was killed or killed player) + * @param isVictim Is the message coming from a bot killed by the player + * @param pmcData Player profile + * @param victimData OPTIMAL - details of the pmc killed + * @returns Message from PMC to player + */ + protected string? ChooseMessage(bool isVictim, PmcData pmcData, Victim? victimData = null) + { + throw new System.NotImplementedException(); + } + + /** + * use map key to get a localised location name + * e.g. factory4_day becomes "Factory" + * @param locationKey location key to localise + * @returns Localised location name + */ + protected string GetLocationName(string locationKey) + { + throw new System.NotImplementedException(); + } + + /** + * Should capitalisation be stripped from the message response before sending + * @param isVictim Was responder a victim of player + * @returns true = should be stripped + */ + protected bool StripCapitalisation(bool isVictim) + { + throw new System.NotImplementedException(); + } + + /** + * Should capitalisation be stripped from the message response before sending + * @param isVictim Was responder a victim of player + * @returns true = should be stripped + */ + protected bool AllCaps(bool isVictim) + { + throw new System.NotImplementedException(); + } + + /** + * Should a suffix be appended to the end of the message being sent to player + * @param isVictim Was responder a victim of player + * @returns true = should be stripped + */ + protected bool AppendSuffixToMessageEnd(bool isVictim) + { + throw new System.NotImplementedException(); + } + + /** + * Choose a type of response based on the weightings in pmc response config + * @param isVictim Was responder killed by player + * @returns Response type (positive/negative) + */ + protected string ChooseResponseType(bool isVictim = true) + { + throw new System.NotImplementedException(); + } + + /** + * Get locale keys related to the type of response to send (victim/killer) + * @param keyType Positive/negative + * @param isVictim Was responder killed by player + * @returns + */ + protected List GetResponseLocaleKeys(string keyType, bool isVictim = true) + { + throw new System.NotImplementedException(); + } + + /** + * Get all locale keys that start with `pmcresponse-suffix` + * @returns list of keys + */ + protected List GetResponseSuffixLocaleKeys() + { + throw new System.NotImplementedException(); + } + + /** + * Randomly draw a victim of the list and return their details + * @param pmcVictims Possible victims to choose from + * @returns IUserDialogInfo + */ + protected UserDialogInfo ChooseRandomVictim(List pmcVictims) + { + throw new System.NotImplementedException(); + } + + /** + * Convert a victim object into a IUserDialogInfo object + * @param pmcVictim victim to convert + * @returns IUserDialogInfo + */ + protected UserDialogInfo GetVictimDetails(Victim pmcVictim) + { + throw new System.NotImplementedException(); + } +} diff --git a/Core/Services/PostDbLoadService.cs b/Core/Services/PostDbLoadService.cs new file mode 100644 index 00000000..eaf885c4 --- /dev/null +++ b/Core/Services/PostDbLoadService.cs @@ -0,0 +1,103 @@ +namespace Core.Services; + +public class PostDbLoadService +{ + public void PerformPostDbLoadActions() + { + throw new NotImplementedException(); + } + + protected void AdjustMinReserveRaiderSpawnChance() + { + throw new NotImplementedException(); + } + + protected void AddCustomLooseLootPositions() + { + throw new NotImplementedException(); + } + +// BSG have two values for shotgun dispersion, we make sure both have the same value + protected void FixShotgunDispersions() + { + throw new NotImplementedException(); + } + +// Apply custom limits on bot types as defined in configs/location.json/botTypeLimits + protected void AdjustMapBotLimits() + { + throw new NotImplementedException(); + } + + protected void AdjustLooseLootSpawnProbabilities() + { + throw new NotImplementedException(); + } + + protected void AdjustLocationBotValues() + { + throw new NotImplementedException(); + } + +// Make Rogues spawn later to allow for scavs to spawn first instead of rogues filling up all spawn positions + protected void FixRoguesSpawningInstantlyOnLighthouse() + { + throw new NotImplementedException(); + } + +// Find and split waves with large numbers of bots into smaller waves - BSG appears to reduce the size of these +// waves to one bot when they're waiting to spawn for too long + protected void SplitBotWavesIntoSingleWaves() + { + throw new NotImplementedException(); + } + +// Make non-trigger-spawned raiders spawn earlier + always + protected void AdjustLabsRaiderSpawnRate() + { + throw new NotImplementedException(); + } + + protected void AdjustHideoutCraftTimes(int overrideSeconds) + { + throw new NotImplementedException(); + } + +// Adjust all hideout craft times to be no higher than the override + protected void AdjustHideoutBuildTimes(int overrideSeconds) + { + throw new NotImplementedException(); + } + +// Blank out the "test" mail message from prapor + protected void RemovePraporTestMessage() + { + throw new NotImplementedException(); + } + +// Check for any missing assorts inside each traders assort.json data, checking against traders questassort.json + protected void ValidateQuestAssortUnlocksExist() + { + throw new NotImplementedException(); + } + + protected void SetAllDbItemsAsSellableOnFlea() + { + throw new NotImplementedException(); + } + + protected void AddMissingTraderBuyRestrictionMaxValue() + { + throw new NotImplementedException(); + } + + protected void ApplyFleaPriceOverrides() + { + throw new NotImplementedException(); + } + + protected void AddCustomItemPresetsToGlobals() + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/ProfileActivityService.cs b/Core/Services/ProfileActivityService.cs new file mode 100644 index 00000000..163ef857 --- /dev/null +++ b/Core/Services/ProfileActivityService.cs @@ -0,0 +1,34 @@ +namespace Core.Services; + +public class ProfileActivityService +{ + /** + * Was the requested profile active in the last requested minutes + * @param sessionId Profile to check + * @param minutes Minutes to check for activity in + * @returns True when profile was active within past x minutes + */ + public bool ActiveWithinLastMinutes(string sessionId, int minutes) + { + throw new NotImplementedException(); + } + + /** + * Get a list of profile ids that were active in the last x minutes + * @param minutes How many minutes from now to search for profiles + * @returns List of profile ids + */ + public List GetActiveProfileIdsWithinMinutes(int minutes) + { + throw new NotImplementedException(); + } + + /** + * Update the timestamp a profile was last observed active + * @param sessionId Profile to update + */ + public void SetActivityTimestamp(string sessionId) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/ProfileFixerService.cs b/Core/Services/ProfileFixerService.cs new file mode 100644 index 00000000..5fa0ead3 --- /dev/null +++ b/Core/Services/ProfileFixerService.cs @@ -0,0 +1,206 @@ +using Core.Models.Eft.Common; +using Core.Models.Eft.Common.Tables; +using Core.Models.Eft.Hideout; +using Core.Models.Eft.Profile; +using Core.Models.Enums; + +namespace Core.Services; + +public class ProfileFixerService +{ + /// + /// Find issues in the pmc profile data that may cause issues and fix them + /// + /// profile to check and fix + public void CheckForAndFixPmcProfileIssues(PmcData pmcProfile) + { + throw new NotImplementedException(); + } + + /// + /// Resolve any dialogue attachments that were accidentally created using the player's equipment ID as + /// the stash root object ID + /// + /// + public void CheckForAndFixDialogueAttachments(SptProfile fullProfile) + { + throw new NotImplementedException(); + } + + /// + /// Find issues in the scav profile data that may cause issues + /// + /// profile to check and fix + public void CheckForAndFixScavProfileIssues(PmcData scavProfile) + { + throw new NotImplementedException(); + } + + /// + /// Attempt to fix common item issues that corrupt profiles + /// + /// Profile to check items of + public void FixProfileBreakingInventoryItemIssues(PmcData pmcProfile) + { + throw new NotImplementedException(); + } + + /// + /// TODO - make this non-public - currently used by RepeatableQuestController + /// Remove unused condition counters + /// + /// profile to remove old counters from + public void RemoveDanglingConditionCounters(PmcData pmcProfile) + { + throw new NotImplementedException(); + } + + /// + /// Repeatable quests leave behind TaskConditionCounter objects that make the profile bloat with time, remove them + /// + /// Player profile to check + protected void RemoveDanglingTaskConditionCounters(PmcData pmcProfile) + { + throw new NotImplementedException(); + } + + protected List GetActiveRepeatableQuests(List repeatableQuests) + { + throw new NotImplementedException(); + } + + /// + /// After removing mods that add quests, the quest panel will break without removing these + /// + /// Profile to remove dead quests from + protected void RemoveOrphanedQuests(PmcData pmcProfile) + { + throw new NotImplementedException(); + } + + /// + /// Verify that all quest production unlocks have been applied to the PMC Profile + /// + /// The profile to validate quest productions for + protected void VerifyQuestProductionUnlocks(PmcData pmcProfile) + { + throw new NotImplementedException(); + } + + /// + /// Validate that the given profile has the given quest reward production scheme unlocked, and add it if not + /// + /// Profile to check + /// The quest reward to validate + /// The quest the reward belongs to + protected void VerifyQuestProductionUnlock(PmcData pmcProfile, QuestReward productionUnlockReward, Quest questDetails) + { + throw new NotImplementedException(); + } + + /// + /// Initial release of SPT 3.10 used an incorrect favorites structure, reformat + /// the structure to the correct MongoID array structure + /// + /// + protected void FixFavorites(PmcData pmcProfile) + { + throw new NotImplementedException(); + } + + /// + /// If the profile has elite Hideout Managment skill, add the additional slots from globals + /// NOTE: This seems redundant, but we will leave it here just in case. + /// + /// profile to add slots to + protected void AddHideoutEliteSlots(PmcData pmcProfile) + { + throw new NotImplementedException(); + } + + /// + /// add in objects equal to the number of slots + /// + /// area to check + /// area to update + /// profile to update + protected void AddEmptyObjectsToHideoutAreaSlots(HideoutAreas areaType, int emptyItemCount, PmcData pmcProfile) + { + throw new NotImplementedException(); + } + + protected IList AddObjectsToList(int count, List slots) + { + throw new NotImplementedException(); + } + + /** + * Check for and cap profile skills at 5100. + * @param pmcProfile profile to check and fix + */ + protected void CheckForSkillsOverMaxLevel(PmcData pmcProfile) + { + throw new NotImplementedException(); + } + + /** + * Checks profile inventory for items that do not exist inside the items db + * @param sessionId Session id + * @param pmcProfile Profile to check inventory of + */ + public void CheckForOrphanedModdedItems(string sessionId, SptProfile fullProfile) + { + throw new NotImplementedException(); + } + + /** + * @param buildType The type of build, used for logging only + * @param build The build to check for invalid items + * @param itemsDb The items database to use for item lookup + * @returns True if the build should be removed from the build list, false otherwise + */ + protected bool ShouldRemoveWeaponEquipmentBuild( + string buildType, + WeaponBuild equipmentBuild, + Dictionary itemsDb) + { + throw new NotImplementedException(); + } + + /** + * @param magazineBuild The magazine build to check for validity + * @param itemsDb The items database to use for item lookup + * @returns True if the build should be removed from the build list, false otherwise + */ + protected bool ShouldRemoveMagazineBuild( + MagazineBuild magazineBuild, + Dictionary itemsDb) + { + throw new NotImplementedException(); + } + + /** + * REQUIRED for dev profiles + * Iterate over players hideout areas and find what's built, look for missing bonuses those areas give and add them if missing + * @param pmcProfile Profile to update + */ + public void AddMissingHideoutBonusesToProfile(PmcData pmcProfile) + { + throw new NotImplementedException(); + } + + /** + * @param profileBonuses bonuses from profile + * @param bonus bonus to find + * @returns matching bonus + */ + protected Bonus GetBonusFromProfile(List profileBonuses, StageBonus bonus) + { + throw new NotImplementedException(); + } + + public void CheckForAndRemoveInvalidTraders(SptProfile fullProfile) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/RagfairCategoriesService.cs b/Core/Services/RagfairCategoriesService.cs new file mode 100644 index 00000000..87c25832 --- /dev/null +++ b/Core/Services/RagfairCategoriesService.cs @@ -0,0 +1,21 @@ +using Core.Models.Eft.Ragfair; + +namespace Core.Services; + +public class RagfairCategoriesService +{ + /// + /// Get a dictionary of each item the play can see in their flea menu, filtered by what is available for them to buy + /// + /// All offers in flea + /// Search criteria requested + /// Can player see full flea yet (level 15 by default) + /// KVP of item tpls + count of offers + public Dictionary GetCategoriesFromOffers( + List offers, + SearchRequestData searchRequestData, + bool fleaUnlocked) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/RagfairLinkedItemService.cs b/Core/Services/RagfairLinkedItemService.cs new file mode 100644 index 00000000..a5f01e56 --- /dev/null +++ b/Core/Services/RagfairLinkedItemService.cs @@ -0,0 +1,52 @@ +using Core.Models.Eft.Common.Tables; + +namespace Core.Services; + +public class RagfairLinkedItemService +{ + public HashSet GetLinkedItems(string linkedSearchId) + { + throw new NotImplementedException(); + } + + /// + /// Use ragfair linked item service to get an array of items that can fit on or in designated itemtpl + /// + /// Item to get sub-items for + /// TemplateItem array + public List GetLinkedDbItems(string itemTpl) + { + throw new NotImplementedException(); + } + + /// + /// Create Dictionary of every item and the items associated with it + /// + protected void BuildLinkedItemTable() + { + throw new NotImplementedException(); + } + + /// + /// Add ammo to revolvers linked item dictionary + /// + /// Revolvers cylinder + /// + protected void AddRevolverCylinderAmmoToLinkedItems( + TemplateItem cylinder, + Action> applyLinkedItems) + { + throw new NotImplementedException(); + } + + /// + /// Scans a given slot type for filters and returns them as a List + /// + /// + /// + /// List of ids + protected List GetFilters(TemplateItem item, string slot) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/RagfairOfferService.cs b/Core/Services/RagfairOfferService.cs new file mode 100644 index 00000000..98a8b835 --- /dev/null +++ b/Core/Services/RagfairOfferService.cs @@ -0,0 +1,142 @@ +using Core.Models.Eft.Common.Tables; +using Core.Models.Eft.Ragfair; + +namespace Core.Services; + +public class RagfairOfferService +{ + /// + /// Get all offers + /// + /// List of RagfairOffer + public List GetOffers() + { + throw new NotImplementedException(); + } + + public RagfairOffer GetOfferByOfferId(string offerId) + { + throw new NotImplementedException(); + } + + public List GetOffersOfType(string templateId) + { + throw new NotImplementedException(); + } + + public void AddOffer(RagfairOffer offer) + { + throw new NotImplementedException(); + } + + public void AddOfferToExpired(RagfairOffer staleOffer) + { + throw new NotImplementedException(); + } + + /// + /// Get total count of current expired offers + /// + /// Number of expired offers + public int GetExpiredOfferCount() + { + throw new NotImplementedException(); + } + + /// + /// Get a list of lists of expired offer items + children + /// + /// Expired offer assorts + public List> GetExpiredOfferAssorts() + { + throw new NotImplementedException(); + } + + /// + /// Clear out internal expiredOffers dictionary of all items + /// + public void ResetExpiredOffers() + { + throw new NotImplementedException(); + } + + /// + /// Does the offer exist on the ragfair + /// + /// offer id to check for + /// offer exists - true + public bool DoesOfferExist(string offerId) + { + throw new NotImplementedException(); + } + + /// + /// Remove an offer from ragfair by offer id + /// + /// Offer id to remove + public void RemoveOfferById(string offerId) + { + throw new NotImplementedException(); + } + + /// + /// Reduce size of an offer stack by specified amount + /// + /// Offer to adjust stack size of + /// How much to deduct from offers stack size + public void RemoveOfferStack(string offerId, int amount) + { + throw new NotImplementedException(); + } + + public void RemoveAllOffersByTrader(string traderId) + { + throw new NotImplementedException(); + } + + /// + /// Do the trader offers on flea need to be refreshed + /// + /// Trader to check + /// true if they do + public bool TraderOffersNeedRefreshing(string traderID) + { + throw new NotImplementedException(); + } + + public void AddPlayerOffers() + { + throw new NotImplementedException(); + } + + public void ExpireStaleOffers() + { + throw new NotImplementedException(); + } + + /// + /// Remove stale offer from flea + /// + /// Stale offer to process + protected void ProcessStaleOffer(RagfairOffer staleOffer) + { + throw new NotImplementedException(); + } + + protected void ReturnPlayerOffer(RagfairOffer playerOffer) + { + throw new NotImplementedException(); + } + + /// + /// Flea offer items are stacked up often beyond the StackMaxSize limit + /// Unstack the items into a list of root items and their children + /// Will create new items equal to the + /// + /// Offer items to unstack + /// Unstacked list of items + protected List UnstackOfferItems(List items) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/RagfairPriceService.cs b/Core/Services/RagfairPriceService.cs new file mode 100644 index 00000000..b4a265ae --- /dev/null +++ b/Core/Services/RagfairPriceService.cs @@ -0,0 +1,222 @@ +using Core.Models.Common; +using Core.Models.Eft.Common.Tables; +using Core.Models.Spt.Config; + +namespace Core.Services; + +public class RagfairPriceService +{ + /// + /// Generate static (handbook) and dynamic (prices.json) flea prices, store inside class as dictionaries + /// + public async Task OnLoadAsync() + { + throw new NotImplementedException(); + } + + public string GetRoute() + { + throw new NotImplementedException(); + } + + /// + /// Iterate over all items of type "Item" in db and get template price, store in cache + /// + public void RefreshStaticPrices() + { + throw new NotImplementedException(); + } + + /// + /// Copy the prices.json data into our dynamic price dictionary + /// + public void RefreshDynamicPrices() + { + throw new NotImplementedException(); + } + + /// + /// Get the dynamic price for an item. If value doesn't exist, use static (handbook) value. + /// if no static value, return 1 + /// + /// Item tpl id to get price for + /// price in roubles + public double GetFleaPriceForItem(string tplId) + { + throw new NotImplementedException(); + } + + /// + /// Get the flea price for an offers items + children + /// + /// offer item + children to process + /// Rouble price + public double GetFleaPriceForOfferItems(List offerItems) + { + throw new NotImplementedException(); + } + + /// + /// get the dynamic (flea) price for an item + /// + /// item template id to look up + /// price in roubles + public double GetDynamicPriceForItem(string itemTpl) + { + throw new NotImplementedException(); + } + + /// + /// Grab the static (handbook) for an item by its tplId + /// + /// item template id to look up + /// price in roubles + public double GetStaticPriceForItem(string itemTpl) + { + throw new NotImplementedException(); + } + + /// + /// Get prices for all items on flea, prioritize handbook prices first, use prices from prices.json if missing + /// This will refresh the caches prior to building the output + /// + /// Dictionary of item tpls and rouble cost + public Dictionary GetAllFleaPrices() + { + throw new NotImplementedException(); + } + + public Dictionary GetAllStaticPrices() + { + throw new NotImplementedException(); + } + + /// + /// Get the percentage difference between two values + /// + /// numerical value a + /// numerical value b + /// different in percent + protected double GetPriceDifference(double a, double b) + { + throw new NotImplementedException(); + } + + /// + /// Get the rouble price for an assorts barter scheme + /// + /// + /// Rouble price + public double GetBarterPrice(List barterScheme) + { + throw new NotImplementedException(); + } + + /// + /// Generate a currency cost for an item and its mods + /// + /// Item with mods to get price for + /// Currency price desired in + /// Price is for a pack type offer + /// cost of item in desired currency + public double GetDynamicOfferPriceForOffer(List offerItems, string desiredCurrency, bool isPackOffer) + { + throw new NotImplementedException(); + } + + /// + /// + /// items tpl value + /// Currency to return result in + /// Item object (used for weapon presets) + /// + /// + /// + public double GetDynamicItemPrice(string itemTemplateId, string desiredCurrency, Item item = null, List offerItems = null, bool? isPackOffer = null) + { + throw new NotImplementedException(); + } + + /// + /// using data from config, adjust an items price to be relative to its handbook price + /// + /// Prices of items in handbook + /// Change object from config + /// Item being adjusted + /// Current price of item + /// Adjusted price of item + protected decimal AdjustUnreasonablePrice( + List handbookPrices, + UnreasonableModPrices unreasonableItemChange, + string itemTpl, + decimal price) + { + throw new NotImplementedException(); + } + + /// + /// Get different min/max price multipliers for different offer types (preset/pack/default) + /// + /// Offer is a preset + /// Offer is a pack + /// MinMax values + protected MinMax GetOfferTypeRangeValues(bool isPreset, bool isPack) + { + throw new NotImplementedException(); + } + + /// + /// Check to see if an items price is below its handbook price and adjust according to values set to config/ragfair.json + /// + /// price of item + /// item template Id being checked + /// adjusted price value in roubles + protected decimal AdjustPriceIfBelowHandbook(decimal itemPrice, string itemTpl) + { + throw new NotImplementedException(); + } + + /// + /// Multiply the price by a randomised curve where n = 2, shift = 2 + /// + /// price to alter + /// min and max to adjust price by + /// multiplied price + protected decimal RandomiseOfferPrice(decimal existingPrice, MinMax rangeValues) + { + throw new NotImplementedException(); + } + + /// + /// Calculate the cost of a weapon preset by adding together the price of its mods + base price of default weapon preset + /// + /// base weapon + /// weapon plus mods + /// price of existing base weapon + /// price of weapon in roubles + protected decimal GetWeaponPresetPrice(Item weaponRootItem, List weaponWithChildren, decimal existingPrice) + { + throw new NotImplementedException(); + } + + /// + /// Get the highest price for an item that is stored in handbook or trader assorts + /// + /// Item to get highest price of + /// rouble cost + protected decimal GetHighestHandbookOrTraderPriceAsRouble(string itemTpl) + { + throw new NotImplementedException(); + } + + /// + /// Attempt to get the default preset for a weapon, failing that get the first preset in the array + /// (assumes default = has encyclopedia entry) + /// + /// weapon presets to choose from + /// Default preset object + protected object GetWeaponPreset(Item weapon) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/RagfairRequiredItemsService.cs b/Core/Services/RagfairRequiredItemsService.cs new file mode 100644 index 00000000..c25921fc --- /dev/null +++ b/Core/Services/RagfairRequiredItemsService.cs @@ -0,0 +1,16 @@ +using Core.Models.Eft.Ragfair; + +namespace Core.Services; + +public class RagfairRequiredItemsService +{ + public List GetRequiredItemsById(string searchId) + { + throw new NotImplementedException(); + } + + public void BuildRequiredItemTable() + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/RagfairTaxService.cs b/Core/Services/RagfairTaxService.cs new file mode 100644 index 00000000..9c54e7db --- /dev/null +++ b/Core/Services/RagfairTaxService.cs @@ -0,0 +1,51 @@ +namespace Core.Services; + +public class RagfairTaxService +{ + public void StoreClientOfferTaxValue(string sessionId, Dictionary offer) + { + throw new NotImplementedException(); + } + + public void ClearStoredOfferTaxById(string offerIdToRemove) + { + throw new NotImplementedException(); + } + + public Dictionary GetStoredClientOfferTaxValueById(string offerIdToGet) + { + throw new NotImplementedException(); + } + + /** + // This method, along with CalculateItemWorth, is trying to mirror the client-side code found in the method "CalculateTaxPrice". + // It's structured to resemble the client-side code as closely as possible - avoid making any big structure changes if it's not necessary. + * @param item Item being sold on flea + * @param pmcData player profile + * @param requirementsValue + * @param offerItemCount Number of offers being created + * @param sellInOnePiece + * @returns Tax in roubles + */ + public double CalculateTax( + Dictionary item, + Dictionary pmcData, + double requirementsValue, + int offerItemCount, + bool sellInOnePiece) + { + throw new NotImplementedException(); + } + + // This method is trying to replicate the item worth calculation method found in the client code. + // Any inefficiencies or style issues are intentional and should not be fixed, to preserve the client-side code mirroring. + protected double CalculateItemWorth( + Dictionary item, + Dictionary itemTemplate, + int itemCount, + Dictionary pmcData, + bool isRootItem = true) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/RaidTimeAdjustmentService.cs b/Core/Services/RaidTimeAdjustmentService.cs new file mode 100644 index 00000000..70ca8f5a --- /dev/null +++ b/Core/Services/RaidTimeAdjustmentService.cs @@ -0,0 +1,72 @@ +using Core.Models.Eft.Common; +using Core.Models.Eft.Game; +using Core.Models.Spt.Config; +using Core.Models.Spt.Location; + +namespace Core.Services; + +public class RaidTimeAdjustmentService +{ + /// + /// Make alterations to the base map data passed in + /// Loot multipliers/waves/wave start times + /// + /// Changes to process on map + /// Map to adjust + public void MakeAdjustmentsToMap(RaidChanges raidAdjustments, LocationBase mapBase) + { + throw new NotImplementedException(); + } + + /// + /// Adjust the loot multiplier values passed in to be a % of their original value + /// + /// Multipliers to adjust + /// Percent to change values to + protected void AdjustLootMultipliers(LootMultiplier mapLootMultipliers, float loosePercent) + { + throw new NotImplementedException(); + } + + /// + /// Adjust bot waves to act as if player spawned later + /// + /// Map to adjust + /// Map adjustments + protected void AdjustWaves(LocationBase mapBase, RaidChanges raidAdjustments) + { + throw new NotImplementedException(); + } + + /// + /// Create a randomised adjustment to the raid based on map data in location.json + /// + /// Session id + /// Raid adjustment request + /// Response to send to client + public GetRaidTimeResponse GetRaidAdjustments(string sessionId, GetRaidTimeRequest request) + { + throw new NotImplementedException(); + } + + /// + /// Get raid start time settings for specific map + /// + /// Map Location e.g. bigmap + /// ScavRaidTimeLocationSettings + protected ScavRaidTimeLocationSettings GetMapSettings(string location) + { + throw new NotImplementedException(); + } + + /// + /// Adjust exit times to handle scavs entering raids part-way through + /// + /// Map base file player is on + /// How long raid is in minutes + /// List of exit changes to send to client + protected List GetExitAdjustments(LocationBase mapBase, int newRaidTimeMinutes) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/RaidWeatherService.cs b/Core/Services/RaidWeatherService.cs new file mode 100644 index 00000000..2bdc5718 --- /dev/null +++ b/Core/Services/RaidWeatherService.cs @@ -0,0 +1,48 @@ +using Core.Models.Eft.Weather; +using Core.Models.Enums; + +namespace Core.Services; + +public class RaidWeatherService +{ + /// + /// Generate 24 hours of weather data starting from midnight today + /// + public void GenerateWeather(Season currentSeason) + { + throw new NotImplementedException(); + } + + /// + /// Get a time period to increment by, e.g 15 or 30 minutes as milliseconds + /// + /// milliseconds + protected long GetWeightedWeatherTimePeriodMs() + { + throw new NotImplementedException(); + } + + /// + /// Find the first matching weather object that applies to the current time + /// + public Weather GetCurrentWeather() + { + throw new NotImplementedException(); + } + + /// + /// Find the first matching weather object that applies to the current time + all following weather data generated + /// + public List GetUpcomingWeather() + { + throw new NotImplementedException(); + } + + /// + /// Ensure future weather data exists + /// + protected void ValidateWeatherDataExists(Season currentSeason) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/RepairService.cs b/Core/Services/RepairService.cs new file mode 100644 index 00000000..eaa911ef --- /dev/null +++ b/Core/Services/RepairService.cs @@ -0,0 +1,212 @@ +using System.Text.Json.Serialization; +using Core.Models.Eft.Common; +using Core.Models.Eft.Common.Tables; +using Core.Models.Eft.ItemEvent; +using Core.Models.Eft.Repair; +using Core.Models.Enums; + +namespace Core.Services; + +public class RepairService +{ + /// + /// Use trader to repair an items durability + /// + /// Session id + /// Profile to find item to repair in + /// Details of the item to repair + /// Trader being used to repair item + /// RepairDetails object + public RepairDetails RepairItemByTrader( + string sessionID, + PmcData pmcData, + RepairItem repairItemDetails, + string traderId + ) + { + throw new NotImplementedException(); + } + + /// + /// + /// Session id + /// Profile to take money from + /// Repaired item id + /// Cost to repair item in roubles + /// Id of the trader who repaired the item / who is paid + /// + public void PayForRepair( + string sessionID, + PmcData pmcData, + string repairedItemId, + decimal repairCost, + string traderId, + ItemEventRouterResponse output + ) + { + throw new NotImplementedException(); + } + + /// + /// Add skill points to profile after repairing an item + /// + /// Session id + /// Details of item repaired, cost/item + /// Profile to add points to + public void AddRepairSkillPoints(string sessionId, RepairDetails repairDetails, PmcData pmcData) + { + throw new NotImplementedException(); + } + + protected decimal GetIntellectGainedFromRepair(RepairDetails repairDetails) + { + throw new NotImplementedException(); + } + + /// + /// Return an approximation of the amount of skill points live would return for the given repairDetails + /// + /// The repair details to calculate skill points for + /// The number of skill points to reward the user + protected decimal GetWeaponRepairSkillPoints(RepairDetails repairDetails) + { + throw new NotImplementedException(); + } + + /// + /// + /// Session id + /// Profile to update repaired item in + /// List of Repair kits to use + /// Item id to repair + /// ItemEventRouterResponse + /// Details of repair, item/price + public RepairDetails RepairItemByKit( + string sessionId, + PmcData pmcData, + List repairKits, + string itemToRepairId, + ItemEventRouterResponse output + ) + { + throw new NotImplementedException(); + } + + /// + /// Calculate value repairkit points need to be divided by to get the durability points to be added to an item + /// + /// Item to repair details + /// Is the item being repaired armor + /// Player profile + /// Number to divide kit points by + protected decimal GetKitDivisor(TemplateItem itemToRepairDetails, bool isArmor, PmcData pmcData) + { + throw new NotImplementedException(); + } + + /// + /// Get the bonus multiplier for a skill from a player profile + /// + /// Bonus to get multiplier of + /// Player profile to look in for skill + /// Multiplier value + protected decimal GetBonusMultiplierValue(BonusType skillBonus, PmcData pmcData) + { + throw new NotImplementedException(); + } + + /// + /// Should a repair kit apply total durability loss on repair + /// + /// Player profile + /// Value from repair config + /// True if loss should be applied + protected bool ShouldRepairKitApplyDurabilityLoss(PmcData pmcData, bool applyRandomizeDurabilityLoss) + { + throw new NotImplementedException(); + } + + /// + /// Update repair kits Resource object if it doesn't exist + /// + /// Repair kit details from db + /// Repair kit to update + protected void AddMaxResourceToKitIfMissing(TemplateItem repairKitDetails, Item repairKitInInventory) + { + throw new NotImplementedException(); + } + + /// + /// Chance to apply buff to an item (Armor/weapon) if repaired by armor kit + /// + /// Repair details of item + /// Player profile + public void AddBuffToItem(RepairDetails repairDetails, PmcData pmcData) + { + throw new NotImplementedException(); + } + + /// + /// Add random buff to item + /// + /// weapon/armor config + /// Details for item to repair + public void AddBuff(BonusSettings itemConfig, Item item) + { + throw new NotImplementedException(); + } + + /// + /// Check if item should be buffed by checking the item type and relevant player skill level + /// + /// Item that was repaired + /// tpl of item to be buffed + /// Player profile + /// True if item should have buff applied + protected bool ShouldBuffItem(RepairDetails repairDetails, PmcData pmcData) + { + throw new NotImplementedException(); + } + + /// + /// Based on item, what underlying skill does this item use for buff settings + /// + /// Item to check for skill + /// Skill name + protected SkillTypes? GetItemSkillType(TemplateItem itemTemplate) + { + throw new NotImplementedException(); + } + + /// + /// Ensure multiplier is between 1 and 0.01 + /// + /// Max durability percent + /// current durability percent + /// durability multiplier value + protected double GetDurabilityMultiplier(double receiveDurabilityMaxPercent, double receiveDurabilityPercent) + { + throw new NotImplementedException(); + } +} + +public class RepairDetails +{ + [JsonPropertyName("repairCost")] + public double? RepairCost { get; set; } + + [JsonPropertyName("repairPoints")] + public double? RepairPoints { get; set; } + + [JsonPropertyName("repairedItem")] + public Item? RepairedItem { get; set; } + + [JsonPropertyName("repairedItemIsArmor")] + public bool? RepairedItemIsArmor { get; set; } + + [JsonPropertyName("repairAmount")] + public double? RepairAmount { get; set; } + + [JsonPropertyName("repairedByKit")] + public bool? RepairedByKit { get; set; } +} diff --git a/Core/Services/SeasonalEventService.cs b/Core/Services/SeasonalEventService.cs new file mode 100644 index 00000000..3212d720 --- /dev/null +++ b/Core/Services/SeasonalEventService.cs @@ -0,0 +1,402 @@ +using Core.Models.Eft.Common; +using Core.Models.Eft.Common.Tables; +using Core.Models.Enums; +using Core.Models.Spt.Config; + +namespace Core.Services; + +public class SeasonalEventService +{ + /// + /// Get an array of christmas items found in bots inventories as loot + /// + /// array + public string[] GetChristmasEventItems() + { + throw new NotImplementedException(); + } + + /// + /// Get an array of halloween items found in bots inventories as loot + /// + /// array + public string[] GetHalloweenEventItems() + { + throw new NotImplementedException(); + } + + public bool ItemIsChristmasRelated(string itemTpl) + { + throw new NotImplementedException(); + } + + public bool ItemIsHalloweenRelated(string itemTpl) + { + throw new NotImplementedException(); + } + + /// + /// Check if item id exists in christmas or halloween event arrays + /// + /// item tpl to check for + /// + public bool ItemIsSeasonalRelated(string itemTpl) + { + throw new NotImplementedException(); + } + + /// + /// Get active seasonal events + /// + /// Array of active events + public List GetActiveEvents() + { + throw new NotImplementedException(); + } + + /// + /// Get an array of seasonal items that should not appear + /// e.g. if halloween is active, only return christmas items + /// or, if halloween and christmas are inactive, return both sets of items + /// + /// array of tpl strings + public string[] GetInactiveSeasonalEventItems() + { + throw new NotImplementedException(); + } + + /// + /// Is a seasonal event currently active + /// + /// true if event is active + public bool SeasonalEventEnabled() + { + throw new NotImplementedException(); + } + + /// + /// Is christmas event active + /// + /// true if active + public bool ChristmasEventEnabled() + { + throw new NotImplementedException(); + } + + /// + /// is halloween event active + /// + /// true if active + public bool HalloweenEventEnabled() + { + throw new NotImplementedException(); + } + + /// + /// Is detection of seasonal events enabled (halloween / christmas) + /// + /// true if seasonal events should be checked for + public bool IsAutomaticEventDetectionEnabled() + { + throw new NotImplementedException(); + } + + /// + /// Get a dictionary of gear changes to apply to bots for a specific event e.g. Christmas/Halloween + /// + /// Name of event to get gear changes for + /// bots with equipment changes + protected Dictionary>> GetEventBotGear(SeasonalEventType eventType) + { + throw new NotImplementedException(); + } + + /// + /// Get a dictionary of loot changes to apply to bots for a specific event e.g. Christmas/Halloween + /// + /// Name of event to get gear changes for + /// bots with loot changes + protected Dictionary>> GetEventBotLoot(SeasonalEventType eventType) + { + throw new NotImplementedException(); + } + + /// + /// Get the dates each seasonal event starts and ends at + /// + /// Record with event name + start/end date + public List GetEventDetails() + { + throw new NotImplementedException(); + } + + /// + /// Look up quest in configs/quest.json + /// + /// Quest to look up + /// event type (Christmas/Halloween/None) + /// true if related + public bool IsQuestRelatedToEvent(string questId, SeasonalEventType eventType) + { + throw new NotImplementedException(); + } + + /// + /// Handle activating seasonal events + /// + public void EnableSeasonalEvents() + { + throw new NotImplementedException(); + } + + /// + /// Force a seasonal event to be active + /// + /// Event to force active + /// True if event was successfully force enabled + public bool ForceSeasonalEvent(SeasonalEventType eventType) + { + throw new NotImplementedException(); + } + + /// + /// Store active events inside class list property `currentlyActiveEvents` + set class properties: christmasEventActive/halloweenEventActive + /// + public void CacheActiveEvents() + { + throw new NotImplementedException(); + } + + /// + /// Get the currently active weather season e.g. SUMMER/AUTUMN/WINTER + /// + /// Season enum value + public Season GetActiveWeatherSeason() + { + throw new NotImplementedException(); + } + + /// + /// Does the provided date fit between the two defined dates? + /// Excludes year + /// Inclusive of end date upto 23 hours 59 minutes + /// + /// Date to check is between 2 dates + /// Lower bound for month + /// Lower bound for day + /// Upper bound for month + /// Upper bound for day + /// True when inside date range + protected bool DateIsBetweenTwoDates(DateTime dateToCheck, int startMonth, int startDay, int endMonth, int endDay) + { + throw new NotImplementedException(); + } + + /// + /// Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) + /// + /// Bots inventory to iterate over + /// the role of the bot being processed + public void RemoveChristmasItemsFromBotInventory(BotBaseInventory botInventory, string botRole) + { + throw new NotImplementedException(); + } + + /// + /// Make adjusted to server code based on the name of the event passed in + /// + /// globals.json + /// Name of the event to enable. e.g. Christmas + protected void UpdateGlobalEvents(Config globalConfig, SeasonalEvent eventType) + { + throw new NotImplementedException(); + } + + protected void ApplyHalloweenEvent(SeasonalEvent eventType, Config globalConfig) + { + throw new NotImplementedException(); + } + + protected void ApplyChristmasEvent(SeasonalEvent eventType, Config globalConfig) + { + throw new NotImplementedException(); + } + + protected void ApplyNewYearsEvent(SeasonalEvent eventType, Config globalConfig) + { + throw new NotImplementedException(); + } + + protected void AdjustBotAppearanceValues(SeasonalEventType season) + { + throw new NotImplementedException(); + } + + protected void ReplaceBotHostility(Dictionary hostilitySettings) + { + throw new NotImplementedException(); + } + + protected void RemoveEntryRequirement(List locationIds) + { + throw new NotImplementedException(); + } + + public void GivePlayerSeasonalGifts(string sessionId) + { + throw new NotImplementedException(); + } + + /// + /// Force zryachiy to always have a melee weapon + /// + protected void AdjustZryachiyMeleeChance() + { + throw new NotImplementedException(); + } + + /// + /// Enable the halloween zryachiy summon event + /// + protected void EnableHalloweenSummonEvent() + { + throw new NotImplementedException(); + } + + protected void ConfigureZombies(ZombieSettings zombieSettings) + { + throw new NotImplementedException(); + } + + /// + /// Get location ids of maps with an infection above 0 + /// + /// Dict of locations with their infection percentage + /// List of location ids + protected List GetLocationsWithZombies(Dictionary locationInfections) + { + throw new NotImplementedException(); + } + + /// + /// BSG store the location ids differently inside `LocationInfection`, need to convert to matching location IDs + /// + /// Key to convert + /// List of locations + protected List GetLocationFromInfectedLocation(string infectedLocationKey) + { + throw new NotImplementedException(); + } + + protected void AddEventWavesToMaps(string eventType) + { + throw new NotImplementedException(); + } + + /// + /// Add event bosses to maps + /// + /// Seasonal event, e.g. HALLOWEEN/CHRISTMAS + /// OPTIONAL - Maps to add bosses to + protected void AddEventBossesToMaps(string eventType, List mapIdWhitelist = null) + { + throw new NotImplementedException(); + } + + /// + /// Change trader icons to be more event themed (Halloween only so far) + /// + /// What event is active + protected void AdjustTraderIcons(SeasonalEventType eventType) + { + throw new NotImplementedException(); + } + + /// + /// Add lootble items from backpack into patrol.ITEMS_TO_DROP difficulty property + /// + protected void AddLootItemsToGifterDropItemsList() + { + throw new NotImplementedException(); + } + + /// + /// Read in data from seasonalEvents.json and add found equipment items to bots + /// + /// Name of the event to read equipment in from config + protected void AddEventGearToBots(SeasonalEventType eventType) + { + throw new NotImplementedException(); + } + + /// + /// Read in data from seasonalEvents.json and add found loot items to bots + /// + /// Name of the event to read loot in from config + protected void AddEventLootToBots(SeasonalEventType eventType) + { + throw new NotImplementedException(); + } + + /// + /// Add pumpkin loot boxes to scavs + /// + protected void AddPumpkinsToScavBackpacks() + { + throw new NotImplementedException(); + } + + protected void RenameBitcoin() + { + throw new NotImplementedException(); + } + + /// + /// Set Khorovod(dancing tree) chance to 100% on all maps that support it + /// + protected void EnableDancingTree() + { + throw new NotImplementedException(); + } + + /// + /// Add santa to maps + /// + protected void AddGifterBotToMaps() + { + throw new NotImplementedException(); + } + + protected void HandleModEvent(SeasonalEvent seasonalEvent, Config globalConfig) + { + throw new NotImplementedException(); + } + + /// + /// Send gift to player if they have not already received it + /// + /// Player to send gift to + /// Key of gift to give + protected void GiveGift(string playerId, string giftKey) + { + throw new NotImplementedException(); + } + + /// + /// Get the underlying bot type for an event bot e.g. `peacefullZryachiyEvent` will return `bossZryachiy` + /// + /// Event bot role type + /// Bot role as string + public string GetBaseRoleForEventBot(string eventBotRole) + { + throw new NotImplementedException(); + } + + /// + /// Force the weather to be snow + /// + public void EnableSnow() + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/TraderAssortService.cs b/Core/Services/TraderAssortService.cs new file mode 100644 index 00000000..3de93442 --- /dev/null +++ b/Core/Services/TraderAssortService.cs @@ -0,0 +1,21 @@ +using Core.Models.Eft.Common.Tables; + +namespace Core.Services; + +public class TraderAssortService +{ + public TraderAssort GetPristineTraderAssort(string traderId) + { + throw new NotImplementedException(); + } + + /// + /// Store trader assorts inside a class property + /// + /// Traderid to store assorts against + /// Assorts to store + public void SetPristineTraderAssort(string traderId, TraderAssort assort) + { + throw new NotImplementedException(); + } +} diff --git a/Core/Services/TraderPurchasePersisterService.cs b/Core/Services/TraderPurchasePersisterService.cs new file mode 100644 index 00000000..4fa8db96 --- /dev/null +++ b/Core/Services/TraderPurchasePersisterService.cs @@ -0,0 +1,52 @@ +using Core.Models.Eft.Profile; + +namespace Core.Services; + +public class TraderPurchasePersisterService +{ + /** + * Get the purchases made from a trader for this profile before the last trader reset + * @param sessionId Session id + * @param traderId Trader to loop up purchases for + * @returns Dictionary of assort id and count purchased + */ + public Dictionary GetProfileTraderPurchases( + string sessionId, + string traderId) + { + throw new NotImplementedException(); + } + + /** + * Get a purchase made from a trader for requested profile before the last trader reset + * @param sessionId Session id + * @param traderId Trader to loop up purchases for + * @param assortId Id of assort to get data for + * @returns TraderPurchaseData + */ + public TraderPurchaseData GetProfileTraderPurchase( + string sessionId, + string traderId, + string assortId) + { + throw new NotImplementedException(); + } + + /** + * Remove all trader purchase records from all profiles that exist + * @param traderId Traders id + */ + public void ResetTraderPurchasesStoredInProfile(string traderId) + { + throw new NotImplementedException(); + } + + /** + * Iterate over all server profiles and remove specific trader purchase data that has passed the trader refresh time + * @param traderId Trader id + */ + public void RemoveStalePurchasesFromProfiles(string traderId) + { + throw new NotImplementedException(); + } +}