diff --git a/Core/Generators/BotWeaponGenerator.cs b/Core/Generators/BotWeaponGenerator.cs
new file mode 100644
index 00000000..30b8a464
--- /dev/null
+++ b/Core/Generators/BotWeaponGenerator.cs
@@ -0,0 +1,243 @@
+using Core.Models.Eft.Common.Tables;
+using Core.Models.Spt.Bots;
+using Core.Models.Spt.Config;
+
+namespace Core.Generators;
+
+public class BotWeaponGenerator
+{
+ private const string _modMagazineSlotId = "mod_magazine";
+ private BotConfig _botConfig;
+ private PmcConfig _pmcConfig;
+ private RepairConfig _repairConfig;
+
+ public BotWeaponGenerator()
+ {
+ }
+
+ ///
+ /// Pick a random weapon based on weightings and generate a functional weapon
+ ///
+ /// Session identifier
+ /// Primary/secondary/holster
+ /// e.g. assault.json
+ ///
+ ///
+ /// Role of bot, e.g. assault/followerBully
+ /// Is weapon generated for a pmc
+ ///
+ /// GenerateWeaponResult object
+ public GenerateWeaponResult GenerateRandomWeapon(string sessionId, string equipmentSlot, BotBaseInventory botTemplateInventory, string weaponParentId,
+ ModsChances modChances, string botRole, bool isPmc, int botLevel)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Gets a random weighted weapon from a bot's pool of weapons.
+ ///
+ /// Primary/secondary/holster
+ /// e.g. assault.json
+ /// Weapon template
+ public string PickWeightedWeaponTemplateFromPool(string equipmentSlot, BotBaseInventory botTemplateInventory)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Generates a weapon based on the supplied weapon template.
+ ///
+ /// The session identifier.
+ /// Weapon template to generate (use pickWeightedWeaponTplFromPool()).
+ /// Slot to fit into, primary/secondary/holster.
+ /// e.g. assault.json.
+ /// Parent ID of the weapon being generated.
+ /// Dictionary of item types and % chance weapon will have that mod.
+ /// e.g. assault/exusec.
+ /// Is weapon being generated for a PMC.
+ /// The level of the bot.
+ /// GenerateWeaponResult object.
+ public GenerateWeaponResult GenerateWeaponByTpl(string sessionId, string weaponTpl, string slotName, BotBaseInventory botTemplateInventory,
+ string weaponParentId, ModsChances modChances, string botRole, bool isPmc, int botLevel)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Insert cartridge(s) into a weapon
+ /// Handles all chambers - patron_in_weapon, patron_in_weapon_000 etc
+ ///
+ /// Weapon and mods
+ /// Cartridge to add to weapon
+ /// Name of slots to create or add ammo to
+ protected void AddCartridgeToChamber(List- weaponWithModsList, string ammoTemplate, List chamberSlotIdentifiers)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Create a list with weapon base as the only element and
+ /// add additional properties based on weapon type
+ ///
+ /// Weapon template to create item with
+ /// Weapons parent id
+ /// e.g. primary/secondary/holster
+ /// Database template for weapon
+ /// For durability values
+ /// Base weapon item in a list
+ protected List
- ConstructWeaponBaseList(string weaponTemplate, string weaponParentId, string equipmentSlot, TemplateItem weaponItemTemplate,
+ string botRole)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get the mods necessary to kit out a weapon to its preset level
+ ///
+ /// Weapon to find preset for
+ /// The slot the weapon will be placed in
+ /// Value used for the parent id
+ /// Item template
+ /// Bot role
+ /// List of weapon mods
+ protected List
- GetPresetWeaponMods(string weaponTemplate, string equipmentSlot, string weaponParentId, TemplateItem itemTemplate, string botRole)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Checks if all required slots are occupied on a weapon and all its mods.
+ ///
+ /// Weapon + mods
+ /// Role of bot weapon is for
+ /// True if valid
+ protected bool IsWeaponValid(List
- weaponItemList, string botRole)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Generates extra magazines or bullets (if magazine is internal) and adds them to TacticalVest and Pockets.
+ /// Additionally, adds extra bullets to SecuredContainer
+ ///
+ /// Object with properties for generated weapon (weapon mods pool / weapon template / ammo tpl)
+ /// Magazine weights for count to add to inventory
+ /// Inventory to add magazines to
+ /// The bot type we're generating extra mags for
+ public void AddExtraMagazinesToInventory(GenerateWeaponResult generatedWeaponResult, GenerationData magWeights, BotBaseInventory inventory, string botRole)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Add Grenades for UBGL to bot's vest and secure container
+ ///
+ /// Weapon list with mods
+ /// Result of weapon generation
+ /// Bot inventory to add grenades to
+ protected void AddUbglGrenadesToBotInventory(List
- weaponMods, GenerateWeaponResult generatedWeaponResult, BotBaseInventory inventory)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Add ammo to the secure container.
+ ///
+ /// How many stacks of ammo to add.
+ /// Ammo type to add.
+ /// Size of the ammo stack to add.
+ /// Player inventory.
+ protected void AddAmmoToSecureContainer(int stackCount, string ammoTemplate, int stackSize, BotBaseInventory inventory)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get a weapons magazine template from a weapon template.
+ ///
+ /// Mods from a weapon template.
+ /// Weapon to get magazine template for.
+ /// The bot type we are getting the magazine for.
+ /// Magazine template string.
+ protected string GetMagazineTemplateFromWeaponTemplate(List
- weaponMods, TemplateItem weaponTemplate, string botRole)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Finds and returns a compatible ammo template based on the bots ammo weightings (x.json/inventory/equipment/ammo)
+ ///
+ /// Dictionary of all cartridges keyed by type e.g. Caliber556x45NATO
+ /// Weapon details from database we want to pick ammo for
+ /// Ammo template that works with the desired gun
+ protected string GetWeightedCompatibleAmmo(Dictionary> cartridgePool, TemplateItem weaponTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get the cartridge ids from a weapon template that work with the weapon
+ ///
+ /// Weapon db template to get cartridges for
+ /// List of cartridge tpls
+ protected List GetCompatibleCartridgesFromWeaponTemplate(TemplateItem weaponTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get a weapons compatible cartridge caliber
+ ///
+ /// Weapon to look up caliber of
+ /// Caliber as string
+ protected string GetWeaponCaliber(TemplateItem weaponTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Fill existing magazines to full, while replacing their contents with specified ammo
+ ///
+ /// Weapon with children
+ /// Magazine item
+ /// Cartridge to insert into magazine
+ protected void FillExistingMagazines(List
- weaponMods, Item magazine, string cartridgeTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Add desired ammo template as item to weapon modifications list, placed as child to UBGL.
+ ///
+ /// Weapon with children.
+ /// UBGL item.
+ /// Grenade ammo template.
+ protected void FillUbgl(List
- weaponMods, Item ubglMod, string ubglAmmoTpl)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Add cartridge item to weapon item list, if it already exists, update
+ ///
+ /// Weapon items list to amend
+ /// Magazine item details we're adding cartridges to
+ /// Cartridge to put into the magazine
+ /// How many cartridges should go into the magazine
+ /// Magazines db template
+ protected void AddOrUpdateMagazinesChildWithAmmo(List
- weaponWithMods, Item magazine, string chosenAmmoTpl, TemplateItem magazineTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Fill each Camora with a bullet
+ ///
+ /// Weapon mods to find and update camora mod(s) from
+ /// Magazine id to find and add to
+ /// Ammo template id to hydrate with
+ protected void FillCamorasWithAmmo(List
- weaponMods, string magazineId, string ammoTpl)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/Core/Generators/FenceBaseAssortGenerator.cs b/Core/Generators/FenceBaseAssortGenerator.cs
new file mode 100644
index 00000000..25634096
--- /dev/null
+++ b/Core/Generators/FenceBaseAssortGenerator.cs
@@ -0,0 +1,62 @@
+using Core.Models.Eft.Common.Tables;
+using Core.Models.Spt.Config;
+
+namespace Core.Generators;
+
+public class FenceBaseAssortGenerator
+{
+ private TraderConfig _traderConfig;
+
+ public FenceBaseAssortGenerator()
+ {
+
+ }
+
+ ///
+ /// Create base fence assorts dynamically and store in memory
+ ///
+ public void GenerateFenceBaseAssorts()
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Check ammo in boxes and loose ammos has a penetration value above the configured value in trader.json / ammoMaxPenLimit
+ ///
+ /// Ammo box or ammo item from items.db
+ /// True if penetration value is above limit set in config
+ protected bool IsAmmoAbovePenetrationLimit(TemplateItem rootItemDb)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Gets the penetration power value of an ammo, works with ammo boxes and raw ammos.
+ ///
+ /// Ammo box or ammo item from items.db
+ /// Penetration power of passed in item, undefined if it doesnt have a power
+ protected double? GetAmmoPenetrationPower(TemplateItem rootItemDb)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Add soft inserts and armor plates to an armor.
+ ///
+ /// Armor item list to add mods into.
+ /// Armor items db template.
+ protected void AddChildrenToArmorModSlots(List
- armor, TemplateItem itemDbDetails)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Check if item is valid for being added to fence assorts
+ ///
+ /// Item to check
+ /// true if valid fence item
+ protected bool IsValidFenceItem(TemplateItem item)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/Core/Generators/LocationLootGenerator.cs b/Core/Generators/LocationLootGenerator.cs
new file mode 100644
index 00000000..02aa1d1c
--- /dev/null
+++ b/Core/Generators/LocationLootGenerator.cs
@@ -0,0 +1,183 @@
+using System.Text.Json.Serialization;
+using Core.Models.Eft.Common;
+using Core.Models.Eft.Common.Tables;
+using Core.Models.Spt.Config;
+
+namespace Core.Generators;
+
+public class LocationLootGenerator
+{
+ private LocationConfig _locationConfig;
+ private SeasonalEventConfig _seasonalEventConfig;
+
+ public LocationLootGenerator()
+ {
+ }
+
+ /// Create a list of container objects with randomised loot
+ ///
+ /// Map base to generate containers for
+ /// Static ammo distribution
+ /// List of container objects
+ public List GenerateStaticContainers(LocationBase locationBase, Dictionary> staticAmmoDist)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get containers with a non-100% chance to spawn OR are NOT on the container type randomistion blacklist
+ ///
+ ///
+ /// StaticContainerData array
+ protected List GetRandomisableContainersOnMap(List staticContainers)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get containers with 100% spawn rate or have a type on the randomistion ignore list
+ ///
+ ///
+ /// IStaticContainerData array
+ protected List GetGuaranteedContainers(List staticContainersOnMap)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Choose a number of containers based on their probabilty value to fulfil the desired count in containerData.chosenCount
+ ///
+ /// Name of the group the containers are being collected for
+ /// Containers and probability values for a groupId
+ /// List of chosen container Ids
+ protected List GetContainersByProbabilty(string groupId, ContainerGroupCount containerData)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get a mapping of each groupid and the containers in that group + count of containers to spawn on map
+ ///
+ /// Container group values
+ /// dictionary keyed by groupId
+ protected Dictionary GetGroupIdToContainerMappings(
+ object staticContainerGroupData, // TODO: Type fuckery staticContainerGroupData was IStaticContainer | Record
+ List staticContainersOnMap)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Choose loot to put into a static container based on weighting
+ /// Handle forced items + seasonal item removal when not in season
+ ///
+ /// The container itself we will add loot to
+ /// Loot we need to force into the container
+ /// staticLoot.json
+ /// staticAmmo.json
+ /// Name of the map to generate static loot for
+ /// StaticContainerData
+ protected StaticContainerData AddLootToContainer(StaticContainerData staticContainer, List staticForced,
+ Dictionary staticLootDist, Dictionary> staticAmmoDist, string locationName
+ )
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get a 2D grid of a container's item slots
+ ///
+ /// Tpl id of the container
+ /// List
>
+ protected List> GetContainerMapping(string containerTpl)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Look up a containers itemcountDistribution data and choose an item count based on the found weights
+ ///
+ /// Container to get item count for
+ /// staticLoot.json
+ /// Map name (to get per-map multiplier for from config)
+ /// item count
+ protected int GetWeightedCountOfContainerItems(string containerTypeId, Dictionary staticLootDist, string locationName)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get all possible loot items that can be placed into a container
+ /// Do not add seasonal items if found + current date is inside seasonal event
+ ///
+ /// Container to get possible loot for
+ /// staticLoot.json
+ /// ProbabilityObjectArray of item tpls + probabilty
+ protected object GetPossibleLootItemsForContainer(string containerTypeId,
+ Dictionary staticLootDist) // TODO: Type Fuckery, return type was ProbabilityObjectArray
+ {
+ throw new NotImplementedException();
+ }
+
+ protected double GetLooseLootMultiplerForLocation(string location)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected double GetStaticLootMultiplierForLocation(string location)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Create array of loose + forced loot using probability system
+ ///
+ ///
+ ///
+ /// Location to generate loot for
+ /// Array of spawn points with loot in them
+ public List GenerateDynamicLoot(LooseLoot dynamicLootDist, Dictionary> staticAmmoDist,
+ string locationName)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Add forced spawn point loot into loot parameter list
+ ///
+ /// List to add forced loot spawn locations to
+ /// Forced loot locations that must be added
+ /// Name of map currently having force loot created for
+ protected void addForcedLoot(List lootLocationTemplates, List forcedSpawnPoints, string locationName,
+ Dictionary> staticAmmoDist)
+ {
+ throw new NotImplementedException();
+ }
+
+ // TODO: rewrite, BIG yikes
+ protected ContainerItem CreateStaticLootItem(string chosenTemplate, Dictionary> staticAmmoDistribution, string? parentIdentifier = null)
+ {
+ throw new NotImplementedException();
+ }
+}
+
+public class ContainerGroupCount
+{
+ [JsonPropertyName("containerIdsWithProbability")]
+ public Dictionary ContainerIdsWithProbability { get; set; }
+
+ [JsonPropertyName("chosenCount")]
+ public int ChosenCount { get; set; }
+}
+
+public class ContainerItem
+{
+ [JsonPropertyName("items")]
+ public List- Items { get; set; }
+
+ [JsonPropertyName("width")]
+ public int Width { get; set; }
+
+ [JsonPropertyName("height")]
+ public int Height { get; set; }
+}
\ No newline at end of file
diff --git a/Core/Generators/LootGenerator.cs b/Core/Generators/LootGenerator.cs
new file mode 100644
index 00000000..1fa7acbb
--- /dev/null
+++ b/Core/Generators/LootGenerator.cs
@@ -0,0 +1,177 @@
+using System.Text.Json.Serialization;
+using Core.Models.Common;
+using Core.Models.Eft.Common;
+using Core.Models.Eft.Common.Tables;
+using Core.Models.Spt.Config;
+using Core.Models.Spt.Services;
+
+namespace Core.Generators;
+
+public class LootGenerator
+{
+ public LootGenerator()
+ {
+ }
+
+ ///
+ /// Generate a list of items based on configuration options parameter
+ ///
+ /// parameters to adjust how loot is generated
+ /// An array of loot items
+ public List
- CreateRandomLoot(LootRequest options)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Generate An array of items
+ /// TODO - handle weapon presets/ammo packs
+ ///
+ /// Dictionary of item tpls with minmax values
+ /// Array of Item
+ public List
- CreateForcedLoot(Dictionary forcedLootDict)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get pool of items from item db that fit passed in param criteria
+ ///
+ /// Prevent these items
+ /// Only allow these items
+ /// Should item.json reward item config be used
+ /// Should boss items be allowed in result
+ /// results of filtering + blacklist used
+ protected object GetItemRewardPool(List itemTplBlacklist, List itemTypeWhitelist,
+ bool useRewardItemBlacklist, // TODO: type fuckery, return type was { itemPool: [string, ITemplateItem][]; blacklist: Set }
+ bool allowBossItems)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Filter armor items by their front plates protection level - top if its a helmet
+ ///
+ /// Armor preset to check
+ /// Loot request options - armor level etc
+ /// True if item has desired armor level
+ protected bool ArmorOfDesiredProtectionLevel(Preset armor, LootRequest options)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Construct item limit record to hold max and current item count for each item type
+ ///
+ /// limits as defined in config
+ /// record, key: item tplId, value: current/max item count allowed
+ protected Dictionary InitItemLimitCounter(Dictionary limits)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Find a random item in items.json and add to result array
+ ///
+ /// items to choose from
+ /// item limit counts
+ /// item filters
+ /// array to add found item to
+ /// true if item was valid and added to pool
+ protected bool FindAndAddRandomItemToLoot(object items, object itemTypeCounts,
+ LootRequest options, // TODO: items type was [string, ITemplateItem][], itemTypeCounts was Record
+ List
- result)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get a randomised stack count for an item between its StackMinRandom and StackMaxSize values
+ ///
+ /// item to get stack count of
+ /// loot options
+ /// stack count
+ protected int GetRandomisedStackCount(TemplateItem item, LootRequest options)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Find a random item in items.json and add to result list
+ ///
+ /// Presets to choose from
+ /// Item limit counts
+ /// Items to skip
+ /// List to add chosen preset to
+ /// true if preset was valid and added to pool
+ protected bool FindAndAddRandomPresetToLoot(List presetPool, object itemTypeCounts,
+ List itemBlacklist, // TODO: type fuckery, itemTypeCounts was Record
+ List
- result)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Sealed weapon containers have a weapon + associated mods inside them + assortment of other things (food/meds)
+ ///
+ /// sealed weapon container settings
+ /// List of items with children lists
+ public List
> GetSealedWeaponCaseLoot(SealedAirdropContainerSettings containerSettings)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get non-weapon mod rewards for a sealed container
+ ///
+ /// Sealed weapon container settings
+ /// Details for the weapon to reward player
+ /// List of item with children lists
+ protected List> GetSealedContainerNonWeaponModRewards(SealedAirdropContainerSettings containerSettings,
+ TemplateItem weaponDetailsDb)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Iterate over the container weaponModRewardLimits settings and create a list of weapon mods to reward player
+ ///
+ /// Sealed weapon container settings
+ /// All items that can be attached/inserted into weapon
+ /// The weapon preset given to player as reward
+ /// List of item with children lists
+ protected List> GetSealedContainerWeaponModRewards(SealedAirdropContainerSettings containerSettings, List linkedItemsToWeapon,
+ Preset chosenWeaponPreset)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Handle event-related loot containers - currently just the halloween jack-o-lanterns that give food rewards
+ ///
+ ///
+ /// List of item with children lists
+ public List> GetRandomLootContainerLoot(RewardDetails rewardContainerDetails)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Pick a reward item based on the reward details data
+ ///
+ ///
+ /// Single tpl
+ protected string PickRewardItem(RewardDetails rewardContainerDetails)
+ {
+ throw new NotImplementedException();
+ }
+}
+
+public class ItemLimit
+{
+ [JsonPropertyName("current")]
+ public double Current { get; set; }
+
+ [JsonPropertyName("max")]
+ public double Max { get; set; }
+}
\ No newline at end of file
diff --git a/Core/Generators/PMCLootGenerator.cs b/Core/Generators/PMCLootGenerator.cs
index 8de791a8..cda424e9 100644
--- a/Core/Generators/PMCLootGenerator.cs
+++ b/Core/Generators/PMCLootGenerator.cs
@@ -1,13 +1,62 @@
-namespace Core.Generators;
+using Core.Models.Eft.Common.Tables;
+
+namespace Core.Generators;
public class PMCLootGenerator
{
- public List GeneratePMCPocketLootPool()
+ public PMCLootGenerator()
+ {
+
+ }
+
+ ///
+ /// Create a List of loot items a PMC can have in their pockets
+ ///
+ ///
+ /// Dictionary of string and number
+ public Dictionary GeneratePMCPocketLootPool(string botRole)
{
throw new NotImplementedException();
}
- public List GeneratePMCBackpackLootPool()
+ ///
+ /// Create a List of loot items a PMC can have in their vests
+ ///
+ ///
+ /// Dictionary of string and number
+ public Dictionary GeneratePMCVestLootPool(string botRole)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Check if item has a width/height that lets it fit into a 2x2 slot
+ /// 1x1 / 1x2 / 2x1 / 2x2
+ ///
+ /// Item to check size of
+ /// true if it fits
+ protected bool ItemFitsInto2By2Slot(TemplateItem item)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Check if item has a width/height that lets it fit into a 1x2 slot
+ /// 1x1 / 1x2 / 2x1
+ ///
+ /// Item to check size of
+ /// true if it fits
+ protected bool ItemFitsInto1By2Slot(TemplateItem item)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Create a List of loot items a PMC can have in their backpack
+ ///
+ ///
+ /// Dictionary of string and number
+ public Dictionary GeneratePMCBackpackLootPool(string botRole)
{
throw new NotImplementedException();
}
diff --git a/Core/Generators/PlayerScavGenerator.cs b/Core/Generators/PlayerScavGenerator.cs
new file mode 100644
index 00000000..86dc3cef
--- /dev/null
+++ b/Core/Generators/PlayerScavGenerator.cs
@@ -0,0 +1,105 @@
+using Core.Models.Eft.Common;
+using Core.Models.Eft.Common.Tables;
+using Core.Models.Spt.Config;
+
+namespace Core.Generators;
+
+public class PlayerScavGenerator
+{
+ private PlayerScavConfig _playerScavConfig;
+
+ public PlayerScavGenerator()
+ {
+
+ }
+
+ ///
+ /// Update a player profile to include a new player scav profile
+ ///
+ /// session id to specify what profile is updated
+ /// profile object
+ public PmcData Generate(string sessionID)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Add items picked from `playerscav.lootItemsToAddChancePercent`
+ ///
+ /// dict of tpl + % chance to be added
+ ///
+ /// Possible slotIds to add loot to
+ protected void AddAdditionalLootToPlayerScavContainers(Dictionary possibleItemsToAdd, BotBase scavData, List containersToAddTo)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get the scav karama level for a profile
+ /// Is also the fence trader rep level
+ ///
+ /// pmc profile
+ /// karma level
+ protected double GetScavKarmaLevel(PmcData pmcData)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get a baseBot template
+ /// If the parameter doesnt match "assault", take parts from the loot type and apply to the return bot template
+ ///
+ /// bot type to use for inventory/chances
+ /// IBotType object
+ protected BotType ConstructBotBaseTemplate(string botTypeForLoot)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Adjust equipment/mod/item generation values based on scav karma levels
+ ///
+ /// Values to modify the bot template with
+ /// bot template to modify according to karama level settings
+ protected void AdjustBotTemplateWithKarmaSpecificSettings(KarmaLevel karmaSettings, BotType baseBotNode)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected Skills GetScavSkills(PmcData scavProfile)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected Skills GetDefaultScavSkills()
+ {
+ throw new NotImplementedException();
+ }
+
+ protected Stats GetScavStats(PmcData scavProfile)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected int GetScavLevel(PmcData scavProfile)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected int GetScavExperience(PmcData scavProfile)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Set cooldown till scav is playable
+ /// take into account scav cooldown bonus
+ ///
+ /// scav profile
+ /// pmc profile
+ ///
+ protected PmcData SetScavCooldownTimer(PmcData scavData, PmcData pmcData)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/Core/Generators/RagfairAssortGenerator.cs b/Core/Generators/RagfairAssortGenerator.cs
index 58c29137..ca147c64 100644
--- a/Core/Generators/RagfairAssortGenerator.cs
+++ b/Core/Generators/RagfairAssortGenerator.cs
@@ -1,10 +1,60 @@
-using Core.Models.Eft.Common.Tables;
+using Core.Models.Eft.Common;
+using Core.Models.Eft.Common.Tables;
namespace Core.Generators;
public class RagfairAssortGenerator
{
- public List- GetAssortItems()
+ public RagfairAssortGenerator()
+ {
+
+ }
+
+ ///
+ /// Get an array of arrays that can be sold on the flea
+ /// Each sub array contains item + children (if any)
+ ///
+ /// List of Lists
+ public List
> GetAssortItems()
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Check internal generatedAssortItems array has objects
+ ///
+ /// true if array has objects
+ protected bool AssortsAreGenerated()
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Generate an array of arrays (item + children) the flea can sell
+ ///
+ /// List of Lists (item + children)
+ protected List> GenerateRagfairAssortItems()
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get presets from globals to add to flea
+ /// ragfairConfig.dynamic.showDefaultPresetsOnly decides if its all presets or just defaults
+ ///
+ /// Dictionary
+ protected List GetPresetsToAdd()
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Create a base assort item and return it with populated values + 999999 stack count + unlimited count = true
+ ///
+ /// tplid to add to item
+ /// id to add to item
+ /// Hydrated Item object
+ protected Item CreateRagfairAssortRootItem(string tplId, string id_checkTodoComment) // TODO: string id = this.hashUtil.generate()
{
throw new NotImplementedException();
}
diff --git a/Core/Generators/RagfairOfferGenerator.cs b/Core/Generators/RagfairOfferGenerator.cs
index 4c6c0268..f26f838b 100644
--- a/Core/Generators/RagfairOfferGenerator.cs
+++ b/Core/Generators/RagfairOfferGenerator.cs
@@ -1,12 +1,284 @@
using Core.Models.Eft.Common.Tables;
using Core.Models.Eft.Ragfair;
+using Core.Models.Spt.Config;
+using Core.Models.Spt.Ragfair;
namespace Core.Generators;
public class RagfairOfferGenerator
{
- public RagfairOffer CreateOffer(string userID, float time, List- items, List barterScheme, int loyalLevel, int price,
- bool sellInOnePiece)
+ public RagfairOfferGenerator()
+ {
+ }
+
+ ///
+ /// Create a flea offer and store it in the Ragfair server offers list
+ ///
+ /// Owner of the offer
+ /// Time offer is listed at
+ /// Items in the offer
+ /// Cost of item (currency or barter)
+ /// Loyalty level needed to buy item
+ /// Flags sellInOnePiece to be true
+ /// Created flea offer
+ public RagfairOffer CreateAndAddFleaOffer(
+ string userID,
+ double time,
+ List
- items,
+ List barterScheme,
+ int loyalLevel,
+ bool sellInOnePiece = false)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Create an offer object ready to send to ragfairOfferService.addOffer()
+ ///
+ /// Owner of the offer
+ /// Time offer is listed at
+ /// Items in the offer
+ /// Cost of item (currency or barter)
+ /// Loyalty level needed to buy item
+ /// Is offer being created flagged as a pack
+ /// RagfairOffer
+ protected RagfairOffer CreateOffer(
+ string userID,
+ double time,
+ List
- items,
+ List barterScheme,
+ int loyalLevel,
+ bool isPackOffer = false)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Create the user object stored inside each flea offer object
+ ///
+ /// user creating the offer
+ /// Is the user creating the offer a trader
+ /// RagfairOfferUser
+ protected RagfairOfferUser CreateUserDataForFleaOffer(string userID, bool isTrader)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Calculate the offer price that's listed on the flea listing
+ ///
+ /// barter requirements for offer
+ /// rouble cost of offer
+ protected decimal ConvertOfferRequirementsIntoRoubles(List offerRequirements)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get avatar url from trader table in db
+ ///
+ /// Is user we're getting avatar for a trader
+ /// persons id to get avatar of
+ /// url of avatar
+ protected string GetAvatarUrl(bool isTrader, string userId)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Convert a count of currency into roubles
+ ///
+ /// amount of currency to convert into roubles
+ /// Type of currency (euro/dollar/rouble)
+ /// count of roubles
+ protected double CalculateRoublePrice(decimal currencyCount, string currencyType)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Check userId, if its a player, return their pmc _id, otherwise return userId parameter
+ ///
+ /// Users Id to check
+ /// Users Id
+ protected string GetTraderId(string userId)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get a flea trading rating for the passed in user
+ ///
+ /// User to get flea rating of
+ /// Flea rating value
+ protected double GetRating(string userId)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Is the offers user rating growing
+ ///
+ /// user to check rating of
+ /// true if its growing
+ protected bool GetRatingGrowing(string userID)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get number of section until offer should expire
+ ///
+ /// Id of the offer owner
+ /// Time the offer is posted
+ /// number of seconds until offer expires
+ protected double GetOfferEndTime(string userID, double time)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Create multiple offers for items by using a unique list of items we've generated previously
+ ///
+ /// optional, expired offers to regenerate
+ public async Task GenerateDynamicOffers(List
> expiredOffers = null)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ ///
+ /// Item with its children to process into offers
+ /// is an expired offer
+ /// Ragfair dynamic config
+ protected async Task CreateOffersFromAssort(List- assortItemWithChildren, bool isExpiredOffer, Dynamic config)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// iterate over an items chidren and look for plates above desired level and remove them
+ ///
+ /// preset to check for plates
+ /// Settings
+ /// True if plate removed
+ protected bool RemoveBannedPlatesFromPreset(List
- presetWithChildren, ArmorPlateBlacklistSettings plateSettings)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Create one flea offer for a specific item
+ ///
+ /// Id of seller
+ /// Item to create offer for
+ /// Is item a weapon preset
+ /// Raw db item details
+ /// Item array
+ protected async Task CreateSingleOfferForItem(string sellerId, List
- itemWithChildren, bool isPreset, TemplateItem itemToSellDetails)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Generate trader offers on flea using the traders assort data
+ ///
+ /// Trader to generate offers for
+ public void GenerateFleaOffersForTrader(string traderID)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get array of an item with its mods + condition properties (e.g durability)
+ /// Apply randomisation adjustments to condition if item base is found in ragfair.json/dynamic/condition
+ ///
+ /// id of owner of item
+ /// Item and mods, get condition of first item (only first array item is modified)
+ /// db details of first item
+ protected void RandomiseOfferItemUpdProperties(string userID, List
- itemWithMods, TemplateItem itemDetails)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected string? GetDynamicConditionIdForTpl(string tpl)
+ {
+ throw new NotImplementedException();
+ }
+
+ /**
+ * Alter an items condition based on its item base type
+ * @param conditionSettingsId also the parentId of item being altered
+ * @param itemWithMods Item to adjust condition details of
+ * @param itemDetails db item details of first item in array
+ */
+ protected void RandomiseItemCondition(string conditionSettingsId, List
- itemWithMods, TemplateItem itemDetails)
+ {
+ throw new NotImplementedException();
+ }
+
+ /**
+ * Adjust an items durability/maxDurability value
+ * @param item item (weapon/armor) to Adjust
+ * @param itemDbDetails Weapon details from db
+ * @param maxMultiplier Value to multiply max durability by
+ * @param currentMultiplier Value to multiply current durability by
+ */
+ protected void RandomiseWeaponDurability(Item item, TemplateItem itemDbDetails, double maxMultiplier, double currentMultiplier)
+ {
+ throw new NotImplementedException();
+ }
+
+ /**
+ * Randomise the durability values for an armors plates and soft inserts
+ * @param armorWithMods Armor item with its child mods
+ * @param currentMultiplier Chosen multiplier to use for current durability value
+ * @param maxMultiplier Chosen multiplier to use for max durability value
+ */
+ protected void RandomiseArmorDurabilityValues(List
- armorWithMods, double currentMultiplier, double maxMultiplier)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Add missing conditions to an item if needed
+ /// Durability for repairable items
+ /// HpResource for medical items
+ ///
+ /// item to add conditions to
+ protected void AddMissingConditions(Item item)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Create a barter-based barter scheme, if not possible, fall back to making barter scheme currency based
+ ///
+ /// Items for sale in offer
+ /// Barter config from ragfairConfig.dynamic.barter
+ /// Barter scheme
+ protected List CreateBarterBarterScheme(List
- offerItems, BarterDetails barterConfig)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get a list of flea prices + item tpl, cached in generator class inside `allowedFleaPriceItemsForBarter`
+ ///
+ /// list with tpl/price values
+ protected List GetFleaPricesAsList()
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Create a random currency-based barter scheme for a list of items
+ ///
+ /// Items on offer
+ /// Is the barter scheme being created for a pack offer
+ /// What to multiply the resulting price by
+ /// Barter scheme for offer
+ protected List CreateCurrencyBarterScheme(List
- offerWithChildren, bool isPackOffer, double multipler = 1)
{
throw new NotImplementedException();
}
diff --git a/Core/Generators/RepeatableQuestGenerator.cs b/Core/Generators/RepeatableQuestGenerator.cs
new file mode 100644
index 00000000..97b16658
--- /dev/null
+++ b/Core/Generators/RepeatableQuestGenerator.cs
@@ -0,0 +1,208 @@
+using Core.Models.Eft.Common;
+using Core.Models.Eft.Common.Tables;
+using Core.Models.Spt.Config;
+using Core.Models.Spt.Repeatable;
+
+namespace Core.Generators;
+
+public class RepeatableQuestGenerator
+{
+ public RepeatableQuestGenerator()
+ {
+ }
+
+ ///
+ /// This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json).
+ /// It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest
+ ///
+ /// Session id
+ /// Player's level for requested items and reward generation
+ /// Players traper standing/rep levels
+ /// Possible quest types pool
+ /// Repeatable quest config
+ /// RepeatableQuest
+ public RepeatableQuest GenerateRepeatableQuest(
+ string sessionId,
+ int pmcLevel,
+ Dictionary pmcTraderInfo,
+ QuestTypePool questTypePool,
+ RepeatableQuestConfig repeatableConfig
+ )
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Generate a randomised Elimination quest
+ ///
+ /// Player's level for requested items and reward generation
+ /// Trader from which the quest will be provided
+ /// Pools for quests (used to avoid redundant quests)
+ /// The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest
+ /// Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json)
+ protected RepeatableQuest GenerateEliminationQuest(
+ string sessionid,
+ int pmcLevel,
+ string traderId,
+ QuestTypePool questTypePool,
+ RepeatableQuestConfig repeatableConfig
+ )
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get a number of kills neded to complete elimination quest
+ ///
+ /// Target type desired e.g. anyPmc/bossBully/Savage
+ /// Config
+ /// Config
+ /// Number of AI to kill
+ protected int GetEliminationKillCount(
+ string targetKey,
+ object targetsConfig, // TODO: typing was ProbabilityObjectArray
+ EliminationConfig eliminationConfig
+ )
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json)
+ /// This is a helper method for GenerateEliminationQuest to create a location condition.
+ ///
+ /// the location on which to fulfill the elimination quest
+ /// Elimination-location-subcondition object
+ protected QuestConditionCounterCondition GenerateEliminationLocation(List location)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Create kill condition for an elimination quest
+ ///
+ /// Bot type target of elimination quest e.g. "AnyPmc", "Savage"
+ /// Body parts player must hit
+ /// Distance from which to kill (currently only >= supported)
+ /// What weapon must be used - undefined = any
+ /// What category of weapon must be used - undefined = any
+ /// EliminationCondition object
+ protected QuestConditionCounterCondition GenerateEliminationCondition(
+ string target,
+ List targetedBodyParts,
+ double distance,
+ string allowedWeapon,
+ string allowedWeaponCategory
+ )
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Generates a valid Completion quest
+ ///
+ /// player's level for requested items and reward generation
+ /// trader from which the quest will be provided
+ /// The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requested quest
+ /// quest type format for "Completion" (see assets/database/templates/repeatableQuests.json)
+ protected RepeatableQuest GenerateCompletionQuest(
+ string sessionId,
+ int pmcLevel,
+ string traderId,
+ RepeatableQuestConfig repeatableConfig
+ )
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json)
+ /// This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many)
+ ///
+ /// id of the item to request
+ /// amount of items of this specific type to request
+ /// object of "Completion"-condition
+ protected RepeatableQuest GenerateCompletionAvailableForFinish(string itemTpl, int value)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Generates a valid Exploration quest
+ ///
+ /// session id for the quest
+ /// player's level for reward generation
+ /// trader from which the quest will be provided
+ /// Pools for quests (used to avoid redundant quests)
+ /// The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requested quest
+ /// object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json)
+ protected RepeatableQuest GenerateExplorationQuest(
+ string sessionId,
+ int pmcLevel,
+ string traderId,
+ QuestTypePool questTypePool,
+ RepeatableQuestConfig repeatableConfig)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Filter a maps exits to just those for the desired side
+ ///
+ /// Map id (e.g. factory4_day)
+ /// Scav/Pmc
+ /// List of Exit objects
+ protected List GetLocationExitsForSide(string locationKey, string playerSide)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected object GeneratePickupQuest(
+ string sessionId,
+ int pmcLevel,
+ string traderId,
+ QuestTypePool questTypePool,
+ RepeatableQuestConfig repeatableConfig)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567)
+ ///
+ /// e.g factory4_day
+ /// guid
+ protected string GetQuestLocationByMapId(string locationKey)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Exploration repeatable quests can specify a required extraction point.
+ /// This method creates the according object which will be appended to the conditions list
+ ///
+ /// The exit name to generate the condition for
+ /// Exit condition
+ protected QuestConditionCounterCondition GenerateExplorationExitCondition(Exit exit)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json
+ /// The templates include Elimination, Completion and Extraction quest types
+ ///
+ /// Quest type: "Elimination", "Completion" or "Extraction"
+ /// Trader from which the quest will be provided
+ /// Scav daily or pmc daily/weekly quest
+ /// Object which contains the base elements for repeatable quests of the requests type
+ /// (needs to be filled with reward and conditions by called to make a valid quest)
+ protected RepeatableQuest GenerateRepeatableTemplate(
+ string type,
+ string traderId,
+ string side,
+ string sessionId)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/Core/Generators/ScavCaseRewardGenerator.cs b/Core/Generators/ScavCaseRewardGenerator.cs
new file mode 100644
index 00000000..e0c9c1fa
--- /dev/null
+++ b/Core/Generators/ScavCaseRewardGenerator.cs
@@ -0,0 +1,125 @@
+using Core.Models.Eft.Common.Tables;
+using Core.Models.Eft.Hideout;
+using Core.Models.Spt.Hideout;
+
+namespace Core.Generators;
+
+public class ScavCaseRewardGenerator
+{
+ public ScavCaseRewardGenerator()
+ {
+ }
+
+ ///
+ /// Create an array of rewards that will be given to the player upon completing their scav case build
+ ///
+ /// recipe of the scav case craft
+ /// Product array
+ public List
> Generate(string recipeId)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get all db items that are not blacklisted in scavcase config or global blacklist
+ /// Store in class field
+ ///
+ protected void CacheDbItems()
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Pick a number of items to be rewards, the count is defined by the values in `itemFilters` param
+ ///
+ /// item pool to pick rewards from
+ /// how the rewards should be filtered down (by item count)
+ ///
+ protected List PickRandomRewards(
+ List items,
+ RewardCountAndPriceDetails itemFilters,
+ string rarity)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Choose if money should be a reward based on the moneyRewardChancePercent config chance in scavCaseConfig
+ ///
+ /// true if reward should be money
+ protected bool RewardShouldBeMoney()
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Choose if ammo should be a reward based on the ammoRewardChancePercent config chance in scavCaseConfig
+ ///
+ /// true if reward should be ammo
+ protected bool RewardShouldBeAmmo()
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Choose from rouble/dollar/euro at random
+ ///
+ protected TemplateItem GetRandomMoney()
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get a random ammo from items.json that is not in the ammo blacklist AND inside the price range defined in scavcase.json config
+ ///
+ /// The rarity this ammo reward is for
+ /// random ammo item from items.json
+ protected TemplateItem GetRandomAmmo(string rarity)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Take all the rewards picked create the Product object array ready to return to calling code
+ /// Also add a stack count to ammo and money
+ ///
+ /// items to convert
+ /// Product array
+ protected List> RandomiseContainerItemRewards(List rewardItems, string rarity)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ ///
+ /// all items from the items.json
+ /// controls how the dbItems will be filtered and returned (handbook price)
+ /// filtered dbItems array
+ protected List GetFilteredItemsByPrice(
+ List dbItems,
+ RewardCountAndPriceDetails itemFilters)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Gathers the reward min and max count params for each reward quality level from config and scavcase.json into a single object
+ ///
+ /// production.json/scavRecipes object
+ /// ScavCaseRewardCountsAndPrices object
+ protected ScavCaseRewardCountsAndPrices GetScavCaseRewardCountsAndPrices(ScavRecipe scavCaseDetails)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Randomises the size of ammo and money stacks
+ ///
+ /// ammo or money item
+ /// rarity (common/rare/superrare)
+ /// value to set stack count to
+ protected int GetRandomAmountRewardForScavCase(TemplateItem itemToCalculate, string rarity)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/Core/Generators/WeatherGenerator.cs b/Core/Generators/WeatherGenerator.cs
new file mode 100644
index 00000000..f3abe30b
--- /dev/null
+++ b/Core/Generators/WeatherGenerator.cs
@@ -0,0 +1,110 @@
+using Core.Models.Eft.Weather;
+using Core.Models.Enums;
+using Core.Models.Spt.Config;
+
+namespace Core.Generators;
+
+public class WeatherGenerator
+{
+ public WeatherGenerator()
+ {
+ }
+
+ /**
+ * Get current + raid datetime and format into correct BSG format and return
+ * @param data Weather data
+ * @returns WeatherData
+ */
+ public WeatherData CalculateGameTime(WeatherData data)
+ {
+ throw new NotImplementedException();
+ }
+
+ /**
+ * Get server uptime seconds multiplied by a multiplier and add to current time as seconds
+ * Format to BSGs requirements
+ * @param currentDate current date
+ * @returns formatted time
+ */
+ protected string GetBsgFormattedInRaidTime()
+ {
+ throw new NotImplementedException();
+ }
+
+ /**
+ * Get current time formatted to fit BSGs requirement
+ * @param date date to format into bsg style
+ * @returns Time formatted in BSG format
+ */
+ protected string GetBsgFormattedTime(DateTime date)
+ {
+ throw new NotImplementedException();
+ }
+
+ /**
+ * Return randomised Weather data with help of config/weather.json
+ * @param currentSeason the currently active season
+ * @param timestamp OPTIONAL what timestamp to generate the weather data at, defaults to now when not supplied
+ * @returns Randomised weather data
+ */
+ public Weather GenerateWeather(Season currentSeason, int? timestamp = null)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected SeasonalValues GetWeatherValuesBySeason(Season currentSeason)
+ {
+ throw new NotImplementedException();
+ }
+
+ /**
+ * Choose a temprature for the raid based on time of day
+ * @param currentSeason What season tarkov is currently in
+ * @param inRaidTimestamp What time is the raid running at
+ * @returns Timestamp
+ */
+ protected double GetRaidTemperature(SeasonalValues weather, int inRaidTimestamp)
+ {
+ throw new NotImplementedException();
+ }
+
+ /**
+ * Set Weather date/time/timestamp values to now
+ * @param weather Object to update
+ * @param timestamp OPTIONAL, define timestamp used
+ */
+ protected void SetCurrentDateTime(Weather weather, int? timestamp = null)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected WindDirection GetWeightedWindDirection(SeasonalValues weather)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected double GetWeightedClouds(SeasonalValues weather)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected double GetWeightedWindSpeed(SeasonalValues weather)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected double GetWeightedFog(SeasonalValues weather)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected double GetWeightedRain(SeasonalValues weather)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected double GetRandomFloat(double min, double max, int precision = 3)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/Core/Models/Spt/Hideout/ScavCaseRewardCountsAndPrice.cs b/Core/Models/Spt/Hideout/ScavCaseRewardCountsAndPrices.cs
similarity index 94%
rename from Core/Models/Spt/Hideout/ScavCaseRewardCountsAndPrice.cs
rename to Core/Models/Spt/Hideout/ScavCaseRewardCountsAndPrices.cs
index 61e780e3..2493204e 100644
--- a/Core/Models/Spt/Hideout/ScavCaseRewardCountsAndPrice.cs
+++ b/Core/Models/Spt/Hideout/ScavCaseRewardCountsAndPrices.cs
@@ -2,7 +2,7 @@
namespace Core.Models.Spt.Hideout;
-public class ScavCaseRewardCountsAndPrice
+public class ScavCaseRewardCountsAndPrices
{
[JsonPropertyName("Common")]
public RewardCountAndPriceDetails Common { get; set; }