Move generators to primary ctor

This commit is contained in:
CWX
2025-01-18 19:54:33 +00:00
parent 5c5a42b535
commit 7e7c1d1aaa
22 changed files with 816 additions and 1088 deletions
+46 -86
View File
@@ -15,75 +15,29 @@ using Core.Utils.Cloners;
namespace Core.Generators;
[Injectable]
public class BotEquipmentModGenerator
public class BotEquipmentModGenerator(
ISptLogger<BotEquipmentModGenerator> _logger,
HashUtil _hashUtil,
RandomUtil _randomUtil,
ProbabilityHelper _probabilityHelper,
DatabaseService _databaseService,
ItemHelper _itemHelper,
BotEquipmentFilterService _botEquipmentFilterService,
ItemFilterService _itemFilterService,
ProfileHelper _profileHelper,
BotWeaponModLimitService _botWeaponModLimitService,
BotHelper _botHelper,
BotGeneratorHelper _botGeneratorHelper,
BotWeaponGeneratorHelper _botWeaponGeneratorHelper,
WeightedRandomHelper _weightedRandomHelper,
PresetHelper _presetHelper,
LocalisationService _localisationService,
BotEquipmentModPoolService _botEquipmentModPoolService,
ConfigServer _configServer,
ICloner _cloner
)
{
private readonly ISptLogger<BotEquipmentModGenerator> _logger;
private readonly HashUtil _hashUtil;
private readonly RandomUtil _randomUtil;
private readonly ProbabilityHelper _probabilityHelper;
private readonly DatabaseService _databaseService;
private readonly ItemHelper _itemHelper;
private readonly BotEquipmentFilterService _botEquipmentFilterService;
private readonly ItemFilterService _itemFilterService;
private readonly ProfileHelper _profileHelper;
private readonly BotWeaponModLimitService _botWeaponModLimitService;
private readonly BotHelper _botHelper;
private readonly BotGeneratorHelper _botGeneratorHelper;
private readonly BotWeaponGeneratorHelper _botWeaponGeneratorHelper;
private readonly WeightedRandomHelper _weightedRandomHelper;
private readonly PresetHelper _presetHelper;
private readonly LocalisationService _localisationService;
private readonly BotEquipmentModPoolService _botEquipmentModPoolService;
private readonly ConfigServer _configServer;
private readonly ICloner _cloner;
private BotConfig _botConfig;
public BotEquipmentModGenerator
(
ISptLogger<BotEquipmentModGenerator> logger,
HashUtil hashUtil,
RandomUtil randomUtil,
ProbabilityHelper probabilityHelper,
DatabaseService databaseService,
ItemHelper itemHelper,
BotEquipmentFilterService botEquipmentFilterService,
ItemFilterService itemFilterService,
ProfileHelper profileHelper,
BotWeaponModLimitService botWeaponModLimitService,
BotHelper botHelper,
BotGeneratorHelper botGeneratorHelper,
BotWeaponGeneratorHelper botWeaponGeneratorHelper,
WeightedRandomHelper weightedRandomHelper,
PresetHelper presetHelper,
LocalisationService localisationService,
BotEquipmentModPoolService botEquipmentModPoolService,
ConfigServer configServer,
ICloner cloner
)
{
_logger = logger;
_hashUtil = hashUtil;
_randomUtil = randomUtil;
_probabilityHelper = probabilityHelper;
_databaseService = databaseService;
_itemHelper = itemHelper;
_botEquipmentFilterService = botEquipmentFilterService;
_itemFilterService = itemFilterService;
_profileHelper = profileHelper;
_botWeaponModLimitService = botWeaponModLimitService;
_botHelper = botHelper;
_botGeneratorHelper = botGeneratorHelper;
_botWeaponGeneratorHelper = botWeaponGeneratorHelper;
_weightedRandomHelper = weightedRandomHelper;
_presetHelper = presetHelper;
_localisationService = localisationService;
_botEquipmentModPoolService = botEquipmentModPoolService;
_configServer = configServer;
_cloner = cloner;
_botConfig = _configServer.GetConfig<BotConfig>();
}
protected BotConfig _botConfig = _configServer.GetConfig<BotConfig>();
/// <summary>
/// Check mods are compatible and add to array
@@ -174,7 +128,9 @@ public class BotEquipmentModGenerator
switch (plateSlotFilteringOutcome.Result)
{
case Result.UNKNOWN_FAILURE or Result.NO_DEFAULT_FILTER:
_logger.Debug($"Plate slot: {modSlotName} selection for armor: {parentTemplate.Id} failed: {plateSlotFilteringOutcome.Result}, skipping");
_logger.Debug(
$"Plate slot: {modSlotName} selection for armor: {parentTemplate.Id} failed: {plateSlotFilteringOutcome.Result}, skipping"
);
continue;
case Result.LACKS_PLATE_WEIGHTS:
@@ -275,7 +231,8 @@ public class BotEquipmentModGenerator
* @param modSlot front/back
* @returns Tpl of plate
*/
protected string GetDefaultPlateTpl(TemplateItem armorItem, string modSlot ) {
protected string GetDefaultPlateTpl(TemplateItem armorItem, string modSlot)
{
var relatedItemDbModSlot = armorItem.Properties.Slots?.FirstOrDefault(slot => slot.Name.ToLower() == modSlot);
return relatedItemDbModSlot?.Props.Filters[0].Plate;
@@ -287,20 +244,21 @@ public class BotEquipmentModGenerator
* @param modSlot front/back
* @returns Armor IItem
*/
protected Item GetDefaultPresetArmorSlot(string armorItemTpl, string modSlot) {
protected Item GetDefaultPresetArmorSlot(string armorItemTpl, string modSlot)
{
var defaultPreset = _presetHelper.GetDefaultPreset(armorItemTpl);
return defaultPreset?.Items.FirstOrDefault((item) => item.SlotId?.ToLower() == modSlot);
}
/// <summary>
/// Add mods to a weapon using the provided mod pool
/// </summary>
/// <param name="sessionId">Session id</param>
/// <param name="request">Data used to generate the weapon</param>
/// <returns>Weapon + mods array</returns>
public List<Item> GenerateModsForWeapon(string sessionId, GenerateWeaponRequest request)
/// <summary>
/// Add mods to a weapon using the provided mod pool
/// </summary>
/// <param name="sessionId">Session id</param>
/// <param name="request">Data used to generate the weapon</param>
/// <returns>Weapon + mods array</returns>
public List<Item> GenerateModsForWeapon(string sessionId, GenerateWeaponRequest request)
{
var pmcProfile = _profileHelper.GetPmcProfile(sessionId);
@@ -1399,14 +1357,16 @@ public List<Item> GenerateModsForWeapon(string sessionId, GenerateWeaponRequest
var filteredMods = FilterModsByBlacklist(supportedSubMods, botEquipBlacklist, desiredSlotName);
if (!filteredMods.Any())
{
_logger.Warning(_localisationService
.GetText("bot-unable_to_filter_mods_all_blacklisted",
new
{
slotName = desiredSlotObject.Name,
itemName = modTemplate.Name,
}
)
_logger.Warning(
_localisationService
.GetText(
"bot-unable_to_filter_mods_all_blacklisted",
new
{
slotName = desiredSlotObject.Name,
itemName = modTemplate.Name,
}
)
);
}
+90 -106
View File
@@ -18,69 +18,28 @@ using BodyPart = Core.Models.Eft.Common.Tables.BodyPart;
namespace Core.Generators;
[Injectable]
public class BotGenerator
public class BotGenerator(
ISptLogger<BotGenerator> _logger,
HashUtil _hashUtil,
RandomUtil _randomUtil,
TimeUtil _timeUtil,
ProfileHelper _profileHelper,
DatabaseService _databaseService,
BotInventoryGenerator _botInventoryGenerator,
BotLevelGenerator _botLevelGenerator,
BotEquipmentFilterService _botEquipmentFilterService,
WeightedRandomHelper _weightedRandomHelper,
BotHelper _botHelper,
BotGeneratorHelper _botGeneratorHelper,
SeasonalEventService _seasonalEventService,
ItemFilterService _itemFilterService,
BotNameService _botNameService,
ConfigServer _configServer,
ICloner _cloner
)
{
protected ISptLogger<BotGenerator> _logger;
protected HashUtil _hashUtil;
protected RandomUtil _randomUtil;
protected TimeUtil _timeUtil;
protected ProfileHelper _profileHelper;
protected DatabaseService _databaseService;
protected BotInventoryGenerator _botInventoryGenerator;
protected BotLevelGenerator _botLevelGenerator;
protected BotEquipmentFilterService _botEquipmentFilterService;
protected WeightedRandomHelper _weightedRandomHelper;
protected BotHelper _botHelper;
protected BotGeneratorHelper _botGeneratorHelper;
protected SeasonalEventService _seasonalEventService;
protected ItemFilterService _itemFilterService;
protected BotNameService _botNameService;
protected ConfigServer _configServer;
protected ICloner _cloner;
private BotConfig _botConfig;
private PmcConfig _pmcConfig;
public BotGenerator(
ISptLogger<BotGenerator> logger,
HashUtil hashUtil,
RandomUtil randomUtil,
TimeUtil timeUtil,
ProfileHelper profileHelper,
DatabaseService databaseService,
BotInventoryGenerator botInventoryGenerator,
BotLevelGenerator botLevelGenerator,
BotEquipmentFilterService botEquipmentFilterService,
WeightedRandomHelper weightedRandomHelper,
BotHelper botHelper,
BotGeneratorHelper botGeneratorHelper,
SeasonalEventService seasonalEventService,
ItemFilterService itemFilterService,
BotNameService botNameService,
ConfigServer configServer,
ICloner cloner
)
{
_logger = logger;
_hashUtil = hashUtil;
_randomUtil = randomUtil;
_timeUtil = timeUtil;
_profileHelper = profileHelper;
_databaseService = databaseService;
_botInventoryGenerator = botInventoryGenerator;
_botLevelGenerator = botLevelGenerator;
_botEquipmentFilterService = botEquipmentFilterService;
_weightedRandomHelper = weightedRandomHelper;
_botHelper = botHelper;
_botGeneratorHelper = botGeneratorHelper;
_seasonalEventService = seasonalEventService;
_itemFilterService = itemFilterService;
_botNameService = botNameService;
_configServer = configServer;
_cloner = cloner;
_botConfig = _configServer.GetConfig<BotConfig>();
_pmcConfig = _configServer.GetConfig<PmcConfig>();
}
protected BotConfig _botConfig = _configServer.GetConfig<BotConfig>();
protected PmcConfig _pmcConfig = _configServer.GetConfig<PmcConfig>();
/// <summary>
/// Generate a player scav bot object
@@ -223,7 +182,8 @@ public class BotGenerator
var botLevel = _botLevelGenerator.GenerateBotLevel(
botJsonTemplate.BotExperience.Level,
botGenerationDetails,
bot);
bot
);
// Only filter bot equipment, never players
if (!botGenerationDetails.IsPlayerScav.GetValueOrDefault(false))
@@ -232,14 +192,16 @@ public class BotGenerator
sessionId,
botJsonTemplate,
botLevel.Level.Value,
botGenerationDetails);
botGenerationDetails
);
}
bot.Info.Nickname = _botNameService.GenerateUniqueBotNickname(
botJsonTemplate,
botGenerationDetails,
botRoleLowercase,
_botConfig.BotRolesThatMustHaveUniqueName);
_botConfig.BotRolesThatMustHaveUniqueName
);
bot.Info.LowerNickname = bot.Info.Nickname.ToLower();
// Only run when generating a 'fake' playerscav, not actual player scav
@@ -256,7 +218,8 @@ public class BotGenerator
{
_seasonalEventService.RemoveChristmasItemsFromBotInventory(
botJsonTemplate.BotInventory,
botGenerationDetails.Role);
botGenerationDetails.Role
);
}
}
@@ -273,15 +236,18 @@ public class BotGenerator
bot.Info.Settings.Experience = GetExperienceRewardForKillByDifficulty(
botJsonTemplate.BotExperience.Reward,
botGenerationDetails.BotDifficulty,
botGenerationDetails.Role);
botGenerationDetails.Role
);
bot.Info.Settings.StandingForKill = GetStandingChangeForKillByDifficulty(
botJsonTemplate.BotExperience.StandingForKill,
botGenerationDetails.BotDifficulty,
botGenerationDetails.Role);
botGenerationDetails.Role
);
bot.Info.Settings.AggressorBonus = GetAgressorBonusByDifficulty(
botJsonTemplate.BotExperience.StandingForKill,
botGenerationDetails.BotDifficulty,
botGenerationDetails.Role);
botGenerationDetails.Role
);
bot.Info.Settings.UseSimpleAnimator = botJsonTemplate.BotExperience.UseSimpleAnimator ?? false;
bot.Info.Voice = _weightedRandomHelper.GetWeightedValue(botJsonTemplate.BotAppearance.Voice);
bot.Health = GenerateHealth(botJsonTemplate.BotHealth, botGenerationDetails.IsPlayerScav.GetValueOrDefault(false));
@@ -309,7 +275,8 @@ public class BotGenerator
botRoleLowercase,
botGenerationDetails.IsPmc.GetValueOrDefault(false),
botLevel.Level.Value,
bot.Info.GameVersion);
bot.Info.GameVersion
);
if (_botConfig.BotRolesWithDogTags.Contains(botRoleLowercase))
{
@@ -408,7 +375,8 @@ public class BotGenerator
{
var blacklist = _botEquipmentFilterService.GetBotEquipmentBlacklist(
_botGeneratorHelper.GetBotEquipmentRole(botGenerationDetails.Role),
botGenerationDetails.PlayerLevel.GetValueOrDefault(1));
botGenerationDetails.PlayerLevel.GetValueOrDefault(1)
);
if (blacklist?.Gear is null)
{
@@ -683,31 +651,35 @@ public class BotGenerator
if (skills is null)
return [];
return skills.Select(kvp =>
{
// Get skill from dict, skip if not found
var skill = kvp.Value;
if (skill == null)
{
return null;
}
return skills.Select(
kvp =>
{
// Get skill from dict, skip if not found
var skill = kvp.Value;
if (skill == null)
{
return null;
}
// All skills have id and progress props
var skillToAdd = new BaseSkill
{
Id = kvp.Key,
Progress = _randomUtil.GetInt((int)skill.Min, (int)skill.Max)
};
// All skills have id and progress props
var skillToAdd = new BaseSkill
{
Id = kvp.Key,
Progress = _randomUtil.GetInt((int)skill.Min, (int)skill.Max)
};
// Common skills have additional props
if (isCommonSkills)
{
((Common)skillToAdd).PointsEarnedDuringSession = 0;
((Common)skillToAdd).LastAccess = 0;
}
// Common skills have additional props
if (isCommonSkills)
{
((Common)skillToAdd).PointsEarnedDuringSession = 0;
((Common)skillToAdd).LastAccess = 0;
}
return skillToAdd;
}).Where(baseSkill => baseSkill != null).ToList();
return skillToAdd;
}
)
.Where(baseSkill => baseSkill != null)
.ToList();
}
/// <summary>
@@ -718,7 +690,7 @@ public class BotGenerator
public void AddIdsToBot(BotBase bot)
{
var botId = _hashUtil.Generate();
bot.Id = botId;
bot.Aid = _hashUtil.GenerateAccountId();
}
@@ -732,9 +704,11 @@ public class BotGenerator
{
var newInventoryItemId = _hashUtil.Generate();
foreach (var item in profile.Inventory.Items) {
foreach (var item in profile.Inventory.Items)
{
// Root item found, update its _id value to newly generated id
if (item.Template == ItemTpl.INVENTORY_DEFAULT) {
if (item.Template == ItemTpl.INVENTORY_DEFAULT)
{
item.Id = newInventoryItemId;
continue;
@@ -742,12 +716,14 @@ public class BotGenerator
// Optimisation - skip items without a parentId
// They are never linked to root inventory item + we already handled root item above
if (item.ParentId is null) {
if (item.ParentId is null)
{
continue;
}
// Item is a child of root inventory item, update its parentId value to newly generated id
if (item.ParentId == profile.Inventory.Equipment) {
if (item.ParentId == profile.Inventory.Equipment)
{
item.ParentId = newInventoryItemId;
}
}
@@ -766,7 +742,8 @@ public class BotGenerator
public string SetRandomisedGameVersionAndCategory(Info botInfo)
{
// Special case
if (botInfo.Nickname?.ToLower() == "nikita") {
if (botInfo.Nickname?.ToLower() == "nikita")
{
botInfo.GameVersion = GameEditions.UNHEARD;
botInfo.MemberCategory = MemberCategory.DEVELOPER;
@@ -777,7 +754,8 @@ public class BotGenerator
botInfo.GameVersion = _weightedRandomHelper.GetWeightedValue(_pmcConfig.GameVersionWeight);
// Choose appropriate member category value
switch (botInfo.GameVersion) {
switch (botInfo.GameVersion)
{
case GameEditions.EDGE_OF_DARKNESS:
botInfo.MemberCategory = MemberCategory.UNIQUE_ID;
break;
@@ -803,12 +781,14 @@ public class BotGenerator
/// <returns></returns>
public void AddDogtagToBot(BotBase bot)
{
Item inventoryItem = new () {
Item inventoryItem = new()
{
Id = _hashUtil.Generate(),
Template = GetDogtagTplByGameVersionAndSide(bot.Info.Side, bot.Info.GameVersion),
ParentId = bot.Inventory.Equipment,
SlotId = "Dogtag",
Upd = new () {
Upd = new()
{
SpawnedInSession = true,
},
};
@@ -824,8 +804,10 @@ public class BotGenerator
/// <returns>item tpl</returns>
public string GetDogtagTplByGameVersionAndSide(string side, string gameVersion)
{
if (side.ToLower() == "usec") {
switch (gameVersion) {
if (side.ToLower() == "usec")
{
switch (gameVersion)
{
case GameEditions.EDGE_OF_DARKNESS:
return ItemTpl.BARTER_DOGTAG_USEC_EOD;
case GameEditions.UNHEARD:
@@ -835,7 +817,8 @@ public class BotGenerator
}
}
switch (gameVersion) {
switch (gameVersion)
{
case GameEditions.EDGE_OF_DARKNESS:
return ItemTpl.BARTER_DOGTAG_BEAR_EOD;
case GameEditions.UNHEARD:
@@ -851,7 +834,8 @@ public class BotGenerator
/// <param name="bot">Pmc object to adjust</param>
public void SetPmcPocketsByGameVersion(BotBase bot)
{
if (bot.Info.GameVersion == GameEditions.UNHEARD) {
if (bot.Info.GameVersion == GameEditions.UNHEARD)
{
var pockets = bot.Inventory.Items.FirstOrDefault((item) => item.SlotId == "Pockets");
pockets.Template = ItemTpl.POCKETS_1X4_TUE;
}
+143 -160
View File
@@ -16,71 +16,28 @@ using Equipment = Core.Models.Eft.Common.Tables.Equipment;
namespace Core.Generators;
[Injectable]
public class BotInventoryGenerator
public class BotInventoryGenerator(
ISptLogger<BotInventoryGenerator> _logger,
HashUtil _hashUtil,
RandomUtil _randomUtil,
DatabaseService _databaseService,
ApplicationContext _applicationContext,
BotWeaponGenerator _botWeaponGenerator,
BotLootGenerator _botLootGenerator,
BotGeneratorHelper _botGeneratorHelper,
ProfileHelper _profileHelper,
BotHelper _botHelper,
WeightedRandomHelper _weightedRandomHelper,
ItemHelper _itemHelper,
WeatherHelper _weatherHelper,
LocalisationService _localisationService,
BotEquipmentFilterService _botEquipmentFilterService,
BotEquipmentModPoolService _botEquipmentModPoolService,
BotEquipmentModGenerator _botEquipmentModGenerator,
ConfigServer _configServer
)
{
protected ISptLogger<BotInventoryGenerator> _logger;
protected HashUtil _hashUtil;
protected RandomUtil _randomUtil;
protected DatabaseService _databaseService;
protected ApplicationContext _applicationContext;
protected BotWeaponGenerator _botWeaponGenerator;
protected BotLootGenerator _botLootGenerator;
protected BotGeneratorHelper _botGeneratorHelper;
protected ProfileHelper _profileHelper;
protected BotHelper _botHelper;
protected WeightedRandomHelper _weightedRandomHelper;
protected ItemHelper _itemHelper;
protected WeatherHelper _weatherHelper;
protected LocalisationService _localisationService;
protected BotEquipmentFilterService _botEquipmentFilterService;
protected BotEquipmentModPoolService _botEquipmentModPoolService;
protected BotEquipmentModGenerator _botEquipmentModGenerator;
protected ConfigServer _configServer;
private BotConfig _botConfig;
public BotInventoryGenerator(
ISptLogger<BotInventoryGenerator> logger,
HashUtil hashUtil,
RandomUtil randomUtil,
DatabaseService databaseService,
ApplicationContext applicationContext,
BotWeaponGenerator botWeaponGenerator,
BotLootGenerator botLootGenerator,
BotGeneratorHelper botGeneratorHelper,
ProfileHelper profileHelper,
BotHelper botHelper,
WeightedRandomHelper weightedRandomHelper,
ItemHelper itemHelper,
WeatherHelper weatherHelper,
LocalisationService localisationService,
BotEquipmentFilterService botEquipmentFilterService,
BotEquipmentModPoolService botEquipmentModPoolService,
BotEquipmentModGenerator botEquipmentModGenerator,
ConfigServer configServer
)
{
_logger = logger;
_hashUtil = hashUtil;
_randomUtil = randomUtil;
_databaseService = databaseService;
_applicationContext = applicationContext;
_botWeaponGenerator = botWeaponGenerator;
_botLootGenerator = botLootGenerator;
_botGeneratorHelper = botGeneratorHelper;
_profileHelper = profileHelper;
_botHelper = botHelper;
_weightedRandomHelper = weightedRandomHelper;
_itemHelper = itemHelper;
_weatherHelper = weatherHelper;
_localisationService = localisationService;
_botEquipmentFilterService = botEquipmentFilterService;
_botEquipmentModPoolService = botEquipmentModPoolService;
_botEquipmentModGenerator = botEquipmentModGenerator;
_configServer = configServer;
_botConfig = _configServer.GetConfig<BotConfig>();
}
private BotConfig _botConfig = _configServer.GetConfig<BotConfig>();
/// <summary>
/// Add equipment/weapons/loot to bot
@@ -114,7 +71,8 @@ public class BotInventoryGenerator
botInventory,
botLevel,
chosenGameVersion,
raidConfig);
raidConfig
);
// Roll weapon spawns (primary/secondary/holster) and generate a weapon for each roll that passed
GenerateAndAddWeaponsToBot(
@@ -125,7 +83,8 @@ public class BotInventoryGenerator
botRole,
isPmc,
itemGenerationLimitsMinMax,
botLevel);
botLevel
);
// Pick loot and add to bots containers (rig/backpack/pockets/secure)
_botLootGenerator.GenerateLoot(sessionId, botJsonTemplate, isPmc, botRole, botInventory, botLevel);
@@ -209,7 +168,9 @@ public class BotInventoryGenerator
{
// Never let mod chance go outside of 0 - 100
randomistionDetails.EquipmentMods[equipmentSlotKvP.Key] = Math.Min(
Math.Max(randomistionDetails.EquipmentMods[equipmentSlotKvP.Key] + equipmentSlotKvP.Value, 0), 100);
Math.Max(randomistionDetails.EquipmentMods[equipmentSlotKvP.Key] + equipmentSlotKvP.Value, 0),
100
);
}
}
@@ -230,10 +191,48 @@ public class BotInventoryGenerator
continue;
}
GenerateEquipment(new GenerateEquipmentProperties
GenerateEquipment(
new GenerateEquipmentProperties
{
RootEquipmentSlot = equipmentSlot,
RootEquipmentPool = value,
ModPool = templateInventory.Mods,
SpawnChances = wornItemChances,
BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole },
Inventory = botInventory,
BotEquipmentConfig = botEquipConfig,
RandomisationDetails = randomistionDetails,
GeneratingPlayerLevel = pmcProfile.Info.Level,
}
);
}
// Generate below in specific order
GenerateEquipment(
new GenerateEquipmentProperties
{
RootEquipmentSlot = equipmentSlot,
RootEquipmentPool = value,
RootEquipmentSlot = EquipmentSlots.Pockets,
// Unheard profiles have unique sized pockets, TODO - handle this somewhere else in a better way
RootEquipmentPool =
chosenGameVersion == GameEditions.UNHEARD
? new Dictionary<string, double> { [ItemTpl.POCKETS_1X4_TUE] = 1 }
: templateInventory.Equipment[EquipmentSlots.Pockets],
ModPool = templateInventory.Mods,
SpawnChances = wornItemChances,
BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole },
Inventory = botInventory,
BotEquipmentConfig = botEquipConfig,
RandomisationDetails = randomistionDetails,
GenerateModsBlacklist = [ItemTpl.POCKETS_1X4_TUE],
GeneratingPlayerLevel = pmcProfile.Info.Level,
}
);
GenerateEquipment(
new GenerateEquipmentProperties
{
RootEquipmentSlot = EquipmentSlots.FaceCover,
RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.FaceCover],
ModPool = templateInventory.Mods,
SpawnChances = wornItemChances,
BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole },
@@ -241,79 +240,53 @@ public class BotInventoryGenerator
BotEquipmentConfig = botEquipConfig,
RandomisationDetails = randomistionDetails,
GeneratingPlayerLevel = pmcProfile.Info.Level,
});
}
}
);
// Generate below in specific order
GenerateEquipment(new GenerateEquipmentProperties
{
RootEquipmentSlot = EquipmentSlots.Pockets,
// Unheard profiles have unique sized pockets, TODO - handle this somewhere else in a better way
RootEquipmentPool =
chosenGameVersion == GameEditions.UNHEARD
? new Dictionary<string, double> { [ItemTpl.POCKETS_1X4_TUE] = 1 }
: templateInventory.Equipment[EquipmentSlots.Pockets],
ModPool = templateInventory.Mods,
SpawnChances = wornItemChances,
BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole },
Inventory = botInventory,
BotEquipmentConfig = botEquipConfig,
RandomisationDetails = randomistionDetails,
GenerateModsBlacklist = [ItemTpl.POCKETS_1X4_TUE],
GeneratingPlayerLevel = pmcProfile.Info.Level,
});
GenerateEquipment(
new GenerateEquipmentProperties
{
RootEquipmentSlot = EquipmentSlots.Headwear,
RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.Headwear],
ModPool = templateInventory.Mods,
SpawnChances = wornItemChances,
BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole },
Inventory = botInventory,
BotEquipmentConfig = botEquipConfig,
RandomisationDetails = randomistionDetails,
GeneratingPlayerLevel = pmcProfile.Info.Level,
}
);
GenerateEquipment(new GenerateEquipmentProperties
{
RootEquipmentSlot = EquipmentSlots.FaceCover,
RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.FaceCover],
ModPool = templateInventory.Mods,
SpawnChances = wornItemChances,
BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole },
Inventory = botInventory,
BotEquipmentConfig = botEquipConfig,
RandomisationDetails = randomistionDetails,
GeneratingPlayerLevel = pmcProfile.Info.Level,
});
GenerateEquipment(
new GenerateEquipmentProperties
{
RootEquipmentSlot = EquipmentSlots.Earpiece,
RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.Earpiece],
ModPool = templateInventory.Mods,
SpawnChances = wornItemChances,
BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole },
Inventory = botInventory,
BotEquipmentConfig = botEquipConfig,
RandomisationDetails = randomistionDetails,
GeneratingPlayerLevel = pmcProfile.Info.Level,
}
);
GenerateEquipment(new GenerateEquipmentProperties
{
RootEquipmentSlot = EquipmentSlots.Headwear,
RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.Headwear],
ModPool = templateInventory.Mods,
SpawnChances = wornItemChances,
BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole },
Inventory = botInventory,
BotEquipmentConfig = botEquipConfig,
RandomisationDetails = randomistionDetails,
GeneratingPlayerLevel = pmcProfile.Info.Level,
});
GenerateEquipment(new GenerateEquipmentProperties
{
RootEquipmentSlot = EquipmentSlots.Earpiece,
RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.Earpiece],
ModPool = templateInventory.Mods,
SpawnChances = wornItemChances,
BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole },
Inventory = botInventory,
BotEquipmentConfig = botEquipConfig,
RandomisationDetails = randomistionDetails,
GeneratingPlayerLevel = pmcProfile.Info.Level,
});
var hasArmorVest = GenerateEquipment(new GenerateEquipmentProperties
{
RootEquipmentSlot = EquipmentSlots.ArmorVest,
RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.ArmorVest],
ModPool = templateInventory.Mods,
SpawnChances = wornItemChances,
BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole },
Inventory = botInventory,
BotEquipmentConfig = botEquipConfig,
RandomisationDetails = randomistionDetails,
GeneratingPlayerLevel = pmcProfile.Info.Level,
});
var hasArmorVest = GenerateEquipment(
new GenerateEquipmentProperties
{
RootEquipmentSlot = EquipmentSlots.ArmorVest,
RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.ArmorVest],
ModPool = templateInventory.Mods,
SpawnChances = wornItemChances,
BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole },
Inventory = botInventory,
BotEquipmentConfig = botEquipConfig,
RandomisationDetails = randomistionDetails,
GeneratingPlayerLevel = pmcProfile.Info.Level,
}
);
// Bot has no armor vest and flagged to be forced to wear armored rig in this event
if (botEquipConfig.ForceOnlyArmoredRigWhenNoArmor.GetValueOrDefault(false) && !hasArmorVest)
@@ -335,18 +308,20 @@ public class BotInventoryGenerator
wornItemChances.EquipmentChances["TacticalVest"] = 100;
}
GenerateEquipment(new GenerateEquipmentProperties
{
RootEquipmentSlot = EquipmentSlots.Earpiece,
RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.Earpiece],
ModPool = templateInventory.Mods,
SpawnChances = wornItemChances,
BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole },
Inventory = botInventory,
BotEquipmentConfig = botEquipConfig,
RandomisationDetails = randomistionDetails,
GeneratingPlayerLevel = pmcProfile.Info.Level,
});
GenerateEquipment(
new GenerateEquipmentProperties
{
RootEquipmentSlot = EquipmentSlots.Earpiece,
RootEquipmentPool = templateInventory.Equipment[EquipmentSlots.Earpiece],
ModPool = templateInventory.Mods,
SpawnChances = wornItemChances,
BotData = new BotData { Role = botRole, Level = botLevel, EquipmentRole = botEquipmentRole },
Inventory = botInventory,
BotEquipmentConfig = botEquipConfig,
RandomisationDetails = randomistionDetails,
GeneratingPlayerLevel = pmcProfile.Info.Level,
}
);
}
/// <summary>
@@ -356,7 +331,8 @@ public class BotInventoryGenerator
/// <param name="botRole">Role of bot vests are being filtered for</param>
public void FilterRigsToThoseWithProtection(Dictionary<EquipmentSlots, Dictionary<string, double>> templateEquipment, string botRole)
{
var tacVestsWithArmor = templateEquipment[EquipmentSlots.TacticalVest].Where(kvp => _itemHelper.ItemHasSlots(kvp.Key))
var tacVestsWithArmor = templateEquipment[EquipmentSlots.TacticalVest]
.Where(kvp => _itemHelper.ItemHasSlots(kvp.Key))
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
if (!tacVestsWithArmor.Any())
@@ -375,9 +351,11 @@ public class BotInventoryGenerator
/// <param name="templateEquipment">Equipment to filter TacticalVest by</param>
/// <param name="botRole">Role of bot vests are being filtered for</param>
/// <param name="allowEmptyResult">Should the function return all rigs when 0 unarmored are found</param>
public void FilterRigsToThoseWithoutProtection(Dictionary<EquipmentSlots, Dictionary<string, double>> templateEquipment, string botRole, bool allowEmptyResult = true)
public void FilterRigsToThoseWithoutProtection(Dictionary<EquipmentSlots, Dictionary<string, double>> templateEquipment, string botRole,
bool allowEmptyResult = true)
{
var tacVestsWithoutArmor = templateEquipment[EquipmentSlots.TacticalVest].Where(kvp => !_itemHelper.ItemHasSlots(kvp.Key))
var tacVestsWithoutArmor = templateEquipment[EquipmentSlots.TacticalVest]
.Where(kvp => !_itemHelper.ItemHasSlots(kvp.Key))
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
if (!allowEmptyResult && !tacVestsWithoutArmor.Any())
@@ -404,8 +382,12 @@ public class BotInventoryGenerator
if (!spawnChance.HasValue)
{
_logger.Warning(_localisationService.GetText("bot-no_spawn_chance_defined_for_equipment_slot",
settings.RootEquipmentSlot));
_logger.Warning(
_localisationService.GetText(
"bot-no_spawn_chance_defined_for_equipment_slot",
settings.RootEquipmentSlot
)
);
return false;
}
@@ -637,14 +619,15 @@ public class BotInventoryGenerator
isPmc,
botLevel
);
botInventory.Items.AddRange(generatedWeapon.Weapon);
_botWeaponGenerator.AddExtraMagazinesToInventory(
generatedWeapon,
itemGenerationWeights.Items.Magazines,
botInventory,
botRole);
botRole
);
}
}
+10 -20
View File
@@ -11,25 +11,13 @@ using Core.Utils;
namespace Core.Generators;
[Injectable]
public class BotLevelGenerator
public class BotLevelGenerator(
ISptLogger<BotLevelGenerator> _logger,
RandomUtil _randomUtil,
MathUtil _mathUtil,
DatabaseService _databaseService
)
{
protected ISptLogger<BotLevelGenerator> _logger;
protected RandomUtil _randomUtil;
protected MathUtil _mathUtil;
protected DatabaseService _databaseService;
public BotLevelGenerator(
ISptLogger<BotLevelGenerator> logger,
RandomUtil randomUtil,
MathUtil mathUtil,
DatabaseService databaseService)
{
_logger = logger;
_randomUtil = randomUtil;
_mathUtil = mathUtil;
_databaseService = databaseService;
}
/// <summary>
/// Return a randomised bot level and exp value
/// </summary>
@@ -44,8 +32,10 @@ public class BotLevelGenerator
// Get random level based on the exp table.
int exp = 0;
var level = int.Parse(ChooseBotLevel(botLevelRange.Min.Value, botLevelRange.Max.Value, 1, 1.15)
.ToString()); // TODO - nasty double to string to int conversion
var level = int.Parse(
ChooseBotLevel(botLevelRange.Min.Value, botLevelRange.Max.Value, 1, 1.15)
.ToString()
); // TODO - nasty double to string to int conversion
for (var i = 0; i < level; i++)
{
exp += expTable[i].Experience.Value;
+56 -84
View File
@@ -13,63 +13,26 @@ using Core.Utils.Cloners;
namespace Core.Generators;
[Injectable]
public class BotLootGenerator
public class BotLootGenerator(
ISptLogger<BotLootGenerator> _logger,
HashUtil _hashUtil,
RandomUtil _randomUtil,
ItemHelper _itemHelper,
InventoryHelper _inventoryHelper,
DatabaseService _databaseService,
HandbookHelper _handbookHelper,
BotGeneratorHelper _botGeneratorHelper,
BotWeaponGenerator _botWeaponGenerator,
WeightedRandomHelper _weightedRandomHelper,
BotHelper _botHelper,
BotLootCacheService _botLootCacheService,
LocalisationService _localisationService,
ConfigServer _configServer,
ICloner _cloner
)
{
private readonly ISptLogger<BotLootGenerator> _logger;
private readonly HashUtil _hashUtil;
private readonly RandomUtil _randomUtil;
private readonly ItemHelper _itemHelper;
private readonly InventoryHelper _inventoryHelper;
private readonly DatabaseService _databaseService;
private readonly HandbookHelper _handbookHelper;
private readonly BotGeneratorHelper _botGeneratorHelper;
private readonly BotWeaponGenerator _botWeaponGenerator;
private readonly WeightedRandomHelper _weightedRandomHelper;
private readonly BotHelper _botHelper;
private readonly BotLootCacheService _botLootCacheService;
private readonly LocalisationService _localisationService;
private readonly ConfigServer _configServer;
private readonly ICloner _cloner;
private readonly BotConfig _botConfig;
private readonly PmcConfig _pmcConfig;
public BotLootGenerator(
ISptLogger<BotLootGenerator> logger,
HashUtil hashUtil,
RandomUtil randomUtil,
ItemHelper itemHelper,
InventoryHelper inventoryHelper,
DatabaseService databaseService,
HandbookHelper handbookHelper,
BotGeneratorHelper botGeneratorHelper,
BotWeaponGenerator botWeaponGenerator,
WeightedRandomHelper weightedRandomHelper,
BotHelper botHelper,
BotLootCacheService botLootCacheService,
LocalisationService localisationService,
ConfigServer configServer,
ICloner cloner)
{
_logger = logger;
_hashUtil = hashUtil;
_randomUtil = randomUtil;
_itemHelper = itemHelper;
_inventoryHelper = inventoryHelper;
_databaseService = databaseService;
_handbookHelper = handbookHelper;
_botGeneratorHelper = botGeneratorHelper;
_botWeaponGenerator = botWeaponGenerator;
_weightedRandomHelper = weightedRandomHelper;
_botHelper = botHelper;
_botLootCacheService = botLootCacheService;
_localisationService = localisationService;
_configServer = configServer;
_cloner = cloner;
_botConfig = _configServer.GetConfig<BotConfig>();
_pmcConfig = _configServer.GetConfig<PmcConfig>();
}
protected BotConfig _botConfig = _configServer.GetConfig<BotConfig>();
protected PmcConfig _pmcConfig = _configServer.GetConfig<PmcConfig>();
/// <summary>
///
@@ -361,13 +324,12 @@ public class BotLootGenerator
{
// TODO - extend to other bot types
if (!isPmc) return null;
var matchingValue = _pmcConfig?.LootItemLimitsRub?.FirstOrDefault(
minMaxValue => botLevel >= minMaxValue.Min && botLevel <= minMaxValue.Max
);
return matchingValue;
}
/// <summary>
@@ -380,12 +342,11 @@ public class BotLootGenerator
private double? GetBackpackRoubleTotalByLevel(int botLevel, bool isPmc)
{
if (!isPmc) return 0;
var matchingValue = _pmcConfig.MaxBackpackLootTotalRub.FirstOrDefault(
(minMaxValue) => botLevel >= minMaxValue.Min && botLevel <= minMaxValue.Max
);
return matchingValue?.Value;
}
/// <summary>
@@ -471,9 +432,9 @@ public class BotLootGenerator
{
// Loot pool has items
var poolSize = pool.Count;
if (poolSize <= 0) return;
double currentTotalRub = 0;
var fitItemIntoContainerAttempts = 0;
@@ -487,7 +448,7 @@ public class BotLootGenerator
var weightedItemTpl = _weightedRandomHelper.GetWeightedValue<string>(pool);
var (key, itemToAddTemplate) = _itemHelper.GetItem(weightedItemTpl);
if (!key)
{
_logger.Warning($"Unable to process item tpl: {weightedItemTpl} for slots: {equipmentSlots} on bot: {botRole}");
@@ -628,7 +589,6 @@ public class BotLootGenerator
var chosenStackCount = _weightedRandomHelper.GetWeightedValue<string>(_botConfig.WalletLoot.StackSizeWeight);
List<Item> items =
[
new Item
{
Id = _hashUtil.Generate(),
@@ -639,8 +599,6 @@ public class BotLootGenerator
StackObjectsCount = double.Parse(chosenStackCount)
}
}
];
result.Add(items);
}
@@ -773,18 +731,21 @@ public class BotLootGenerator
private bool ItemHasReachedSpawnLimit(TemplateItem? itemTemplate, string botRole, ItemSpawnLimitSettings? itemSpawnLimits)
{
// PMCs and scavs have different sections of bot config for spawn limits
if (itemSpawnLimits is not null && itemSpawnLimits.GlobalLimits?.Count == 0) {
if (itemSpawnLimits is not null && itemSpawnLimits.GlobalLimits?.Count == 0)
{
// No items found in spawn limit, drop out
return false;
}
// No spawn limits, skipping
if (itemSpawnLimits is null) {
if (itemSpawnLimits is null)
{
return false;
}
var idToCheckFor = GetMatchingIdFromSpawnLimits(itemTemplate, itemSpawnLimits.GlobalLimits);
if (idToCheckFor is null) {
if (idToCheckFor is null)
{
// ParentId or tplid not found in spawnLimits, not a spawn limited item, skip
return false;
}
@@ -793,15 +754,21 @@ public class BotLootGenerator
itemSpawnLimits.CurrentLimits[idToCheckFor]++;
// Check if over limit
if (itemSpawnLimits.CurrentLimits[idToCheckFor] > itemSpawnLimits.GlobalLimits[idToCheckFor]) {
if (itemSpawnLimits.CurrentLimits[idToCheckFor] > itemSpawnLimits.GlobalLimits[idToCheckFor])
{
// Prevent edge-case of small loot pools + code trying to add limited item over and over infinitely
if (itemSpawnLimits.CurrentLimits[idToCheckFor] > itemSpawnLimits.CurrentLimits[idToCheckFor] * 10) {
if (itemSpawnLimits.CurrentLimits[idToCheckFor] > itemSpawnLimits.CurrentLimits[idToCheckFor] * 10)
{
_logger.Debug(
_localisationService.GetText("bot-item_spawn_limit_reached_skipping_item", new {
botRole = botRole,
itemName = itemTemplate.Name,
attempts = itemSpawnLimits.CurrentLimits[idToCheckFor]
})
_localisationService.GetText(
"bot-item_spawn_limit_reached_skipping_item",
new
{
botRole = botRole,
itemName = itemTemplate.Name,
attempts = itemSpawnLimits.CurrentLimits[idToCheckFor]
}
)
);
return false;
@@ -823,8 +790,9 @@ public class BotLootGenerator
{
// Get all currency weights for this bot type
var currencyWeights = _botConfig.CurrencyStackSize[botRole];
if (currencyWeights is null) {
currencyWeights = new ();
if (currencyWeights is null)
{
currencyWeights = new();
}
var currencyWeight = currencyWeights[moneyItem.Template];
@@ -856,17 +824,19 @@ public class BotLootGenerator
/// <returns>Dictionary of tplIds and limit</returns>
public Dictionary<string, double> GetItemSpawnLimitsForBotType(string botRole)
{
if (_botHelper.IsBotPmc(botRole)) {
if (_botHelper.IsBotPmc(botRole))
{
return _botConfig.ItemSpawnLimits["pmc"];
}
if (_botConfig.ItemSpawnLimits[botRole.ToLower()] is not null) {
if (_botConfig.ItemSpawnLimits[botRole.ToLower()] is not null)
{
return _botConfig.ItemSpawnLimits[botRole.ToLower()];
}
_logger.Warning(_localisationService.GetText("bot-unable_to_find_spawn_limits_fallback_to_defaults", botRole));
return new ();
return new();
}
/// <summary>
@@ -877,12 +847,14 @@ public class BotLootGenerator
/// <returns>id as string, otherwise undefined</returns>
public string? GetMatchingIdFromSpawnLimits(TemplateItem itemTemplate, Dictionary<string, double> spawnLimits)
{
if (spawnLimits.ContainsKey(itemTemplate.Id)) {
if (spawnLimits.ContainsKey(itemTemplate.Id))
{
return itemTemplate.Id;
}
// tplId not found in spawnLimits, check if parentId is
if (spawnLimits.ContainsKey(itemTemplate.Parent)) {
if (spawnLimits.ContainsKey(itemTemplate.Parent))
{
return itemTemplate.Parent;
}
+26 -60
View File
@@ -16,74 +16,40 @@ using Core.Utils.Cloners;
namespace Core.Generators;
[Injectable(InjectionType.Singleton)]
public class BotWeaponGenerator
public class BotWeaponGenerator(
ISptLogger<BotWeaponGenerator> _logger,
HashUtil _hashUtil,
DatabaseService _databaseService,
ItemHelper _itemHelper,
WeightedRandomHelper _weightedRandomHelper,
BotGeneratorHelper _botGeneratorHelper,
RandomUtil _randomUtil,
BotWeaponGeneratorHelper _botWeaponGeneratorHelper,
BotWeaponModLimitService _botWeaponModLimitService,
BotEquipmentModGenerator _botEquipmentModGenerator,
LocalisationService _localisationService,
RepairService _repairService,
ICloner _cloner,
ConfigServer _configServer,
IEnumerable<IInventoryMagGen> inventoryMagGenComponents
)
{
private readonly ISptLogger<BotWeaponGenerator> _logger;
private readonly HashUtil _hashUtil;
private readonly DatabaseService _databaseService;
private readonly ItemHelper _itemHelper;
private readonly WeightedRandomHelper _weightedRandomHelper;
private readonly BotGeneratorHelper _botGeneratorHelper;
private readonly RandomUtil _randomUtil;
private readonly BotWeaponGeneratorHelper _botWeaponGeneratorHelper;
private readonly BotWeaponModLimitService _botWeaponModLimitService;
private readonly BotEquipmentModGenerator _botEquipmentModGenerator;
private readonly LocalisationService _localisationService;
private readonly RepairService _repairService;
private readonly ICloner _cloner;
private readonly ConfigServer _configServer;
private List<IInventoryMagGen> _inventoryMagGenComponents;
protected List<IInventoryMagGen> _inventoryMagGenComponents = MagGenSetUp(inventoryMagGenComponents);
protected BotConfig _botConfig = _configServer.GetConfig<BotConfig>();
protected PmcConfig _pmcConfig = _configServer.GetConfig<PmcConfig>();
protected RepairConfig _repairConfig = _configServer.GetConfig<RepairConfig>();
protected const string _modMagazineSlotId = "mod_magazine";
private BotConfig _botConfig;
private PmcConfig _pmcConfig;
private RepairConfig _repairConfig;
private const string _modMagazineSlotId = "mod_magazine";
public BotWeaponGenerator
(
ISptLogger<BotWeaponGenerator> logger,
HashUtil hashUtil,
DatabaseService databaseService,
ItemHelper itemHelper,
WeightedRandomHelper weightedRandomHelper,
BotGeneratorHelper botGeneratorHelper,
RandomUtil randomUtil,
BotWeaponGeneratorHelper botWeaponGeneratorHelper,
BotWeaponModLimitService botWeaponModLimitService,
BotEquipmentModGenerator botEquipmentModGenerator,
LocalisationService localisationService,
RepairService repairService,
ICloner cloner,
ConfigServer configServer,
IEnumerable<IInventoryMagGen> inventoryMagGenComponents
)
private static List<IInventoryMagGen> MagGenSetUp(IEnumerable<IInventoryMagGen> components)
{
_logger = logger;
_hashUtil = hashUtil;
_databaseService = databaseService;
_itemHelper = itemHelper;
_weightedRandomHelper = weightedRandomHelper;
_botGeneratorHelper = botGeneratorHelper;
_randomUtil = randomUtil;
_botWeaponGeneratorHelper = botWeaponGeneratorHelper;
_botWeaponModLimitService = botWeaponModLimitService;
_botEquipmentModGenerator = botEquipmentModGenerator;
_localisationService = localisationService;
_repairService = repairService;
_cloner = cloner;
_configServer = configServer;
inventoryMagGenComponents.ToList()
var inventoryMagGens = components.ToList();
inventoryMagGens.ToList()
.Sort(
(a, b) =>
a.GetPriority() -
b.GetPriority()
);
_inventoryMagGenComponents = inventoryMagGenComponents.ToList();
_botConfig = _configServer.GetConfig<BotConfig>();
_pmcConfig = _configServer.GetConfig<PmcConfig>();
_repairConfig = _configServer.GetConfig<RepairConfig>();
return inventoryMagGens.ToList();
}
/// <summary>
+5 -6
View File
@@ -1,17 +1,16 @@
using Core.Annotations;
using Core.Models.Eft.Common.Tables;
using Core.Models.Spt.Config;
using Core.Servers;
namespace Core.Generators;
[Injectable]
public class FenceBaseAssortGenerator
public class FenceBaseAssortGenerator(
ConfigServer _configServer
)
{
private TraderConfig _traderConfig;
public FenceBaseAssortGenerator()
{
}
protected TraderConfig _traderConfig = _configServer.GetConfig<TraderConfig>();
/// <summary>
/// Create base fence assorts dynamically and store in memory
+3 -5
View File
@@ -7,15 +7,13 @@ using Core.Models.Spt.Config;
namespace Core.Generators;
[Injectable]
public class LocationLootGenerator
public class LocationLootGenerator(
)
{
private LocationConfig _locationConfig;
private SeasonalEventConfig _seasonalEventConfig;
public LocationLootGenerator()
{
}
/// Create a list of container objects with randomised loot
/// </summary>
/// <param name="locationBase">Map base to generate containers for</param>
+2 -4
View File
@@ -9,11 +9,9 @@ using Core.Models.Spt.Services;
namespace Core.Generators;
[Injectable]
public class LootGenerator
public class LootGenerator(
)
{
public LootGenerator()
{
}
/// <summary>
/// Generate a list of items based on configuration options parameter
+1 -4
View File
@@ -4,11 +4,8 @@ using Core.Models.Eft.Common.Tables;
namespace Core.Generators;
[Injectable]
public class PMCLootGenerator
public class PMCLootGenerator()
{
public PMCLootGenerator()
{
}
/// <summary>
/// Create a List of loot items a PMC can have in their pockets
+39 -71
View File
@@ -14,66 +14,26 @@ using Core.Utils.Cloners;
namespace Core.Generators;
[Injectable]
public class PlayerScavGenerator
public class PlayerScavGenerator(
ISptLogger<PlayerScavGenerator> _logger,
RandomUtil _randomUtil,
DatabaseService _databaseService,
HashUtil _hashUtil,
ItemHelper _itemHelper,
BotGeneratorHelper _botGeneratorHelper,
SaveServer _saveServer,
ProfileHelper _profileHelper,
BotHelper _botHelper,
FenceService _fenceService,
BotLootCacheService _botLootCacheService,
LocalisationService _localisationService,
BotGenerator _botGenerator,
ConfigServer _configServer,
ICloner _cloner,
TimeUtil _timeUtil
)
{
protected ISptLogger<PlayerScavGenerator> _logger;
protected RandomUtil _randomUtil;
protected DatabaseService _databaseService;
protected HashUtil _hashUtil;
protected ItemHelper _itemHelper;
protected BotGeneratorHelper _botGeneratorHelper;
protected SaveServer _saveServer;
protected ProfileHelper _profileHelper;
protected BotHelper _botHelper;
protected FenceService _fenceService;
protected BotLootCacheService _botLootCacheService;
protected LocalisationService _localisationService;
protected BotGenerator _botGenerator;
protected ConfigServer _configServer;
protected ICloner _cloner;
protected TimeUtil _timeUtil;
private PlayerScavConfig _playerScavConfig;
public PlayerScavGenerator
(
ISptLogger<PlayerScavGenerator> logger,
RandomUtil randomUtil,
DatabaseService databaseService,
HashUtil hashUtil,
ItemHelper itemHelper,
BotGeneratorHelper botGeneratorHelper,
SaveServer saveServer,
ProfileHelper profileHelper,
BotHelper botHelper,
FenceService fenceService,
BotLootCacheService botLootCacheService,
LocalisationService localisationService,
BotGenerator botGenerator,
ConfigServer configServer,
ICloner cloner,
TimeUtil timeUtil
)
{
_logger = logger;
_randomUtil = randomUtil;
_databaseService = databaseService;
_hashUtil = hashUtil;
_itemHelper = itemHelper;
_botGeneratorHelper = botGeneratorHelper;
_saveServer = saveServer;
_profileHelper = profileHelper;
_botHelper = botHelper;
_fenceService = fenceService;
_botLootCacheService = botLootCacheService;
_localisationService = localisationService;
_botGenerator = botGenerator;
_configServer = configServer;
_cloner = cloner;
_timeUtil = timeUtil;
_playerScavConfig = configServer.GetConfig<PlayerScavConfig>();
}
protected PlayerScavConfig _playerScavConfig = _configServer.GetConfig<PlayerScavConfig>();
/// <summary>
/// Update a player profile to include a new player scav profile
@@ -106,7 +66,8 @@ public class PlayerScavGenerator
playerScavKarmaSettings.BotTypeForLoot.ToLower(),
"easy",
baseBotNode,
pmcDataClone);
pmcDataClone
);
// Remove cached bot data after scav was generated
_botLootCacheService.ClearCache();
@@ -138,11 +99,15 @@ public class PlayerScavGenerator
scavData.Encyclopedia = pmcDataClone.Encyclopedia ?? new();
// Add additional items to player scav as loot
AddAdditionalLootToPlayerScavContainers(playerScavKarmaSettings.LootItemsToAddChancePercent, scavData, [
EquipmentSlots.TacticalVest,
EquipmentSlots.Pockets,
EquipmentSlots.Backpack
]);
AddAdditionalLootToPlayerScavContainers(
playerScavKarmaSettings.LootItemsToAddChancePercent,
scavData,
[
EquipmentSlots.TacticalVest,
EquipmentSlots.Pockets,
EquipmentSlots.Backpack
]
);
// Remove secure container
scavData = _profileHelper.RemoveSecureContainer(scavData);
@@ -162,7 +127,8 @@ public class PlayerScavGenerator
/// <param name="possibleItemsToAdd">dict of tpl + % chance to be added</param>
/// <param name="scavData"></param>
/// <param name="containersToAddTo">Possible slotIds to add loot to</param>
protected void AddAdditionalLootToPlayerScavContainers(Dictionary<string, double> possibleItemsToAdd, BotBase scavData, List<EquipmentSlots> containersToAddTo)
protected void AddAdditionalLootToPlayerScavContainers(Dictionary<string, double> possibleItemsToAdd, BotBase scavData,
List<EquipmentSlots> containersToAddTo)
{
foreach (var tpl in possibleItemsToAdd)
{
@@ -193,7 +159,8 @@ public class PlayerScavGenerator
itemsToAdd[0].Id,
itemTemplate.Id,
itemsToAdd,
scavData.Inventory);
scavData.Inventory
);
if (result != ItemAddedResult.SUCCESS)
_logger.Debug($"Unable to add keycard to bot. Reason: {result.ToString()}");
@@ -252,8 +219,8 @@ public class PlayerScavGenerator
protected void AdjustBotTemplateWithKarmaSpecificSettings(KarmaLevel karmaSettings, BotType baseBotNode)
{
// Adjust equipment chance values
foreach (var equipmentKvP in karmaSettings.Modifiers.Equipment) {
foreach (var equipmentKvP in karmaSettings.Modifiers.Equipment)
{
// Adjustment value zero, nothing to do
if (equipmentKvP.Value == 0)
{
@@ -287,7 +254,8 @@ public class PlayerScavGenerator
}
// Blacklist equipment, keyed by equipment slot
foreach (var equipmentBlacklistKvP in karmaSettings.EquipmentBlacklist) {
foreach (var equipmentBlacklistKvP in karmaSettings.EquipmentBlacklist)
{
baseBotNode.BotInventory.Equipment.TryGetValue(equipmentBlacklistKvP.Key, out var equipmentDict);
foreach (var itemToRemove in equipmentBlacklistKvP.Value)
{
@@ -309,7 +277,7 @@ public class PlayerScavGenerator
return new()
{
Common = new(),
Mastering = new (),
Mastering = new(),
Points = 0
};
}
+1 -4
View File
@@ -5,11 +5,8 @@ using Core.Models.Eft.Common.Tables;
namespace Core.Generators;
[Injectable]
public class RagfairAssortGenerator
public class RagfairAssortGenerator()
{
public RagfairAssortGenerator()
{
}
/// <summary>
/// Get an array of arrays that can be sold on the flea
+1 -4
View File
@@ -7,11 +7,8 @@ using Core.Models.Spt.Ragfair;
namespace Core.Generators;
[Injectable]
public class RagfairOfferGenerator
public class RagfairOfferGenerator()
{
public RagfairOfferGenerator()
{
}
/// <summary>
/// Create a flea offer and store it in the Ragfair server offers list
+62 -65
View File
@@ -16,43 +16,19 @@ using BodyPart = Core.Models.Spt.Config.BodyPart;
namespace Core.Generators;
[Injectable]
public class RepeatableQuestGenerator
public class RepeatableQuestGenerator(
ISptLogger<RepeatableQuestGenerator> _logger,
RandomUtil _randomUtil,
HashUtil _hashUtil,
MathUtil _mathUtil,
RepeatableQuestHelper _repeatableQuestHelper,
ItemHelper _itemHelper,
RepeatableQuestRewardGenerator _repeatableQuestRewardGenerator,
DatabaseService _databaseService,
ConfigServer _configServer
)
{
protected ISptLogger<RepeatableQuestGenerator> _logger;
protected RandomUtil _randomUtil;
protected HashUtil _hashUtil;
protected MathUtil _mathUtil;
protected RepeatableQuestHelper _repeatableQuestHelper;
protected ItemHelper _itemHelper;
protected RepeatableQuestRewardGenerator _repeatableQuestRewardGenerator;
protected DatabaseService _databaseService;
protected ConfigServer _configServer;
protected QuestConfig _questConfig;
public RepeatableQuestGenerator(
ISptLogger<RepeatableQuestGenerator> logger,
RandomUtil randomUtil,
HashUtil hashUtil,
MathUtil mathUtil,
RepeatableQuestHelper repeatableQuestHelper,
ItemHelper itemHelper,
RepeatableQuestRewardGenerator repeatableQuestRewardGenerator,
DatabaseService databaseService,
ConfigServer configServer
)
{
_logger = logger;
_randomUtil = randomUtil;
_hashUtil = hashUtil;
_mathUtil = mathUtil;
_repeatableQuestHelper = repeatableQuestHelper;
_itemHelper = itemHelper;
_repeatableQuestRewardGenerator = repeatableQuestRewardGenerator;
_databaseService = databaseService;
_configServer = configServer;
_questConfig = _configServer.GetConfig<QuestConfig>();
}
protected QuestConfig _questConfig = _configServer.GetConfig<QuestConfig>();
/// <summary>
/// This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json).
@@ -77,7 +53,8 @@ public class RepeatableQuestGenerator
// Get traders from whitelist and filter by quest type availability
var traders = repeatableConfig.TraderWhitelist
.Where(x => x.QuestTypes.Contains(questType))
.Select(x => x.TraderId).ToList();
.Select(x => x.TraderId)
.ToList();
// filter out locked traders
traders = traders.Where(x => pmcTraderInfo[x].Unlocked.GetValueOrDefault(false)).ToList();
var traderId = _randomUtil.DrawRandomFromList(traders).FirstOrDefault();
@@ -115,8 +92,10 @@ public class RepeatableQuestGenerator
var locationsConfig = repeatableConfig.Locations;
var targetsConfig = _repeatableQuestHelper.ProbabilityObjectArray<Target, string, BossInfo>(eliminationConfig.Targets);
var bodyPartsConfig = _repeatableQuestHelper.ProbabilityObjectArray<BodyPart, string, List<string>>(eliminationConfig.BodyParts);
var weaponCategoryRequirementConfig = _repeatableQuestHelper.ProbabilityObjectArray<WeaponRequirement, string, List<string>>(eliminationConfig.WeaponCategoryRequirements);
var weaponRequirementConfig = _repeatableQuestHelper.ProbabilityObjectArray<WeaponRequirement, string, List<string>>(eliminationConfig.WeaponRequirements);
var weaponCategoryRequirementConfig =
_repeatableQuestHelper.ProbabilityObjectArray<WeaponRequirement, string, List<string>>(eliminationConfig.WeaponCategoryRequirements);
var weaponRequirementConfig =
_repeatableQuestHelper.ProbabilityObjectArray<WeaponRequirement, string, List<string>>(eliminationConfig.WeaponRequirements);
// the difficulty of the quest varies in difficulty depending on the condition
// possible conditions are
@@ -171,7 +150,7 @@ public class RepeatableQuestGenerator
var locationKey = "any";
if (locations.Contains("any") &&
(eliminationConfig.SpecificLocationProbability < rand.Next() || locations.Count <= 1)
)
)
{
locationKey = "any";
questTypePool.Pool.Elimination.Targets.Remove(targetKey);
@@ -183,7 +162,9 @@ public class RepeatableQuestGenerator
{
locationKey = _randomUtil.DrawRandomFromList(locations).FirstOrDefault();
questTypePool.Pool.Elimination.Targets.Get<TargetLocation>(targetKey).Locations = locations.Where(
(l) => l != locationKey).ToList();
(l) => l != locationKey
)
.ToList();
if (questTypePool.Pool.Elimination.Targets.Get<TargetLocation>(targetKey).Locations.Count == 0)
{
questTypePool.Pool.Elimination.Targets.Remove(targetKey);
@@ -216,6 +197,7 @@ public class RepeatableQuestGenerator
bodyPartsToClient.Add(biClient);
}
}
bodyPartDifficulty = 1 / probability;
}
@@ -227,17 +209,21 @@ public class RepeatableQuestGenerator
if (targetsConfig.Data(targetKey).IsBoss.GetValueOrDefault(false))
{
// Get all boss spawn information
var bossSpawns = _databaseService.GetLocations().GetDictionary()
var bossSpawns = _databaseService.GetLocations()
.GetDictionary()
.Select(x => x.Value)
.Where(x => x.Base?.Id != null)
.Select(x => (new { x.Base.Id, BossSpawn = x.Base.BossLocationSpawn }));
// filter for the current boss to spawn on map
var thisBossSpawns = bossSpawns
.Select(x => new {
x.Id,
BossSpawn = x.BossSpawn
.Where(e => e.BossName == targetKey)
})
.Select(
x => new
{
x.Id,
BossSpawn = x.BossSpawn
.Where(e => e.BossName == targetKey)
}
)
.Where((x) => x.BossSpawn.Count() > 0);
// remove blacklisted locations
var allowedSpawns = thisBossSpawns.Where((x) => !eliminationConfig.DistLocationBlacklist.Contains(x.Id));
@@ -250,7 +236,8 @@ public class RepeatableQuestGenerator
// Random distance with lower values more likely; simple distribution for starters...
distance = (int)Math.Floor(
(decimal)(Math.Abs(rand.Next(0, 1) - rand.Next(0, 1)) * (1 + eliminationConfig.MaxDistance - eliminationConfig.MinDistance) +
eliminationConfig.MinDistance));
eliminationConfig.MinDistance)
);
distance = (int)Math.Ceiling((decimal)(distance / 5)) * 5;
distanceDifficulty = (int)(maxDistDifficulty * distance / eliminationConfig.MaxDistance);
}
@@ -263,16 +250,20 @@ public class RepeatableQuestGenerator
{
List<string> weaponTypes = ["Shotgun", "Pistol"];
weaponCategoryRequirementConfig = (ProbabilityObjectArray<WeaponRequirement, string, List<string>>)weaponCategoryRequirementConfig
.Where((category) => weaponTypes
.Contains(category.Key));
.Where(
(category) => weaponTypes
.Contains(category.Key)
);
}
else if (distance < 20)
{
List<string> weaponTypes = ["MarksmanRifle", "DMR"];
// Filter out far range weapons from close distance requirement
weaponCategoryRequirementConfig = (ProbabilityObjectArray<WeaponRequirement, string, List<string>>)weaponCategoryRequirementConfig
.Where((category) => weaponTypes
.Contains(category.Key));
.Where(
(category) => weaponTypes
.Contains(category.Key)
);
}
// Pick a weighted weapon category
@@ -304,7 +295,8 @@ public class RepeatableQuestGenerator
bodyPartDifficulty / maxBodyPartsDifficulty.Value,
distanceDifficulty / maxDistDifficulty,
killDifficulty / maxKillDifficulty.Value,
allowedWeaponsCategory is not null || allowedWeapon is not null ? 1 : 0);
allowedWeaponsCategory is not null || allowedWeapon is not null ? 1 : 0
);
// Aforementioned issue makes it a bit crazy since now all easier quests give significantly lower rewards than Completion / Exploration
// I therefore moved the mapping a bit up (from 0.2...1 to 0.5...2) so that normal difficulty still gives good reward and having the
@@ -326,16 +318,18 @@ public class RepeatableQuestGenerator
// Only add specific location condition if specific map selected
if (locationKey != "any")
{
Enum.TryParse(typeof (ELocationName), locationKey, true, out var locationId);
Enum.TryParse(typeof(ELocationName), locationKey, true, out var locationId);
availableForFinishCondition.Counter.Conditions.Add(GenerateEliminationLocation(locationsConfig[(ELocationName)locationId]));
}
availableForFinishCondition.Counter.Conditions.Add(
GenerateEliminationCondition(
targetKey,
bodyPartsToClient,
distance.Value,
allowedWeapon,
allowedWeaponsCategory)
allowedWeaponsCategory
)
);
availableForFinishCondition.Value = desiredKillCount;
availableForFinishCondition.Id = _hashUtil.Generate();
@@ -346,7 +340,8 @@ public class RepeatableQuestGenerator
Math.Min(difficulty, 1),
traderId,
repeatableConfig,
eliminationConfig);
eliminationConfig
);
return quest;
}
@@ -377,11 +372,11 @@ public class RepeatableQuestGenerator
}
protected double DifficultyWeighing(
double target,
double bodyPart,
int dist,
int kill,
int weaponRequirement)
double target,
double bodyPart,
int dist,
int kill,
int weaponRequirement)
{
return Math.Sqrt(Math.Sqrt(target) + bodyPart + dist + weaponRequirement) * kill;
}
@@ -430,15 +425,17 @@ public class RepeatableQuestGenerator
string? allowedWeaponCategory
)
{
var killConditionProps = new QuestConditionCounterCondition{
var killConditionProps = new QuestConditionCounterCondition
{
Id = _hashUtil.Generate(),
DynamicLocale = true,
Target = target, // e,g, "AnyPmc"
Value = 1,
ResetOnSessionEnd = false,
EnemyHealthEffects = [],
Daytime = new DaytimeCounter(){ From = 0, To = 0 },
ConditionType = "Kills"};
Daytime = new DaytimeCounter() { From = 0, To = 0 },
ConditionType = "Kills"
};
if (target.StartsWith("boss"))
{
@@ -455,7 +452,7 @@ public class RepeatableQuestGenerator
// Don't allow distance + melee requirement
if (distance is not null && allowedWeaponCategory != "5b5f7a0886f77409407a7f96")
{
killConditionProps.Distance = new CounterConditionDistance{ CompareMethod = ">=", Value = distance.Value };
killConditionProps.Distance = new CounterConditionDistance { CompareMethod = ">=", Value = distance.Value };
}
// Has specific weapon requirement
+263 -288
View File
@@ -10,327 +10,302 @@ using Core.Services;
using Core.Utils;
using Core.Utils.Cloners;
namespace Core.Generators
namespace Core.Generators;
[Injectable]
public class RepeatableQuestRewardGenerator(
ISptLogger<RepeatableQuestRewardGenerator> _logger,
RandomUtil _randomUtil,
HashUtil _hashUtil,
MathUtil _mathUtil,
DatabaseService _databaseService,
ItemHelper _itemHelper,
PresetHelper _presetHelper,
HandbookHelper _handbookHelper,
LocalisationService _localisationService,
ItemFilterService _itemFilterService,
SeasonalEventService _seasonalEventService,
ConfigServer _configServer,
ICloner _cloner
)
{
[Injectable]
public class RepeatableQuestRewardGenerator
protected QuestConfig _questConfig = _configServer.GetConfig<QuestConfig>();
/**
* Generate the reward for a mission. A reward can consist of:
* - Experience
* - Money
* - GP coins
* - Weapon preset
* - Items
* - Trader Reputation
* - Skill level experience
*
* The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to
* experience / money / items / trader reputation can be defined in QuestConfig.js
*
* There's also a random variation of the reward the spread of which can be also defined in the config
*
* Additionally, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used
* @param pmcLevel Level of player reward is being generated for
* @param difficulty Reward scaling factor from 0.2 to 1
* @param traderId Trader reward will be given by
* @param repeatableConfig Config for quest type (daily, weekly)
* @param questConfig
* @param rewardTplBlacklist OPTIONAL: list of tpls to NOT use when picking a reward
* @returns IQuestRewards
*/
public QuestRewards GenerateReward(
int pmcLevel,
double difficulty,
string traderId,
RepeatableQuestConfig repeatableConfig,
EliminationConfig eliminationConfig,
List<string>? rewardTplBlacklist = null)
{
#region Ctor & Params
// Get vars to configure rewards with
var rewardParams = GetQuestRewardValues(repeatableConfig.RewardScaling, difficulty, pmcLevel);
private readonly ISptLogger<RepeatableQuestRewardGenerator> _logger;
private readonly RandomUtil _randomUtil;
private readonly HashUtil _hashUtil;
private readonly MathUtil _mathUtil;
private readonly DatabaseService _databaseService;
private readonly ItemHelper _itemHelper;
private readonly PresetHelper _presetHelper;
private readonly HandbookHelper _handbookHelper;
private readonly LocalisationService _localisationService;
private readonly ItemFilterService _itemFilterService;
private readonly SeasonalEventService _seasonalEventService;
private readonly ConfigServer _configServer;
private readonly ICloner _cloner;
private readonly QuestConfig _questConfig;
// Get budget to spend on item rewards (copy of raw roubles given)
var itemRewardBudget = rewardParams.RewardRoubles;
public RepeatableQuestRewardGenerator
(
ISptLogger<RepeatableQuestRewardGenerator> logger,
RandomUtil randomUtil,
HashUtil hashUtil,
MathUtil mathUtil,
DatabaseService databaseService,
ItemHelper itemHelper,
PresetHelper presetHelper,
HandbookHelper handbookHelper,
LocalisationService localisationService,
ItemFilterService itemFilterService,
SeasonalEventService seasonalEventService,
ConfigServer configServer,
ICloner cloner
)
// Possible improvement -> draw trader-specific items e.g. with this.itemHelper.isOfBaseclass(val._id, ItemHelper.BASECLASS.FoodDrink)
QuestRewards rewards = new() { Started = [], Success = [], Fail = [] };
// Start reward index to keep track
var rewardIndex = -1;
// Add xp reward
if (rewardParams.RewardXP > 0)
{
_logger = logger;
_randomUtil = randomUtil;
_hashUtil = hashUtil;
_mathUtil = mathUtil;
_databaseService = databaseService;
_itemHelper = itemHelper;
_presetHelper = presetHelper;
_handbookHelper = handbookHelper;
_localisationService = localisationService;
_itemFilterService = itemFilterService;
_seasonalEventService = seasonalEventService;
_configServer = configServer;
_cloner = cloner;
_questConfig = _configServer.GetConfig<QuestConfig>();
}
#endregion
/**
* Generate the reward for a mission. A reward can consist of:
* - Experience
* - Money
* - GP coins
* - Weapon preset
* - Items
* - Trader Reputation
* - Skill level experience
*
* The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to
* experience / money / items / trader reputation can be defined in QuestConfig.js
*
* There's also a random variation of the reward the spread of which can be also defined in the config
*
* Additionally, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used
* @param pmcLevel Level of player reward is being generated for
* @param difficulty Reward scaling factor from 0.2 to 1
* @param traderId Trader reward will be given by
* @param repeatableConfig Config for quest type (daily, weekly)
* @param questConfig
* @param rewardTplBlacklist OPTIONAL: list of tpls to NOT use when picking a reward
* @returns IQuestRewards
*/
public QuestRewards GenerateReward(
int pmcLevel,
double difficulty,
string traderId,
RepeatableQuestConfig repeatableConfig,
EliminationConfig eliminationConfig,
List<string>? rewardTplBlacklist = null)
{
// Get vars to configure rewards with
var rewardParams = GetQuestRewardValues(repeatableConfig.RewardScaling, difficulty, pmcLevel);
// Get budget to spend on item rewards (copy of raw roubles given)
var itemRewardBudget = rewardParams.RewardRoubles;
// Possible improvement -> draw trader-specific items e.g. with this.itemHelper.isOfBaseclass(val._id, ItemHelper.BASECLASS.FoodDrink)
QuestRewards rewards = new() { Started = [], Success = [], Fail = [] };
// Start reward index to keep track
var rewardIndex = -1;
// Add xp reward
if (rewardParams.RewardXP > 0)
{
rewards.Success.Add(
new()
{
Id = _hashUtil.Generate(),
Unknown = false,
GameMode = [],
AvailableInGameEditions = [],
Index = rewardIndex,
Value = rewardParams.RewardXP,
Type = RewardType.Experience
}
);
rewardIndex++;
}
// Add money reward
rewards.Success.Add(GetMoneyReward(traderId, rewardParams.RewardRoubles, rewardIndex));
rewardIndex++;
// Add GP coin reward
rewards.Success.Add(GenerateItemReward(Money.GP, rewardParams.GpCoinRewardCount, rewardIndex));
rewardIndex++;
// Add preset weapon to reward if checks pass
var traderWhitelistDetails = repeatableConfig.TraderWhitelist.FirstOrDefault(
(traderWhitelist) => traderWhitelist.TraderId == traderId
);
if (traderWhitelistDetails?.RewardCanBeWeapon ?? false && _randomUtil.GetChance100(traderWhitelistDetails.WeaponRewardChancePercent ?? 0)
)
{
var chosenWeapon = GetRandomWeaponPresetWithinBudget(itemRewardBudget, rewardIndex);
if (chosenWeapon is not null)
{
rewards.Success.Add(chosenWeapon.Value.Key);
// Subtract price of preset from item budget so we dont give player too much stuff
itemRewardBudget -= (int)chosenWeapon.Value.Value;
rewardIndex++;
}
}
var inBudgetRewardItemPool = ChooseRewardItemsWithinBudget(repeatableConfig, itemRewardBudget, traderId);
if (rewardTplBlacklist is not null)
{
// Filter reward pool of items from blacklist, only use if there's at least 1 item remaining
var filteredRewardItemPool = inBudgetRewardItemPool.Where(
(item) => !rewardTplBlacklist.Contains(item.Id)
);
if (filteredRewardItemPool.Count() > 0)
{
inBudgetRewardItemPool = filteredRewardItemPool.ToList();
}
}
_logger.Debug(
$"Generating: {repeatableConfig.Name} quest for: {traderId} with budget: {itemRewardBudget} totalling: {rewardParams.RewardNumItems} items"
);
if (inBudgetRewardItemPool.Count > 0)
{
var itemsToReward = GetRewardableItemsFromPoolWithinBudget(
inBudgetRewardItemPool,
rewardParams.RewardNumItems,
itemRewardBudget,
repeatableConfig
);
// Add item rewards
foreach (var itemReward in itemsToReward)
{
rewards.Success.Add(GenerateItemReward(itemReward.Key.Id, itemReward.Value, rewardIndex));
rewardIndex++;
}
}
// Add rep reward to rewards array
if (rewardParams.RewardReputation > 0)
{
Reward reward = new()
rewards.Success.Add(
new()
{
Id = _hashUtil.Generate(),
Unknown = false,
GameMode = [],
AvailableInGameEditions = [],
Target = traderId,
Value = rewardParams.RewardReputation,
Type = RewardType.TraderStanding,
Index = rewardIndex
};
rewards.Success.Add(reward);
rewardIndex++;
_logger.Debug($"Adding: {rewardParams.RewardReputation} {traderId} trader reputation reward");
}
// Chance of adding skill reward
if (_randomUtil.GetChance100((double)rewardParams.SkillRewardChance * 100))
{
var targetSkill = _randomUtil.GetArrayValue(eliminationConfig.PossibleSkillRewards);
Reward reward = new()
{
Id = _hashUtil.Generate(),
Unknown = false,
GameMode = [],
AvailableInGameEditions = [],
Target = targetSkill,
Value = rewardParams.SkillPointReward,
Type = RewardType.Skill,
Index = rewardIndex
};
rewards.Success.Add(reward);
_logger.Debug($"Adding {rewardParams.SkillPointReward} skill points to {targetSkill}");
}
return rewards;
Index = rewardIndex,
Value = rewardParams.RewardXP,
Type = RewardType.Experience
}
);
rewardIndex++;
}
private QuestRewardValues GetQuestRewardValues(RewardScaling? rewardScaling, double? difficulty, int pmcLevel)
// Add money reward
rewards.Success.Add(GetMoneyReward(traderId, rewardParams.RewardRoubles, rewardIndex));
rewardIndex++;
// Add GP coin reward
rewards.Success.Add(GenerateItemReward(Money.GP, rewardParams.GpCoinRewardCount, rewardIndex));
rewardIndex++;
// Add preset weapon to reward if checks pass
var traderWhitelistDetails = repeatableConfig.TraderWhitelist.FirstOrDefault(
(traderWhitelist) => traderWhitelist.TraderId == traderId
);
if (traderWhitelistDetails?.RewardCanBeWeapon ?? false && _randomUtil.GetChance100(traderWhitelistDetails.WeaponRewardChancePercent ?? 0)
)
{
// difficulty could go from 0.2 ... -> for lowest difficulty receive 0.2*nominal reward
var levelsConfig = rewardScaling.Levels;
var roublesConfig = rewardScaling.Roubles;
var gpCoinConfig = rewardScaling.GpCoins;
var xpConfig = rewardScaling.Experience;
var itemsConfig = rewardScaling.Items;
var rewardSpreadConfig = rewardScaling.RewardSpread;
var skillRewardChanceConfig = rewardScaling.SkillRewardChance;
var skillPointRewardConfig = rewardScaling.SkillPointReward;
var reputationConfig = rewardScaling.Reputation;
var effectiveDifficulty = difficulty is null ? 1 : difficulty;
if (difficulty is null)
var chosenWeapon = GetRandomWeaponPresetWithinBudget(itemRewardBudget, rewardIndex);
if (chosenWeapon is not null)
{
_logger.Warning(_localisationService.GetText("repeatable-difficulty_was_nan"));
}
rewards.Success.Add(chosenWeapon.Value.Key);
return new () {
SkillPointReward = _mathUtil.Interp1(pmcLevel, levelsConfig, skillPointRewardConfig),
SkillRewardChance = _mathUtil.Interp1(pmcLevel, levelsConfig, skillRewardChanceConfig),
RewardReputation = GetRewardRep(effectiveDifficulty, pmcLevel, levelsConfig, reputationConfig, rewardSpreadConfig),
RewardNumItems = GetRewardNumItems(pmcLevel, levelsConfig, itemsConfig),
RewardRoubles = GetRewardRoubles(effectiveDifficulty, pmcLevel, levelsConfig, roublesConfig, rewardSpreadConfig),
GpCoinRewardCount = GetGpCoinRewardCount(effectiveDifficulty, pmcLevel, levelsConfig, gpCoinConfig, rewardSpreadConfig),
RewardXP = GetRewardXp(effectiveDifficulty, pmcLevel, levelsConfig, xpConfig, rewardSpreadConfig),
// Subtract price of preset from item budget so we dont give player too much stuff
itemRewardBudget -= (int)chosenWeapon.Value.Value;
rewardIndex++;
}
}
var inBudgetRewardItemPool = ChooseRewardItemsWithinBudget(repeatableConfig, itemRewardBudget, traderId);
if (rewardTplBlacklist is not null)
{
// Filter reward pool of items from blacklist, only use if there's at least 1 item remaining
var filteredRewardItemPool = inBudgetRewardItemPool.Where(
(item) => !rewardTplBlacklist.Contains(item.Id)
);
if (filteredRewardItemPool.Count() > 0)
{
inBudgetRewardItemPool = filteredRewardItemPool.ToList();
}
}
_logger.Debug(
$"Generating: {repeatableConfig.Name} quest for: {traderId} with budget: {itemRewardBudget} totalling: {rewardParams.RewardNumItems} items"
);
if (inBudgetRewardItemPool.Count > 0)
{
var itemsToReward = GetRewardableItemsFromPoolWithinBudget(
inBudgetRewardItemPool,
rewardParams.RewardNumItems,
itemRewardBudget,
repeatableConfig
);
// Add item rewards
foreach (var itemReward in itemsToReward)
{
rewards.Success.Add(GenerateItemReward(itemReward.Key.Id, itemReward.Value, rewardIndex));
rewardIndex++;
}
}
// Add rep reward to rewards array
if (rewardParams.RewardReputation > 0)
{
Reward reward = new()
{
Id = _hashUtil.Generate(),
Unknown = false,
GameMode = [],
AvailableInGameEditions = [],
Target = traderId,
Value = rewardParams.RewardReputation,
Type = RewardType.TraderStanding,
Index = rewardIndex
};
rewards.Success.Add(reward);
rewardIndex++;
_logger.Debug($"Adding: {rewardParams.RewardReputation} {traderId} trader reputation reward");
}
private double GetRewardXp(double? effectiveDifficulty, int pmcLevel, List<double>? levelsConfig, List<double>? xpConfig, double? rewardSpreadConfig)
// Chance of adding skill reward
if (_randomUtil.GetChance100((double)rewardParams.SkillRewardChance * 100))
{
return Math.Floor((effectiveDifficulty
* _mathUtil.Interp1(pmcLevel, levelsConfig, xpConfig)
* _randomUtil.GetFloat((float)(1 - rewardSpreadConfig), (float)(1 + rewardSpreadConfig)))
?? 0);
var targetSkill = _randomUtil.GetArrayValue(eliminationConfig.PossibleSkillRewards);
Reward reward = new()
{
Id = _hashUtil.Generate(),
Unknown = false,
GameMode = [],
AvailableInGameEditions = [],
Target = targetSkill,
Value = rewardParams.SkillPointReward,
Type = RewardType.Skill,
Index = rewardIndex
};
rewards.Success.Add(reward);
_logger.Debug($"Adding {rewardParams.SkillPointReward} skill points to {targetSkill}");
}
private double GetGpCoinRewardCount(double? effectiveDifficulty, int pmcLevel, List<double>? levelsConfig, List<double>? gpCoinConfig,
double? rewardSpreadConfig)
return rewards;
}
private QuestRewardValues GetQuestRewardValues(RewardScaling? rewardScaling, double? difficulty, int pmcLevel)
{
// difficulty could go from 0.2 ... -> for lowest difficulty receive 0.2*nominal reward
var levelsConfig = rewardScaling.Levels;
var roublesConfig = rewardScaling.Roubles;
var gpCoinConfig = rewardScaling.GpCoins;
var xpConfig = rewardScaling.Experience;
var itemsConfig = rewardScaling.Items;
var rewardSpreadConfig = rewardScaling.RewardSpread;
var skillRewardChanceConfig = rewardScaling.SkillRewardChance;
var skillPointRewardConfig = rewardScaling.SkillPointReward;
var reputationConfig = rewardScaling.Reputation;
var effectiveDifficulty = difficulty is null ? 1 : difficulty;
if (difficulty is null)
{
return Math.Ceiling((effectiveDifficulty
* _mathUtil.Interp1(pmcLevel, levelsConfig, gpCoinConfig)
* _randomUtil.GetFloat((float)(1 - rewardSpreadConfig), (float)(1 + rewardSpreadConfig)))
?? 0);
_logger.Warning(_localisationService.GetText("repeatable-difficulty_was_nan"));
}
private double GetRewardRep(double? effectiveDifficulty, int pmcLevel, List<double>? levelsConfig, List<double>? reputationConfig, double? rewardSpreadConfig)
return new()
{
return Math.Round(100 * effectiveDifficulty
* _mathUtil.Interp1(pmcLevel, levelsConfig, reputationConfig)
* _randomUtil.GetFloat((float)(1 - rewardSpreadConfig), (float)(1 + rewardSpreadConfig))
?? 0) / 100;
}
SkillPointReward = _mathUtil.Interp1(pmcLevel, levelsConfig, skillPointRewardConfig),
SkillRewardChance = _mathUtil.Interp1(pmcLevel, levelsConfig, skillRewardChanceConfig),
RewardReputation = GetRewardRep(effectiveDifficulty, pmcLevel, levelsConfig, reputationConfig, rewardSpreadConfig),
RewardNumItems = GetRewardNumItems(pmcLevel, levelsConfig, itemsConfig),
RewardRoubles = GetRewardRoubles(effectiveDifficulty, pmcLevel, levelsConfig, roublesConfig, rewardSpreadConfig),
GpCoinRewardCount = GetGpCoinRewardCount(effectiveDifficulty, pmcLevel, levelsConfig, gpCoinConfig, rewardSpreadConfig),
RewardXP = GetRewardXp(effectiveDifficulty, pmcLevel, levelsConfig, xpConfig, rewardSpreadConfig),
};
}
private double GetRewardNumItems(int pmcLevel, List<double>? levelsConfig, List<double>? itemsConfig)
{
return _randomUtil.RandInt(1, (int)Math.Round(_mathUtil.Interp1(pmcLevel, levelsConfig, itemsConfig) ?? 0) + 1);
}
private double GetRewardXp(double? effectiveDifficulty, int pmcLevel, List<double>? levelsConfig, List<double>? xpConfig, double? rewardSpreadConfig)
{
return Math.Floor(
(effectiveDifficulty *
_mathUtil.Interp1(pmcLevel, levelsConfig, xpConfig) *
_randomUtil.GetFloat((float)(1 - rewardSpreadConfig), (float)(1 + rewardSpreadConfig))) ??
0
);
}
private double GetRewardRoubles(double? effectiveDifficulty, int pmcLevel, List<double>? levelsConfig, List<double>? roublesConfig, double? rewardSpreadConfig)
{
return Math.Floor((effectiveDifficulty
* _mathUtil.Interp1(pmcLevel, levelsConfig, roublesConfig)
* _randomUtil.GetFloat((float)(1 - rewardSpreadConfig), (float)(1 + rewardSpreadConfig)))
?? 0);
}
private double GetGpCoinRewardCount(double? effectiveDifficulty, int pmcLevel, List<double>? levelsConfig, List<double>? gpCoinConfig,
double? rewardSpreadConfig)
{
return Math.Ceiling(
(effectiveDifficulty *
_mathUtil.Interp1(pmcLevel, levelsConfig, gpCoinConfig) *
_randomUtil.GetFloat((float)(1 - rewardSpreadConfig), (float)(1 + rewardSpreadConfig))) ??
0
);
}
private List<KeyValuePair<TemplateItem, double>> GetRewardableItemsFromPoolWithinBudget(List<TemplateItem> inBudgetRewardItemPool,
object rewardNumItems, double? itemRewardBudget, RepeatableQuestConfig repeatableConfig)
{
throw new NotImplementedException();
}
private double GetRewardRep(double? effectiveDifficulty, int pmcLevel, List<double>? levelsConfig, List<double>? reputationConfig,
double? rewardSpreadConfig)
{
return Math.Round(
100 *
effectiveDifficulty *
_mathUtil.Interp1(pmcLevel, levelsConfig, reputationConfig) *
_randomUtil.GetFloat((float)(1 - rewardSpreadConfig), (float)(1 + rewardSpreadConfig)) ??
0
) /
100;
}
private List<TemplateItem> ChooseRewardItemsWithinBudget(RepeatableQuestConfig repeatableConfig, double? itemRewardBudget, string traderId)
{
throw new NotImplementedException();
}
private double GetRewardNumItems(int pmcLevel, List<double>? levelsConfig, List<double>? itemsConfig)
{
return _randomUtil.RandInt(1, (int)Math.Round(_mathUtil.Interp1(pmcLevel, levelsConfig, itemsConfig) ?? 0) + 1);
}
private KeyValuePair<Reward, double>? GetRandomWeaponPresetWithinBudget(double? itemRewardBudget, double rewardIndex)
{
throw new NotImplementedException();
}
private double GetRewardRoubles(double? effectiveDifficulty, int pmcLevel, List<double>? levelsConfig, List<double>? roublesConfig,
double? rewardSpreadConfig)
{
return Math.Floor(
(effectiveDifficulty *
_mathUtil.Interp1(pmcLevel, levelsConfig, roublesConfig) *
_randomUtil.GetFloat((float)(1 - rewardSpreadConfig), (float)(1 + rewardSpreadConfig))) ??
0
);
}
private Reward GenerateItemReward(string d235b4d86f7742e017bc88a, object gpCoinRewardCount, double rewardIndex)
{
throw new NotImplementedException();
}
private List<KeyValuePair<TemplateItem, double>> GetRewardableItemsFromPoolWithinBudget(List<TemplateItem> inBudgetRewardItemPool,
object rewardNumItems, double? itemRewardBudget, RepeatableQuestConfig repeatableConfig)
{
throw new NotImplementedException();
}
private Reward GetMoneyReward(string traderId, object rewardRoubles, double rewardIndex)
{
throw new NotImplementedException();
}
private List<TemplateItem> ChooseRewardItemsWithinBudget(RepeatableQuestConfig repeatableConfig, double? itemRewardBudget, string traderId)
{
throw new NotImplementedException();
}
private KeyValuePair<Reward, double>? GetRandomWeaponPresetWithinBudget(double? itemRewardBudget, double rewardIndex)
{
throw new NotImplementedException();
}
private Reward GenerateItemReward(string d235b4d86f7742e017bc88a, object gpCoinRewardCount, double rewardIndex)
{
throw new NotImplementedException();
}
private Reward GetMoneyReward(string traderId, object rewardRoubles, double rewardIndex)
{
throw new NotImplementedException();
}
public Dictionary<string, List<TemplateItem>> GetRewardableItems(RepeatableQuestConfig repeatableConfig, string traderId)
{
throw new NotImplementedException();
}
public Dictionary<string, List<TemplateItem>> GetRewardableItems(RepeatableQuestConfig repeatableConfig, string traderId)
{
throw new NotImplementedException();
}
}
+1 -4
View File
@@ -6,11 +6,8 @@ using Core.Models.Spt.Hideout;
namespace Core.Generators;
[Injectable]
public class ScavCaseRewardGenerator
public class ScavCaseRewardGenerator()
{
public ScavCaseRewardGenerator()
{
}
/// <summary>
/// Create an array of rewards that will be given to the player upon completing their scav case build
@@ -5,21 +5,11 @@ using Core.Utils;
namespace Core.Generators.WeaponGen.Implementations;
[Injectable]
public class BarrelInvetoryMagGen : InventoryMagGen, IInventoryMagGen
public class BarrelInvetoryMagGen(
RandomUtil _randomUtil,
BotWeaponGeneratorHelper _botWeaponGeneratorHelper
) : InventoryMagGen, IInventoryMagGen
{
private readonly RandomUtil _randomUtil;
private readonly BotWeaponGeneratorHelper _botWeaponGeneratorHelper;
public BarrelInvetoryMagGen
(
RandomUtil randomUtil,
BotWeaponGeneratorHelper botWeaponGeneratorHelper
)
{
_randomUtil = randomUtil;
_botWeaponGeneratorHelper = botWeaponGeneratorHelper;
}
public int GetPriority()
{
return 50;
@@ -9,32 +9,15 @@ using Core.Utils;
namespace Core.Generators.WeaponGen.Implementations;
[Injectable]
public class ExternalInventoryMagGen : InventoryMagGen, IInventoryMagGen
public class ExternalInventoryMagGen(
ISptLogger<ExternalInventoryMagGen> _logger,
ItemHelper _itemHelper,
LocalisationService _localisationService,
BotWeaponGeneratorHelper _botWeaponGeneratorHelper,
BotGeneratorHelper _botGeneratorHelper,
RandomUtil _randomUtil
) : InventoryMagGen, IInventoryMagGen
{
private readonly ISptLogger<ExternalInventoryMagGen> _logger;
private readonly ItemHelper _itemHelper;
private readonly LocalisationService _localisationService;
private readonly BotWeaponGeneratorHelper _botWeaponGeneratorHelper;
private readonly BotGeneratorHelper _botGeneratorHelper;
private readonly RandomUtil _randomUtil;
public ExternalInventoryMagGen
(
ISptLogger<ExternalInventoryMagGen> logger,
ItemHelper itemHelper,
LocalisationService localisationService,
BotWeaponGeneratorHelper botWeaponGeneratorHelper,
BotGeneratorHelper botGeneratorHelper,
RandomUtil randomUtil
)
{
_logger = logger;
_itemHelper = itemHelper;
_localisationService = localisationService;
_botWeaponGeneratorHelper = botWeaponGeneratorHelper;
_botGeneratorHelper = botGeneratorHelper;
_randomUtil = randomUtil;
}
public int GetPriority()
{
@@ -58,7 +41,8 @@ public class ExternalInventoryMagGen : InventoryMagGen, IInventoryMagGen
List<string> attemptedMagBlacklist = [];
var defaultMagazineTpl = _botWeaponGeneratorHelper.GetWeaponsDefaultMagazineTpl(weapon);
var randomizedMagazineCount = _botWeaponGeneratorHelper.GetRandomizedMagazineCount(inventoryMagGen.GetMagCount());
for (var i = 0; i < randomizedMagazineCount; i++) {
for (var i = 0; i < randomizedMagazineCount; i++)
{
var magazineWithAmmo = _botWeaponGeneratorHelper.CreateMagazineWithAmmo(
magazineTpl,
inventoryMagGen.GetAmmoTemplate().Id,
@@ -73,15 +57,18 @@ public class ExternalInventoryMagGen : InventoryMagGen, IInventoryMagGen
inventoryMagGen.GetPmcInventory()
);
if (fitsIntoInventory == ItemAddedResult.NO_CONTAINERS) {
if (fitsIntoInventory == ItemAddedResult.NO_CONTAINERS)
{
// No containers to fit magazines, stop trying
break;
}
// No space for magazine and we haven't reached desired magazine count
if (fitsIntoInventory == ItemAddedResult.NO_SPACE && i < randomizedMagazineCount) {
if (fitsIntoInventory == ItemAddedResult.NO_SPACE && i < randomizedMagazineCount)
{
// Prevent infinite loop by only allowing 5 attempts at fitting a magazine into inventory
if (fitAttempts > 5) {
if (fitAttempts > 5)
{
_logger.Debug($"Failed {fitAttempts} times to add magazine {magazineTpl} to bot inventory, stopping");
break;
@@ -91,7 +78,8 @@ public class ExternalInventoryMagGen : InventoryMagGen, IInventoryMagGen
* so we fallback to default magazine and try again.
* Temporary workaround to Killa spawning with no extra mags if he spawns with a drum mag */
if (magazineTpl == defaultMagazineTpl) {
if (magazineTpl == defaultMagazineTpl)
{
// We were already on default - stop here to prevent infinite looping
break;
}
@@ -102,7 +90,8 @@ public class ExternalInventoryMagGen : InventoryMagGen, IInventoryMagGen
// Set chosen magazine tpl to the weapons default magazine tpl and try to fit into inventory next loop
magazineTpl = defaultMagazineTpl;
magTemplate = _itemHelper.GetItem(magazineTpl).Value;
if (magTemplate is null) {
if (magTemplate is null)
{
_logger.Error(
_localisationService.GetText("bot-unable_to_find_default_magazine_item", magazineTpl)
);
@@ -111,12 +100,14 @@ public class ExternalInventoryMagGen : InventoryMagGen, IInventoryMagGen
}
// Edge case - some weapons (SKS) have an internal magazine as default, choose random non-internal magazine to add to bot instead
if (magTemplate.Properties.ReloadMagType == "InternalMagazine") {
if (magTemplate.Properties.ReloadMagType == "InternalMagazine")
{
var result = GetRandomExternalMagazineForInternalMagazineGun(
inventoryMagGen.GetWeaponTemplate().Id,
attemptedMagBlacklist
);
if (result?.Id is null) {
if (result?.Id is null)
{
_logger.Debug($"Unable to add additional magazine into bot inventory for weapon: {weapon.Name}, attempted: {fitAttempts} times");
break;
@@ -131,7 +122,8 @@ public class ExternalInventoryMagGen : InventoryMagGen, IInventoryMagGen
i--;
}
if (fitsIntoInventory == ItemAddedResult.SUCCESS) {
if (fitsIntoInventory == ItemAddedResult.SUCCESS)
{
// Reset fit counter now it succeeded
fitAttempts = 0;
}
@@ -142,21 +134,26 @@ public class ExternalInventoryMagGen : InventoryMagGen, IInventoryMagGen
{
// The mag Slot data for the weapon
var magSlot = _itemHelper.GetItem(weaponTpl).Value.Properties.Slots.FirstOrDefault((x) => x.Name == "mod_magazine");
if (magSlot is null) {
if (magSlot is null)
{
return null;
}
// All possible mags that fit into the weapon excluding blacklisted
var magazinePool = magSlot.Props.Filters[0].Filter.Where((x) => !magazineBlacklist.Contains(x)).Select(
(x) => _itemHelper.GetItem(x).Value
);
if (magazinePool is null) {
var magazinePool = magSlot.Props.Filters[0]
.Filter.Where((x) => !magazineBlacklist.Contains(x))
.Select(
(x) => _itemHelper.GetItem(x).Value
);
if (magazinePool is null)
{
return null;
}
// Non-internal magazines that fit into the weapon
var externalMagazineOnlyPool = magazinePool.Where((x) => x.Properties.ReloadMagType != "InternalMagazine");
if (externalMagazineOnlyPool is null || externalMagazineOnlyPool?.Count() == 0) {
if (externalMagazineOnlyPool is null || externalMagazineOnlyPool?.Count() == 0)
{
return null;
}
@@ -4,18 +4,10 @@ using Core.Helpers;
namespace Core.Generators.WeaponGen.Implementations;
[Injectable]
public class InternalMagazineInventoryMagGen : InventoryMagGen, IInventoryMagGen
public class InternalMagazineInventoryMagGen(
BotWeaponGeneratorHelper _botWeaponGeneratorHelper
) : InventoryMagGen, IInventoryMagGen
{
private readonly BotWeaponGeneratorHelper _botWeaponGeneratorHelper;
public InternalMagazineInventoryMagGen
(
BotWeaponGeneratorHelper botWeaponGeneratorHelper
)
{
_botWeaponGeneratorHelper = botWeaponGeneratorHelper;
}
public int GetPriority()
{
return 0;
@@ -35,7 +27,7 @@ public class InternalMagazineInventoryMagGen : InventoryMagGen, IInventoryMagGen
_botWeaponGeneratorHelper.AddAmmoIntoEquipmentSlots(
inventoryMagGen.GetAmmoTemplate().Id,
(int)bulletCount,
inventoryMagGen.GetPmcInventory(),
inventoryMagGen.GetPmcInventory(),
null
);
}
@@ -5,18 +5,11 @@ using Core.Models.Enums;
namespace Core.Generators.WeaponGen.Implementations;
[Injectable]
public class UbglExternalMagGen : InventoryMagGen, IInventoryMagGen
public class UbglExternalMagGen(
BotWeaponGeneratorHelper _botWeaponGeneratorHelper
) : InventoryMagGen, IInventoryMagGen
{
private readonly BotWeaponGeneratorHelper _botWeaponGeneratorHelper;
public UbglExternalMagGen
(
BotWeaponGeneratorHelper botWeaponGeneratorHelper
)
{
_botWeaponGeneratorHelper = botWeaponGeneratorHelper;
}
public int GetPriority()
{
return 1;
+2 -6
View File
@@ -4,7 +4,7 @@ using Core.Models.Eft.Common.Tables;
namespace Core.Generators.WeaponGen;
[Injectable]
public class InventoryMagGen
public class InventoryMagGen()
{
private GenerationData _magCounts;
private TemplateItem _magazineTemplate;
@@ -12,10 +12,6 @@ public class InventoryMagGen
private TemplateItem _ammoTemplate;
private BotBaseInventory _pmcInventory;
public InventoryMagGen()
{
}
public InventoryMagGen
(
GenerationData magCounts,
@@ -23,7 +19,7 @@ public class InventoryMagGen
TemplateItem weaponTemplate,
TemplateItem ammoTemplate,
BotBaseInventory pmcInventory
)
) : this()
{
_magCounts = magCounts;
_magazineTemplate = magazineTemplate;
+16 -34
View File
@@ -10,34 +10,16 @@ using Core.Utils;
namespace Core.Generators;
[Injectable]
public class WeatherGenerator
public class WeatherGenerator(
TimeUtil _timeUtil,
SeasonalEventService _seasonalEventService,
WeatherHelper _weatherHelper,
ConfigServer _configServer,
WeightedRandomHelper _weightedRandomHelper,
RandomUtil _randomUtil
)
{
protected TimeUtil _timeUtil;
protected SeasonalEventService _seasonalEventService;
protected WeatherHelper _weatherHelper;
protected ConfigServer _configServer;
protected WeightedRandomHelper _weightedRandomHelper;
protected RandomUtil _randomUtil;
protected WeatherConfig _weatherConfig;
public WeatherGenerator(
TimeUtil timeUtil,
SeasonalEventService seasonalEventService,
WeatherHelper weatherHelper,
ConfigServer configServer,
WeightedRandomHelper weightedRandomHelper,
RandomUtil randomUtil
)
{
_timeUtil = timeUtil;
_seasonalEventService = seasonalEventService;
_weatherHelper = weatherHelper;
_configServer = configServer;
_weightedRandomHelper = weightedRandomHelper;
_randomUtil = randomUtil;
_weatherConfig = _configServer.GetConfig<WeatherConfig>();
}
protected WeatherConfig _weatherConfig = _configServer.GetConfig<WeatherConfig>();
/**
* Get current + raid datetime and format into correct BSG format and return
@@ -47,13 +29,13 @@ public class WeatherGenerator
public void CalculateGameTime(WeatherData data)
{
var computedDate = DateTime.Now;
var formattedDate = this._timeUtil.FormatDate(computedDate);
var formattedDate = _timeUtil.FormatDate(computedDate);
data.Date = formattedDate;
data.Time = GetBsgFormattedInRaidTime();
data.Acceleration = this._weatherConfig.Acceleration;
data.Acceleration = _weatherConfig.Acceleration;
data.Season = this._seasonalEventService.GetActiveWeatherSeason();
data.Season = _seasonalEventService.GetActiveWeatherSeason();
}
/**
@@ -64,7 +46,7 @@ public class WeatherGenerator
*/
protected string GetBsgFormattedInRaidTime()
{
var clientAcceleratedDate = this._weatherHelper.GetInRaidTime();
var clientAcceleratedDate = _weatherHelper.GetInRaidTime();
return GetBsgFormattedTime(clientAcceleratedDate);
}
@@ -121,10 +103,10 @@ public class WeatherGenerator
protected SeasonalValues GetWeatherValuesBySeason(Season currentSeason)
{
var result = this._weatherConfig.Weather.SeasonValues.TryGetValue(currentSeason.ToString(), out var value);
var result = _weatherConfig.Weather.SeasonValues.TryGetValue(currentSeason.ToString(), out var value);
if (!result)
{
return this._weatherConfig.Weather.SeasonValues["default"];
return _weatherConfig.Weather.SeasonValues["default"];
}
return value!;
@@ -158,7 +140,7 @@ public class WeatherGenerator
var normalTime = GetBsgFormattedTime(inRaidTime);
var formattedDate = _timeUtil.FormatDate(timestamp.HasValue ? _timeUtil.GetDateTimeFromTimeStamp(timestamp.Value) : DateTime.UtcNow);
var datetimeBsgFormat = $"{formattedDate} {normalTime}";
weather.Timestamp = timestamp ?? _timeUtil.GetTimeStampFromEpoch(inRaidTime) / 1000; // matches weather.date
weather.Date = formattedDate; // matches weather.timestamp
weather.Time = datetimeBsgFormat; // matches weather.timestamp