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; }