diff --git a/Core/Generators/BotEquipmentModGenerator.cs b/Core/Generators/BotEquipmentModGenerator.cs
new file mode 100644
index 00000000..44add471
--- /dev/null
+++ b/Core/Generators/BotEquipmentModGenerator.cs
@@ -0,0 +1,391 @@
+using Core.Models.Eft.Common;
+using Core.Models.Eft.Common.Tables;
+using Core.Models.Enums;
+using Core.Models.Spt.Bots;
+using Core.Models.Spt.Config;
+
+namespace Core.Generators;
+
+public class BotEquipmentModGenerator
+{
+ private BotConfig _botConfig;
+
+ public BotEquipmentModGenerator()
+ {
+ }
+
+ ///
+ /// Check mods are compatible and add to array
+ ///
+ /// Equipment item to add mods to
+ /// Mod list to choose from
+ /// parentid of item to add mod to
+ /// Template object of item to add mods to
+ /// The relevant blacklist from bot.json equipment dictionary
+ /// should this mod be forced to spawn
+ /// Item + compatible mods as an array
+ public Item GenerateModsForEquipment(List- equipment, string parentId, TemplateItem parentTemplate, GenerateEquipmentProperties settings,
+ EquipmentFilterDetails specificBlacklist, bool shouldForceSpawn = false)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Filter a bots plate pool based on its current level
+ ///
+ /// Bot equipment generation settings
+ /// Armor slot being filtered
+ /// Plates tpls to choose from
+ /// The armor items db template
+ /// Array of plate tpls to choose from
+ public FilterPlateModsForSlotByLevelResult FilterPlateModsForSlotByLevel(GenerateEquipmentProperties settings, string modSlot,
+ List existingPlateTplPool, TemplateItem armorItem)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Add mods to a weapon using the provided mod pool
+ ///
+ /// Session id
+ /// Data used to generate the weapon
+ /// Weapon + mods array
+ public List
- GenerateModsForWeapon(string sessionId, GenerateWeaponRequest request)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Should the provided bot have its stock chance values altered to 100%
+ ///
+ /// Slot to check
+ /// Bots equipment config/chance values
+ /// Mod being added to bots weapon
+ /// True if it should
+ public bool ShouldForceSubStockSlots(string modSlot, EquipmentFilters botEquipConfig, TemplateItem modToAddTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Is this modslot a front or rear sight
+ ///
+ /// Slot to check
+ ///
+ /// true if it's a front/rear sight
+ public bool ModIsFrontOrRearSight(string modSlot, string tpl)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Does the provided mod details show the mod can hold a scope
+ ///
+ /// e.g. mod_scope, mod_mount
+ /// Parent id of mod item
+ /// true if it can hold a scope
+ public bool ModSlotCanHoldScope(string modSlot, string ModsParentId)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Set mod spawn chances to defined amount
+ ///
+ /// Chance dictionary to update
+ ///
+ ///
+ public void AdjustSlotSpawnChances(ModsChances modSpawnChances, List modSlotsToAdjust, double newChancePercent)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Does the provided modSlot allow muzzle-related items
+ ///
+ /// Slot id to check
+ /// OPTIONAL: parent id of modslot being checked
+ /// True if modSlot can have muzzle-related items
+ public bool AodSlotCanHoldMuzzleDevices(string modSlot, string? modsParentId)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Sort mod slots into an ordering that maximises chance of a successful weapon generation
+ ///
+ /// Array of mod slot strings to sort
+ /// The Tpl of the item with mod keys being sorted
+ /// Sorted array
+ public List SortModKeys(List unsortedSlotKeys, string itemTplWithKeysToSort)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get a Slot property for an item (chamber/cartridge/slot)
+ ///
+ /// e.g patron_in_weapon
+ /// item template
+ /// Slot item
+ public Slot GetModItemSlotFromDb(string modSlot, TemplateItem parentTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Randomly choose if a mod should be spawned, 100% for required mods OR mod is ammo slot
+ ///
+ /// slot the item sits in from db
+ /// Name of slot the mod sits in
+ /// Chances for various mod spawns
+ /// Various config settings for generating this type of bot
+ /// ModSpawn.SPAWN when mod should be spawned, ModSpawn.DEFAULT_MOD when default mod should spawn, ModSpawn.SKIP when mod is skipped
+ public ModSpawn ShouldModBeSpawned(Slot itemSlot, string modSlotName, ModsChances modSpawnChances, EquipmentFilters botEquipConfig)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Choose a mod to fit into the desired slot
+ ///
+ /// Data used to choose an appropriate mod with
+ /// itemHelper.getItem() result
+ public object? ChooseModToPutIntoSlot(ModToSpawnRequest request) // TODO: type fuckery: [boolean, ITemplateItem] | undefined
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Given the passed in array of magaizne tpls, look up the min size set in config and return only those that have that size or larger
+ ///
+ /// Request data
+ /// Pool of magazine tpls to filter
+ /// Filtered pool of magazine tpls
+ ///
+ public List GetFilterdMagazinePoolByCapacity(ModToSpawnRequest modSpawnRequest, List modPool)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Choose a weapon mod tpl for a given slot from a pool of choices
+ /// Checks chosen tpl is compatible with all existing weapon items
+ ///
+ ///
+ /// Pool of mods that can be picked from
+ /// Slot the picked mod will have as a parent
+ /// How should chosen tpl be treated: DEFAULT_MOD/SPAWN/SKIP
+ /// Array of weapon items chosen item will be added to
+ /// Name of slot picked mod will be placed into
+ /// Chosen weapon details
+ public ChooseRandomCompatibleModResult GetCompatibleWeaponModTplForSlotFromPool(ModToSpawnRequest request, List modPool, Slot parentSlot,
+ ModSpawn choiceTypeEnum, List
- weapon, string modSlotName)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ ///
+ ///
+ /// Pool of item Tpls to choose from
+ /// How should the slot choice be handled - forced/normal etc
+ /// Weapon mods at current time
+ /// IChooseRandomCompatibleModResult
+ public ChooseRandomCompatibleModResult GetCompatibleModFromPool(List modPool, ModSpawn modSpawnType, List
- weapon)
+ {
+ throw new NotImplementedException();
+ }
+
+ public object CreateExhaustableArray(T itemsToAddToArray) // TODO: this wont likely be needed, reimplement for C#
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get a list of mod tpls that are compatible with the current weapon
+ ///
+ ///
+ /// Tpls that are incompatible and should not be used
+ /// string array of compatible mod tpls with weapon
+ public List GetFilteredModPool(List modPool, List tplBlacklist) // TODO: tplBlacklist was Set
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Filter mod pool down based on various criteria:
+ /// Is slot flagged as randomisable
+ /// Is slot required
+ /// Is slot flagged as default mod only
+ ///
+ ///
+ /// Mods root parent (weapon/equipment)
+ /// Array of mod tpls
+ public List GetModPoolForSlot(ModToSpawnRequest request, TemplateItem weaponTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ public List GetModPoolForDefaultSlot(ModToSpawnRequest request, TemplateItem weaponTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ public object GetMatchingModFromPreset(ModToSpawnRequest request, TemplateItem weaponTemplate) // TODO: no return type given in node server
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get default preset for weapon OR get specific weapon presets for edge cases (mp5/silenced dvl)
+ ///
+ /// Weapons db template
+ /// Tpl of the parent item
+ /// Default preset found
+ public Preset? GetMatchingPreset(TemplateItem weaponTemplate, string parentItemTpl)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Temp fix to prevent certain combinations of weapons with mods that are known to be incompatible
+ ///
+ /// Array of items that make up a weapon
+ /// Mod to check compatibility with weapon
+ /// True if incompatible
+ public bool WeaponModComboIsIncompatible(List
- weapon, string modTpl)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Create a mod item with provided parameters as properties + add upd property
+ ///
+ /// _id
+ /// _tpl
+ /// parentId
+ /// slotId
+ /// Used to add additional properties in the upd object
+ /// The bots role mod is being created for
+ /// Item object
+ public Item CreateModItem(string modId, string modTpl, string parentId, string modSlot, TemplateItem modTemplate, string botRole)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get a list of containers that hold ammo
+ /// e.g. mod_magazine / patron_in_weapon_000
+ ///
+ /// string array
+ public List GetAmmoContainers()
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get a random mod from an items compatible mods Filter array
+ ///
+ /// Default value to return if parentSlot Filter is empty
+ /// Item mod will go into, used to get compatible items
+ /// Slot to get mod to fill
+ /// Items to ensure picked mod is compatible with
+ /// Item tpl
+ public string? GetRandomModTplFromItemDb(string fallbackModTpl, Slot parentSlot, string modSlot, List
- items)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Check if mod exists in db + is for a required slot
+ /// TODO: modToAdd type was [boolean, ITemplateItem] in node
+ ///
+ /// Db template of mod to check
+ /// Slot object the item will be placed as child into
+ /// Slot the mod will fill
+ /// Db template of the mods being added
+ /// Bots wildspawntype (assault/pmcBot/exUsec etc)
+ /// True if valid for slot
+ public bool IsModValidForSlot(object modToAdd, Slot slotAddedToTemplate, string modSlot, TemplateItem parentTemplate, string botRole)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Find mod tpls of a provided type and add to modPool
+ ///
+ /// Slot to look up and add we are adding tpls for (e.g mod_scope)
+ /// db object for modItem we get compatible mods from
+ /// Pool of mods we are adding to
+ /// A blacklist of items that cannot be picked
+ public void AddCompatibleModsForProvidedMod(string desiredSlotName, TemplateItem modTemplate, Dictionary>> modPool,
+ EquipmentFilterDetails botEquipBlacklist)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get the possible items that fit a slot
+ ///
+ /// item tpl to get compatible items for
+ /// Slot item should fit in
+ /// Equipment that should not be picked
+ /// Array of compatible items for that slot
+ public List GetDynamicModPool(string parentItemId, string modSlot, EquipmentFilterDetails botEquipBlacklist)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Take a list of tpls and filter out blacklisted values using itemFilterService + botEquipmentBlacklist
+ ///
+ /// Base mods to filter
+ /// Equipment blacklist
+ /// Slot mods belong to
+ /// Filtered array of mod tpls
+ public List FilterModsByBlacklist(List allowedMods, EquipmentFilterDetails botEquipBlacklist, string modSlot)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// With the shotgun revolver (60db29ce99594040e04c4a27) 12.12 introduced CylinderMagazines.
+ /// Those magazines (e.g. 60dc519adf4c47305f6d410d) have a "Cartridges" entry with a _max_count=0.
+ /// Ammo is not put into the magazine directly but assigned to the magazine's slots: The "camora_xxx" slots.
+ /// This function is a helper called by generateModsForItem for mods with parent type "CylinderMagazine"
+ ///
+ /// The items where the CylinderMagazine's camora are appended to
+ /// ModPool which should include available cartridges
+ /// The CylinderMagazine's UID
+ /// The CylinderMagazine's template
+ public void FillCamora(List
- items, Dictionary>> modPool, string cylinderMagParentId,
+ TemplateItem cylinderMagTemplate)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Take a record of camoras and merge the compatible shells into one array
+ ///
+ /// Dictionary of camoras we want to merge into one array
+ /// String array of shells for multiple camora sources
+ public List MergeCamoraPools(Dictionary> camorasWithShells)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Filter out non-whitelisted weapon scopes
+ /// Controlled by bot.json weaponSightWhitelist
+ /// e.g. filter out rifle scopes from SMGs
+ ///
+ /// Weapon scopes will be added to
+ /// Full scope pool
+ /// Whitelist of scope types by weapon base type
+ /// Array of scope tpls that have been filtered to just ones allowed for that weapon type
+ public List FilterSightsByWeaponType(Item weapon, List scopes, Dictionary> botWeaponSightWhitelist)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/Core/Generators/BotLevelGenerator.cs b/Core/Generators/BotLevelGenerator.cs
new file mode 100644
index 00000000..1741311d
--- /dev/null
+++ b/Core/Generators/BotLevelGenerator.cs
@@ -0,0 +1,43 @@
+using Core.Models.Common;
+using Core.Models.Eft.Bot;
+using Core.Models.Eft.Common.Tables;
+using Core.Models.Spt.Bots;
+
+namespace Core.Generators;
+
+public class BotLevelGenerator
+{
+ public BotLevelGenerator()
+ {
+
+ }
+
+ ///
+ /// Return a randomised bot level and exp value
+ ///
+ /// Min and max of level for bot
+ /// Details to help generate a bot
+ /// Bot the level is being generated for
+ /// IRandomisedBotLevelResult object
+ public RandomisedBotLevelResult GenerateBotLevel(MinMax levelDetails, BotGenerationDetails botGenerationDetails, BotBase bot)
+ {
+ throw new NotImplementedException();
+ }
+
+ public int ChooseBotLevel(int min, int max, int shift, int number)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Return the min and max bot level based on a relative delta from the PMC level
+ ///
+ /// Details to help generate a bot
+ ///
+ /// Max level allowed
+ /// A MinMax of the lowest and highest level to generate the bots
+ public MinMax GetRelativeBotLevelRange(BotGenerationDetails botGenerationDetails, MinMax levelDetails, int maxAvailableLevel)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/Core/Generators/BotLootGenerator.cs b/Core/Generators/BotLootGenerator.cs
new file mode 100644
index 00000000..074a18fd
--- /dev/null
+++ b/Core/Generators/BotLootGenerator.cs
@@ -0,0 +1,202 @@
+using Core.Models.Eft.Common.Tables;
+using Core.Models.Enums;
+using Core.Models.Spt.Bots;
+using Core.Models.Spt.Config;
+
+namespace Core.Generators;
+
+public class BotLootGenerator
+{
+ private BotConfig _botConfig;
+ private PmcConfig _pmcConfig;
+
+ public BotLootGenerator()
+ {
+
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ItemSpawnLimitSettings GetItemSpawnLimitsForBot(string botRole)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Add loot to bots containers
+ ///
+ /// Session id
+ /// Base json db file for the bot having its loot generated
+ /// Will bot be a pmc
+ /// Role of bot, e.g. asssult
+ /// Inventory to add loot to
+ /// Level of bot
+ public void GenerateLoot(string sessionId, BotType botJsonTemplate, bool isPmc, string botRole, BotBaseInventory botInventory, int botLevel)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Gets the rouble cost total for loot in a bots backpack by the bots levl
+ /// Will return 0 for non PMCs
+ ///
+ /// Bots level
+ /// Is the bot a PMC
+ /// int
+ public int GetBackpackRoubleTotalByLevel(int botLevel, bool isPmc)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public List GetAvailableContainersBotCanStoreItemsIn(BotBaseInventory botInventory)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Force healing items onto bot to ensure they can heal in-raid
+ ///
+ /// Inventory to add items to
+ /// Role of bot (pmcBEAR/pmcUSEC)
+ public void AddForcedMedicalItemsToPmcSecure(BotBaseInventory botInventory, string botRole)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Take random items from a pool and add to an inventory until totalItemCount or totalValueLimit or space limit is reached
+ ///
+ /// Pool of items to pick from with weight
+ /// What equipment slot will the loot items be added to
+ /// Max count of items to add
+ /// Bot inventory loot will be added to
+ /// Role of the bot loot is being generated for (assault/pmcbot)
+ /// Item spawn limits the bot must adhere to
+ ///
+ /// Total value of loot allowed in roubles
+ /// Is bot being generated for a pmc
+ ///
+ public void AddLootFromPool(Dictionary pool, List equipmentSlots, int totalItemCount, BotBaseInventory inventoryToAddItemsTo, // TODO: type for containersIdFull was Set
+ string botRole, ItemSpawnLimitSettings? itemSpawnLimits, List containersIdFull, int totalValueLimitRub = 0, bool isPmc = false)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public List
> CrateWalletLoot(string walletId)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Some items need child items to function, add them to the itemToAddChildrenTo array
+ ///
+ /// Db template of item to check
+ /// Item to add children to
+ /// Is the item being generated for a pmc (affects money/ammo stack sizes)
+ /// role bot has that owns item
+ public void AddRequiredChildItemsToParent(TemplateItem itemToAddTemplate, List- itemToAddChildrenTo, bool isPmc, string botRole)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Add generated weapons to inventory as loot
+ ///
+ ///
+ /// inventory to add preset to
+ /// slot to place the preset in (backpack)
+ /// bots template, assault.json
+ /// chances for mods to spawn on weapon
+ /// bots role .e.g. pmcBot
+ /// are we generating for a pmc
+ ///
+ ///
+ public void AddLooseWeaponsToInventorySlot(string sessionId, BotBaseInventory botInventory, string equipmentSlot, BotBaseInventory templateInventory, // TODO: type for containersIdFull was Set
+ ModsChances modsChances, string botRole, bool isPmc, int botLevel, List? containersIdFull)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Hydrate item limit array to contain items that have a limit for a specific bot type
+ /// All values are set to 0
+ ///
+ /// Role the bot has
+ ///
+ public void InitItemLimitArray(string botRole, Dictionary limitCount)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Check if an item has reached its bot-specific spawn limit
+ ///
+ /// Item we check to see if its reached spawn limit
+ /// Bot type
+ ///
+ /// true if item has reached spawn limit
+ public bool ItemHasReachedSpawnLimit(TemplateItem itemTemplate, string botRole, ItemSpawnLimitSettings itemSpawnLimits)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Randomise the stack size of a money object, uses different values for pmc or scavs
+ ///
+ /// Role bot has that has money stack
+ /// item details from db
+ /// Money item to randomise
+ public void RandomiseMoneyStackSize(string botRole, TemplateItem itemTemplate, Item moneyItem)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Randomise the size of an ammo stack
+ ///
+ /// Is ammo on a PMC bot
+ /// item details from db
+ /// Ammo item to randomise
+ public void RandomiseAmmoStackSize(bool isPmc, TemplateItem itemTemplate, Item ammoItem)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get spawn limits for a specific bot type from bot.json config
+ /// If no limit found for a non pmc bot, fall back to defaults
+ ///
+ /// what role does the bot have
+ /// Dictionary of tplIds and limit
+ public Dictionary GetItemSpawnLimitsForBotType(string botRole)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get the parentId or tplId of item inside spawnLimits object if it exists
+ ///
+ /// item we want to look for in spawn limits
+ /// Limits to check for item
+ /// id as string, otherwise undefined
+ public string? GetMatchingIdFromSpawnLimits(TemplateItem itemTemplate, Dictionary spawnLimits)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
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/WeaponGen/BotInventoryGenerator.cs b/Core/Generators/WeaponGen/BotInventoryGenerator.cs
new file mode 100644
index 00000000..7884a6de
--- /dev/null
+++ b/Core/Generators/WeaponGen/BotInventoryGenerator.cs
@@ -0,0 +1,145 @@
+using Core.Models.Eft.Common.Tables;
+using Core.Models.Eft.Match;
+using Core.Models.Spt.Bots;
+using Core.Models.Spt.Config;
+using Equipment = Core.Models.Eft.Common.Tables.Equipment;
+
+namespace Core.Generators.WeaponGen;
+
+public class BotInventoryGenerator
+{
+ private BotConfig _botConfig;
+
+ public BotInventoryGenerator()
+ {
+
+ }
+
+ ///
+ /// Add equipment/weapons/loot to bot
+ ///
+ /// Session id
+ /// Base json db file for the bot having its loot generated
+ /// Role bot has (assault/pmcBot)
+ /// Is bot being converted into a pmc
+ /// Level of bot being generated
+ /// Game version for bot, only really applies for PMCs
+ /// PmcInventory object with equipment/weapons/loot
+ public BotBaseInventory generateInventory(string sessionId, BotType botJsonTemplate, string botRole, bool isPmc, int botLevel, string chosenGameVersion)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Create a pmcInventory object with all the base/generic items needed
+ ///
+ /// PmcInventory object
+ public BotBaseInventory GenerateInventoryBase()
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Add equipment to a bot
+ ///
+ /// Session id
+ /// bot/x.json data from db
+ /// Chances items will be added to bot
+ /// Role bot has (assault/pmcBot)
+ /// Inventory to add equipment to
+ /// Level of bot
+ /// Game version for bot, only really applies for PMCs
+ /// RadiConfig
+ public void GenerateAndAddEquipmentToBot(string sessionId, BotBaseInventory templateInventory, Chances wornItemChances, string botRole,
+ BotBaseInventory botInventory, int botLevel, string chosenGameVersion, GetRaidConfigurationRequestData raidConfig)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Remove non-armored rigs from parameter data
+ ///
+ /// Equpiment to filter TacticalVest of
+ /// Role of bot vests are being filtered for
+ public void FilterRigsToThoseWithProtection(Equipment templateEquipment, string botRole)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Remove armored rigs from parameter data
+ ///
+ /// Equpiment to filter TacticalVest of
+ /// Role of bot vests are being filtered for
+ /// Should the function return all rigs when 0 unarmored are found
+ public void FilterRigsTothoseWithoutProtection(Equipment templateEquipment, string botRole, bool allowEmptyRequest = false)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Add a piece of equipment with mods to inventory from the provided pools
+ ///
+ /// Values to adjust how item is chosen and added to bot
+ /// true when item added
+ public bool GenerateEquipment(GenerateEquipmentProperties settings)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Get all possible mods for item and filter down based on equipment blacklist from bot.json config
+ ///
+ /// Item mod pool is being retrieved and filtered
+ /// Blacklist to filter mod pool with
+ /// Filtered pool of mods
+ public Dictionary> GetFilteredDynamicModsForItem(string itemTpl, Dictionary> equipmentBlacklist)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Work out what weapons bot should have equipped and add them to bot inventory
+ ///
+ /// bot/x.json data from db
+ /// Chances bot can have equipment equipped
+ /// Session id
+ /// Inventory to add weapons to
+ /// assault/pmcBot/bossTagilla etc
+ /// Is the bot being generated as a pmc
+ /// Limits for items the bot can have
+ /// level of bot having weapon generated
+ public void GenerateAndAddWeaponsToBot(BotBaseInventory templateInventory, Chances equipmentChances, string sessionId, BotBaseInventory botInventory, string botRole,
+ bool isPmc, Generation itemGenerationLimitsMinMax, int botLevel)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Calculate if the bot should have weapons in Primary/Secondary/Holster slots
+ ///
+ /// Chances bot has certain equipment
+ /// What slots bot should have weapons generated for
+ public object GetDesiredWeaponsForBot(Chances equipmentChances) // TODO: Type fuckery { slot: EquipmentSlots; shouldSpawn: boolean }[]
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Add weapon + spare mags/ammo to bots inventory
+ ///
+ /// Session id
+ /// Weapon slot being generated
+ /// bot/x.json data from db
+ /// Inventory to add weapon+mags/ammo to
+ /// Chances bot can have equipment equipped
+ /// assault/pmcBot/bossTagilla etc
+ /// Is the bot being generated as a pmc
+ ///
+ ///
+ public void AddWeaponAndMagazineToInventory(string sessionId, object weaponSlot, BotBaseInventory templateInventory, BotBaseInventory botInventory, Chances equipmentChances, string botRole,
+ bool isPmc, Generation itemGenerationWeights, int botLevel)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/Core/Generators/WeaponGen/Implementations/InventoryMagGen.cs b/Core/Generators/WeaponGen/Implementations/InventoryMagGen.cs
new file mode 100644
index 00000000..5866e62b
--- /dev/null
+++ b/Core/Generators/WeaponGen/Implementations/InventoryMagGen.cs
@@ -0,0 +1,42 @@
+using Core.Models.Eft.Common.Tables;
+
+namespace Core.Generators.WeaponGen.Implementations;
+
+public class InventoryMagGen
+{
+ private GenerationData _magCounts;
+ private TemplateItem _magazineTemplate;
+ private TemplateItem _weaponTemplate;
+ private TemplateItem _ammoTemplate;
+ private BotBaseInventory _pmcInventory;
+
+ public InventoryMagGen()
+ {
+
+ }
+
+ public GenerationData GetMagCount()
+ {
+ return _magCounts;
+ }
+
+ public TemplateItem GetMagazineTemplate()
+ {
+ return _magazineTemplate;
+ }
+
+ public TemplateItem GetWeaponTemplate()
+ {
+ return _weaponTemplate;
+ }
+
+ public TemplateItem GetAmmoTemplate()
+ {
+ return _ammoTemplate;
+ }
+
+ public BotBaseInventory GetPmcInventory()
+ {
+ return _pmcInventory;
+ }
+}
\ 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/Eft/Bot/RandomisedBotLevelResult.cs b/Core/Models/Eft/Bot/RandomisedBotLevelResult.cs
new file mode 100644
index 00000000..b10697b0
--- /dev/null
+++ b/Core/Models/Eft/Bot/RandomisedBotLevelResult.cs
@@ -0,0 +1,12 @@
+using System.Text.Json.Serialization;
+
+namespace Core.Models.Eft.Bot;
+
+public class RandomisedBotLevelResult
+{
+ [JsonPropertyName("level")]
+ public int Level { get; set; }
+
+ [JsonPropertyName("exp")]
+ public int Exp { get; set; }
+}
\ No newline at end of file
diff --git a/Core/Models/Enums/EquipmentSlots.cs b/Core/Models/Enums/EquipmentSlots.cs
new file mode 100644
index 00000000..8d736c11
--- /dev/null
+++ b/Core/Models/Enums/EquipmentSlots.cs
@@ -0,0 +1,19 @@
+namespace Core.Models.Enums;
+
+public enum EquipmentSlots
+{
+ HEADWEAR,
+ EARPIECE,
+ FACE_COVER,
+ ARMOR_VEST,
+ EYEWEAR,
+ ARM_BAND,
+ TACTICAL_VEST,
+ POCKETS,
+ BACKPACK,
+ SECURED_CONTAINER,
+ FIRST_PRIMARY_WEAPON,
+ SECOND_PRIMARY_WEAPON,
+ HOLSTER,
+ SCABBARD
+}
\ 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; }