Merge branch 'master' into feature/mod-chance-calculation-adjustments

This commit is contained in:
Martynas Gestautas 2021-09-01 17:39:56 +03:00
commit 63a5cecfc2
18 changed files with 372 additions and 1140 deletions

View File

@ -25,8 +25,10 @@ namespace Common
"5cadf6e5ae921500113bb973", // 12.7x55 mm PS12A "5cadf6e5ae921500113bb973", // 12.7x55 mm PS12A
"5cadf6ddae9215051e1c23b2", // 12.7x55 mm PS12 "5cadf6ddae9215051e1c23b2", // 12.7x55 mm PS12
"5ea2a8e200685063ec28c05a", // .45 acp rip "5ea2a8e200685063ec28c05a", // .45 acp rip
"5fbe3ffdf8b6a877a729ea82" // .300 aac bcp fmj "5fbe3ffdf8b6a877a729ea82", // .300 aac bcp fmj
}; "5e023e6e34d52a55c3304f71", // 7.62x51mm tcw sp
"5e023e88277cce2b522ff2b1" // 7.62x51 ultra nosler
};
public static bool BulletIsOnBlackList(string bullet) public static bool BulletIsOnBlackList(string bullet)
{ {

View File

@ -0,0 +1,15 @@
using Common.Models;
namespace Common.Extensions
{
public static class EnumExtensions
{
/// <summary>
/// Add a string to a list only if it doesnt already exist
/// </summary>
public static bool IsBoss(this BotType self)
{
return self.HasFlag(BotType.bossbully | BotType.bossgluhar | BotType.bosskilla | BotType.bosskojaniy | BotType.bosssanitar);
}
}
}

View File

@ -12,5 +12,14 @@ namespace Common.Extensions
if (!self.Contains(item)) if (!self.Contains(item))
self.Add(item); self.Add(item);
} }
public static void AddUniqueRange(this IList<string> self, IList<string> itemsToAdd)
{
foreach (var item in itemsToAdd)
{
if (!self.Contains(item))
self.Add(item);
}
}
} }
} }

28
Common/Models/BotType.cs Normal file
View File

@ -0,0 +1,28 @@
namespace Common.Models
{
public enum BotType
{
assault = 1,
pmcBot = 2,
marksman = 3,
bossbully = 4,
bossgluhar = 5,
bosskilla = 6,
bosskojaniy = 7,
bosssanitar = 8,
bosstagilla = 9,
bossstormtrooper = 10,
followerbully = 11,
followergluharassault = 12,
followergluharscout = 13,
followergluharsecurity = 14,
followergluharsnipe = 15,
followerkojaniy = 16,
followersanitar = 17,
followerstormtrooper = 18,
cursedassault = 19,
sectantpriest = 20,
sectantwarrior = 21,
usec = 22
}
}

View File

@ -1,7 +1,7 @@
using Common; using Common;
using Common.Extensions; using Common.Extensions;
using Common.Models;
using Generator.Helpers; using Generator.Helpers;
using Generator.Models;
using Generator.Models.Input; using Generator.Models.Input;
using Generator.Models.Output; using Generator.Models.Output;
using System; using System;

View File

@ -0,0 +1,50 @@
using Common;
using Generator.Helpers.Gear;
using Generator.Models.Input;
using Generator.Models.Output;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace Generator
{
internal class BotChancesGenerator
{
private readonly List<Bot> _bots;
private readonly List<Datum> _rawParsedBots;
public BotChancesGenerator(List<Bot> botsWithGearAndLoot, List<Datum> parsedBots)
{
_bots = botsWithGearAndLoot;
_rawParsedBots = parsedBots;
}
internal List<Bot> AddChances()
{
var stopwatch = Stopwatch.StartNew();
LoggingHelpers.LogToConsole("Started processing bot gear");
foreach (var botToUpdate in _bots)
{
var rawParsedBotOfCurrentType = _rawParsedBots
.Where(x => x.Info.Settings.Role.Equals(botToUpdate.botType.ToString(), StringComparison.OrdinalIgnoreCase))
.ToList();
if (rawParsedBotOfCurrentType.Count == 0)
{
continue;
}
GearChanceHelpers.CalculateEquipmentChances(botToUpdate, rawParsedBotOfCurrentType);
GearChanceHelpers.AddGenerationChances(botToUpdate);
GearChanceHelpers.CalculateModChances(botToUpdate, rawParsedBotOfCurrentType);
}
stopwatch.Stop();
LoggingHelpers.LogToConsole($"Finished processing bot chances. Took {LoggingHelpers.LogTimeTaken(stopwatch.Elapsed.TotalSeconds)} seconds");
return _bots;
}
}
}

View File

@ -37,10 +37,6 @@ namespace Generator
continue; continue;
} }
GearChanceHelpers.CalculateEquipmentChances(botToUpdate, rawParsedBotOfCurrentType);
GearChanceHelpers.AddGenerationChances(botToUpdate);
GearChanceHelpers.CalculateModChances(botToUpdate, rawParsedBotOfCurrentType);
foreach (var rawParsedBot in rawParsedBotOfCurrentType) foreach (var rawParsedBot in rawParsedBotOfCurrentType)
{ {
GearHelpers.AddEquippedGear(botToUpdate, rawParsedBot); GearHelpers.AddEquippedGear(botToUpdate, rawParsedBot);

View File

@ -1,12 +1,14 @@
using Common; using Common;
using Common.Extensions; using Common.Extensions;
using Generator.Helpers; using Generator.Helpers;
using Generator.Helpers.Gear;
using Generator.Models.Input; using Generator.Models.Input;
using Generator.Models.Output; using Generator.Models.Output;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
namespace Generator namespace Generator
{ {
@ -27,15 +29,15 @@ namespace Generator
LoggingHelpers.LogToConsole("Started processing bot loot"); LoggingHelpers.LogToConsole("Started processing bot loot");
// Iterate over assault/raider etc // Iterate over assault/raider etc
foreach (var botToUpdate in _botsWithGear) Parallel.ForEach(_botsWithGear, botToUpdate =>
{ {
var rawBotsOfSameType = _rawParsedBots var rawBotsOfSameType = _rawParsedBots
.Where(x => x.Info.Settings.Role.Equals(botToUpdate.botType.ToString(), StringComparison.OrdinalIgnoreCase)) .Where(x => x.Info.Settings.Role.Equals(botToUpdate.botType.ToString(), StringComparison.OrdinalIgnoreCase))
.ToList(); .ToList();
if (rawBotsOfSameType.Count == 0) if (rawBotsOfSameType.Count == 0)
{ {
continue; return;
} }
foreach (var rawParsedBot in rawBotsOfSameType) foreach (var rawParsedBot in rawBotsOfSameType)
@ -44,9 +46,10 @@ namespace Generator
} }
AddTacticalVestLoot(botToUpdate, rawBotsOfSameType); AddTacticalVestLoot(botToUpdate, rawBotsOfSameType);
AddBackbackLoot(botToUpdate, rawBotsOfSameType); AddBackpackLoot(botToUpdate, rawBotsOfSameType);
AddSecureContainerLoot(botToUpdate, rawBotsOfSameType); AddSecureContainerLoot(botToUpdate, rawBotsOfSameType);
} AddSpecialLoot(botToUpdate);
});
stopwatch.Stop(); stopwatch.Stop();
LoggingHelpers.LogToConsole($"Finished processing bot loot. Took: {LoggingHelpers.LogTimeTaken(stopwatch.Elapsed.TotalSeconds)} seconds"); LoggingHelpers.LogToConsole($"Finished processing bot loot. Took: {LoggingHelpers.LogTimeTaken(stopwatch.Elapsed.TotalSeconds)} seconds");
@ -54,24 +57,6 @@ namespace Generator
return _botsWithGear; return _botsWithGear;
} }
private void AddTacticalVestLoot(Bot finalAssaultBot, List<Datum> bots)
{
var tacVestItems = GetItemsStoredInEquipmentItem(bots, "TacticalVest");
finalAssaultBot.inventory.items.TacticalVest.AddRange(tacVestItems);
}
private void AddBackbackLoot(Bot finalAssaultBot, List<Datum> bots)
{
var backpackItems = GetItemsStoredInEquipmentItem(bots, "Backpack");
finalAssaultBot.inventory.items.Backpack.AddRange(backpackItems);
}
private void AddSecureContainerLoot(Bot finalAssaultBot, List<Datum> bots)
{
var tacVestItems = GetItemsStoredInEquipmentItem(bots, "SecuredContainer");
finalAssaultBot.inventory.items.SecuredContainer.AddRange(tacVestItems);
}
private void AddPocketLoot(Bot finalBot, Datum bot) private void AddPocketLoot(Bot finalBot, Datum bot)
{ {
// pocket loot // pocket loot
@ -81,6 +66,35 @@ namespace Generator
} }
} }
private void AddTacticalVestLoot(Bot finalBot, List<Datum> bots)
{
var tacVestItems = GetItemsStoredInEquipmentItem(bots, "TacticalVest");
finalBot.inventory.items.TacticalVest.AddRange(tacVestItems);
}
private void AddBackpackLoot(Bot finalBot, List<Datum> bots)
{
// add generic keys to bosses
if (finalBot.botType.IsBoss())
{
finalBot.inventory.items.Backpack.AddRange(SpecialLootHelper.GetGenericBossKeys());
}
var backpackItems = GetItemsStoredInEquipmentItem(bots, "Backpack");
finalBot.inventory.items.Backpack.AddRange(backpackItems);
}
private void AddSecureContainerLoot(Bot finalAssaultBot, List<Datum> bots)
{
var tacVestItems = GetItemsStoredInEquipmentItem(bots, "SecuredContainer");
finalAssaultBot.inventory.items.SecuredContainer.AddRange(tacVestItems);
}
private void AddSpecialLoot(Bot botToUpdate)
{
botToUpdate.inventory.items.SpecialLoot.AddRange(SpecialLootHelper.GetSpecialLootForBotType(botToUpdate.botType));
}
private List<string> GetItemsStoredInEquipmentItem(List<Datum> bots, string containerName) private List<string> GetItemsStoredInEquipmentItem(List<Datum> bots, string containerName)
{ {
var itemsStoredInContainer = new List<string>(); var itemsStoredInContainer = new List<string>();

View File

@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
namespace Generator namespace Generator
{ {
@ -30,22 +31,20 @@ namespace Generator
Console.WriteLine($"{botFiles.Count} bot dump files found"); Console.WriteLine($"{botFiles.Count} bot dump files found");
var parsedBots = new List<Datum>(); var parsedBots = new List<Datum>();
foreach (var file in botFiles) Parallel.ForEach(botFiles, file => {
{
var splitFile = file.Split("\\"); var splitFile = file.Split("\\");
var json = File.ReadAllText(file); var json = File.ReadAllText(file);
try try
{ {
json = PruneMalformedBsgJson(json, splitFile.Last()); json = PruneMalformedBsgJson(json, splitFile.Last());
var bots = ParseJson(json, file); var bots = ParseJson(json);
if (bots == null || bots.Count == 0) if (bots == null || bots.Count == 0)
{ {
Console.WriteLine($"skipping file: {splitFile.Last()}. no bots found, "); Console.WriteLine($"skipping file: {splitFile.Last()}. no bots found, ");
continue; return;
} }
Console.WriteLine($"parsing: {bots.Count} bots in file {splitFile.Last()}"); Console.WriteLine($"parsing: {bots.Count} bots in file {splitFile.Last()}");
@ -59,7 +58,7 @@ namespace Generator
failedFilesCount++; failedFilesCount++;
Console.WriteLine($"JSON Error message: {jex.Message} || file: {splitFile.Last()}"); Console.WriteLine($"JSON Error message: {jex.Message} || file: {splitFile.Last()}");
} }
} });
stopwatch.Stop(); stopwatch.Stop();
LoggingHelpers.LogToConsole($"Cleaned and Parsed: {parsedBots.Count} bots. Failed: {failedFilesCount}. Took {LoggingHelpers.LogTimeTaken(stopwatch.Elapsed.TotalSeconds)} seconds"); LoggingHelpers.LogToConsole($"Cleaned and Parsed: {parsedBots.Count} bots. Failed: {failedFilesCount}. Took {LoggingHelpers.LogTimeTaken(stopwatch.Elapsed.TotalSeconds)} seconds");
@ -87,10 +86,10 @@ namespace Generator
return o.ToString(); return o.ToString();
} }
private static List<Datum> ParseJson(string json, string file) private static List<Datum> ParseJson(string json)
{ {
//Console.WriteLine($"parsing file {file}"); var serialisedObject = JsonConvert.DeserializeObject<Root>(json);
var serialisedObject = JsonConvert.DeserializeObject<Models.Input.Root>(json);
return serialisedObject.data; return serialisedObject.data;
} }
} }

View File

@ -16,7 +16,7 @@ namespace Generator.Helpers
// Read bot setting files from assets folder that match this bots type // Read bot setting files from assets folder that match this bots type
// Save into dictionary with difficulty as key // Save into dictionary with difficulty as key
var difficultySettingsJsons = new Dictionary<string, DifficultySettings>(); var difficultySettingsJsons = new Dictionary<string, DifficultySettings>();
foreach (var path in difficultyFilePaths.Where(x=>x.Contains($"_{bot.botType.ToString()}", System.StringComparison.InvariantCultureIgnoreCase))) foreach (var path in difficultyFilePaths.Where(x=>x.Contains($"_{bot.botType}", System.StringComparison.InvariantCultureIgnoreCase)))
{ {
var json = File.ReadAllText(path); var json = File.ReadAllText(path);
var serialisedObject = JsonConvert.DeserializeObject<DifficultySettings>(json); var serialisedObject = JsonConvert.DeserializeObject<DifficultySettings>(json);
@ -46,7 +46,7 @@ namespace Generator.Helpers
// Split path into parts and find the last part (filename) // Split path into parts and find the last part (filename)
// Split filename and take the first part (difficulty, easy/normal etc) // Split filename and take the first part (difficulty, easy/normal etc)
var splitPath = path.Split("\\"); var splitPath = path.Split("\\");
return splitPath.Last().Split("_").First(); return splitPath.Last().Split("_")[0];
} }
private static void SaveSettingsIntoBotFile(Bot bot, string difficulty, DifficultySettings settings) private static void SaveSettingsIntoBotFile(Bot bot, string difficulty, DifficultySettings settings)

View File

@ -123,16 +123,8 @@ namespace Generator.Helpers.Gear
public static void AddGenerationChances(Bot bot) public static void AddGenerationChances(Bot bot)
{ {
switch (bot.botType) bot.generation = new GenerationChances(bot.inventory.items.SpecialLoot.Count, bot.inventory.items.SpecialLoot.Count, 1, 2, 0, 3, 2, 4, 0, 5); //TODO get dynamically
{
case BotType.assault:
case BotType.pmcBot:
case BotType.marksman:
bot.generation = new GenerationChances(0, 1, 1, 2, 0, 3, 2, 4, 0, 5); //TODO get dynamically
break;
}
} }
public static void CalculateEquipmentChances(Bot bot, List<Datum> baseBots) public static void CalculateEquipmentChances(Bot bot, List<Datum> baseBots)
{ {
// TODO: Convert to dynamic? // TODO: Convert to dynamic?

View File

@ -0,0 +1,123 @@
using Common.Models;
using Generator.Models;
using System.Collections.Generic;
namespace Generator.Helpers.Gear
{
public static class SpecialLootHelper
{
private static readonly List<string> _genericBossKeys = new List<string>()
{
"5c1d0d6d86f7744bb2683e1f", // "TerraGroup Labs keycard (Yellow)",
"5c1d0c5f86f7744bb2683cf0", // "TerraGroup Labs keycard (Blue)",
"5c1e495a86f7743109743dfb", // "TerraGroup Labs keycard (Violet)",
"5c1d0dc586f7744baf2e7b79", // "TerraGroup Labs keycard (Green)",
"5c1d0efb86f7744baf2e7b7b", // "TerraGroup Labs keycard (Red)",
"5c1d0f4986f7744bb01837fa", // "TerraGroup Labs keycard (Black)",
"5c94bbff86f7747ee735c08f", // "TerraGroup Labs access keycard",
"5e42c83786f7742a021fdf3c", // "Object #21WS keycard",
"5e42c81886f7742a01529f57", // "Object #11SR keycard",
"59136a4486f774447a1ed172", // "Dorm guard desk key",
"5780cf7f2459777de4559322", // "Dorm room 314 marked key",
"5d80c60f86f77440373c4ece", // "RB-BK marked key",
"5d80c62a86f7744036212b3f", // "RB-VO marked key",
"5ede7a8229445733cb4c18e2", // "RB-PKPM marked key",
"5da743f586f7744014504f72", // "USEC Customs stash key",
"5d8e15b686f774445103b190", // "HEP station storage room key",
"5a13f24186f77410e57c5626", // "Health Resort east wing room 222 key",
"5448ba0b4bdc2d02308b456c", // "Factory emergency exit key",
"5a1452ee86f7746f33111763", // "Health Resort west wing room 222 key",
"5a13f35286f77413ef1436b0", // "Health Resort east wing room 226 key",
"5a0eec9686f77402ac5c39f2", // "Health Resort east wing room 310 key",
"5a13ef7e86f7741290491063", // "Health Resort west wing room 301 key",
"5a0ee30786f774023b6ee08f", // "Health Resort west wing room 216 key",
"5a0ee76686f7743698200d5c", // "Health Resort east wing room 216 key",
"5913877a86f774432f15d444", // "Gas station storage room key",
"5780d0652459777df90dcb74", // "Gas station office key",
"5d80c88d86f77440556dbf07", // "RB-AM key",
"5ede7b0c6d23e5473e6e8c66", // "RB-RLSA key",
"5d8e0e0e86f774321140eb56", // "RB-KPRL key",
"5d80cb3886f77440556dbf09", // "RB-PSP1 key",
"5d95d6fa86f77424484aa5e9", // "RB-PSP2 key",
"5d80cb5686f77440545d1286", // "RB-PSV1 key",
"5d80c6fc86f774403a401e3c", // "RB-TB key",
"5d9f1fa686f774726974a992", // "RB-ST key",
"5d947d3886f774447b415893", // "RB-SMP key",
"5e42c71586f7747f245e1343", // "ULTRA medical storage key",
"5ad5d7d286f77450166e0a89", // "KIBA Arms International outlet outer door key",
"5addaffe86f77470b455f900", // "KIBA Arms International outlet inner grate door key",
"5ad5d64486f774079b080af8", // "NecrusPharm pharmacy key",
"591afe0186f77431bd616a11", // "ZB-014 key",
"5c1e2d1f86f77431e9280bee", // "TerraGroup Labs Weapons testing area key",
"5c1f79a086f7746ed066fb8f", // "TerraGroup Labs Arsenal storage room key",
"5c1e2a1e86f77431ea0ea84c", // "TerraGroup Labs Manager office room key",
"5a144bdb86f7741d374bbde0", // "Health Resort east wing room 205 key",
"5a0ee4b586f7743698200d22", // "Health Resort east wing room 206 key",
"5a145d4786f7744cbb6f4a12", // "Health Resort east wing room 306 key",
"5a145d7b86f7744cbb6f4a13", // "Health Resort east wing room 308 key",
"5a0eecf686f7740350630097", // "Health Resort east wing room 313 key",
"5a0eee1486f77402aa773226" // "Health Resort east wing room 328 key"
};
public static IEnumerable<string> GetGenericBossKeys()
{
return _genericBossKeys;
}
public static IEnumerable<string> GetSpecialLootForBotType(BotType botType)
{
var results = new List<string>();
switch (botType)
{
case BotType.assault:
break;
case BotType.pmcBot:
break;
case BotType.marksman:
break;
case BotType.bossbully:
break;
case BotType.bossgluhar:
break;
case BotType.bosskilla:
break;
case BotType.bosskojaniy:
results.Add("5d08d21286f774736e7c94c3"); // Shturman's stash key
break;
case BotType.bosssanitar:
results.Add("5efde6b4f5448336730dbd61"); // Keycard with a blue marking
break;
case BotType.bossstormtrooper:
break;
case BotType.followerbully:
break;
case BotType.followergluharassault:
break;
case BotType.followergluharscout:
break;
case BotType.followergluharsecurity:
break;
case BotType.followergluharsnipe:
break;
case BotType.followerkojaniy:
break;
case BotType.followersanitar:
break;
case BotType.followerstormtrooper:
break;
case BotType.cursedassault:
break;
case BotType.sectantpriest:
break;
case BotType.sectantwarrior:
break;
case BotType.usec:
break;
default:
break;
}
return results;
}
}
}

View File

@ -1,26 +0,0 @@
namespace Generator.Models
{
public enum BotType
{
assault = 1,
pmcBot = 2,
marksman = 3,
bossbully = 4,
bossgluhar = 5,
bosskilla = 6,
bosskojaniy = 7,
bosssanitar = 8,
bossstormtrooper = 9,
followerbully = 10,
followergluharassault = 11,
followergluharscout = 12,
followergluharsecurity = 13,
followergluharsnipe = 14,
followerkojaniy = 15,
followersanitar = 16,
followerstormtrooper = 17,
cursedassault = 18,
sectantpriest = 19,
sectantwarrior = 20
}
}

File diff suppressed because it is too large Load Diff

View File

@ -60,11 +60,13 @@ namespace Generator.Models.Output
Pockets = new List<string>(); Pockets = new List<string>();
Backpack = new List<string>(); Backpack = new List<string>();
SecuredContainer = new List<string>(); SecuredContainer = new List<string>();
SpecialLoot = new List<string>();
} }
public List<string> TacticalVest { get; set; } public List<string> TacticalVest { get; set; }
public List<string> Pockets { get; set; } public List<string> Pockets { get; set; }
public List<string> Backpack { get; set; } public List<string> Backpack { get; set; }
public List<string> SecuredContainer { get; set; } public List<string> SecuredContainer { get; set; }
public List<string> SpecialLoot { get; set; }
} }
} }

View File

@ -1,4 +1,5 @@
using Newtonsoft.Json; using Common.Models;
using Newtonsoft.Json;
using System.Collections.Generic; using System.Collections.Generic;
namespace Generator.Models.Output namespace Generator.Models.Output

View File

@ -17,6 +17,7 @@ namespace Generator
"bosskilla", "bosskilla",
"bosskojaniy", "bosskojaniy",
"bosssanitar", "bosssanitar",
"bosstagilla",
//"bossstormtrooper", //"bossstormtrooper",
"followerbully", "followerbully",
@ -59,9 +60,13 @@ namespace Generator
var botLootGenerator = new BotLootGenerator(botsWithGear, parsedBots); var botLootGenerator = new BotLootGenerator(botsWithGear, parsedBots);
var botsWithGearAndLoot = botLootGenerator.AddLoot(); var botsWithGearAndLoot = botLootGenerator.AddLoot();
// Add mod/equipment chances
var botChancesGenerator = new BotChancesGenerator(botsWithGearAndLoot, parsedBots);
var botsWithGearAndLootAndChances = botChancesGenerator.AddChances();
// Output bot to json file // Output bot to json file
var jsonWriter = new JsonWriter(workingPath, "output"); var jsonWriter = new JsonWriter(workingPath, "output");
jsonWriter.WriteJson(botsWithGearAndLoot); jsonWriter.WriteJson(botsWithGearAndLootAndChances);
} }
} }
} }

View File

@ -21,6 +21,9 @@ namespace PMCGenerator
// Create flat lists of weapons + list of mods // Create flat lists of weapons + list of mods
var flatPrimaryWeaponsList = GetWeaponsFromRawFile(parsedPresets); var flatPrimaryWeaponsList = GetWeaponsFromRawFile(parsedPresets);
var flatSecondaryWeaponsList = GetSecondaryWeaponsFromRawFile(parsedPresets); var flatSecondaryWeaponsList = GetSecondaryWeaponsFromRawFile(parsedPresets);
var flatAllWeaponsList = CombinePrimaryAndSecondaryWeapons(flatPrimaryWeaponsList, flatSecondaryWeaponsList);
var flatModList = GetModsFromRawFile(parsedPresets); var flatModList = GetModsFromRawFile(parsedPresets);
// Add weapon mods to output // Add weapon mods to output
@ -28,10 +31,12 @@ namespace PMCGenerator
FirstPrimaryWeapon = new List<string>(), FirstPrimaryWeapon = new List<string>(),
Holster = new List<string>(), Holster = new List<string>(),
mods = new Dictionary<string, Dictionary<string, List<string>>>() }; mods = new Dictionary<string, Dictionary<string, List<string>>>() };
output.FirstPrimaryWeapon.AddRange(flatPrimaryWeaponsList.Select(x => x.TemplateId).Distinct()); output.FirstPrimaryWeapon.AddRange(flatPrimaryWeaponsList.Select(x => x.TemplateId).Distinct());
output.Holster.AddRange(flatSecondaryWeaponsList.Select(x => x.TemplateId).Distinct()); output.Holster.AddRange(flatSecondaryWeaponsList.Select(x => x.TemplateId).Distinct());
foreach (var weapon in flatPrimaryWeaponsList) // Loop over each gun
foreach (var weapon in flatAllWeaponsList)
{ {
// add weapon if its not already here // add weapon if its not already here
if (!output.mods.ContainsKey(weapon.TemplateId)) if (!output.mods.ContainsKey(weapon.TemplateId))
@ -40,7 +45,7 @@ namespace PMCGenerator
output.mods.Add(weapon.TemplateId, new Dictionary<string, List<string>>()); output.mods.Add(weapon.TemplateId, new Dictionary<string, List<string>>());
} }
// Get mods types for this gun, top level // Get top level mods types for this gun
var uniqueModSlots = flatModList.Where(x => x.ParentId == weapon.Id).Select(x => x.SlotId).Distinct().ToList(); var uniqueModSlots = flatModList.Where(x => x.ParentId == weapon.Id).Select(x => x.SlotId).Distinct().ToList();
var chamberedBulletModItemName = "patron_in_weapon"; var chamberedBulletModItemName = "patron_in_weapon";
uniqueModSlots.AddUnique(chamberedBulletModItemName); uniqueModSlots.AddUnique(chamberedBulletModItemName);
@ -55,17 +60,9 @@ namespace PMCGenerator
} }
// Add compatible bullets to weapons gun chamber // Add compatible bullets to weapons gun chamber
var modItemToAddBulletsTo = output.mods[weapon.TemplateId].FirstOrDefault(x=> x.Key == chamberedBulletModItemName); var modItemToAddBulletsTo = output.mods[weapon.TemplateId].FirstOrDefault(x => x.Key == chamberedBulletModItemName);
var compatibleBullets = GetCompatibileBullets(itemLibrary, weapon);
foreach (var bullet in GetCompatibileBullets(itemLibrary, weapon)) modItemToAddBulletsTo.Value.AddUniqueRange(compatibleBullets);
{
if (BulletHelpers.BulletIsOnBlackList(bullet))
{
continue;
}
modItemToAddBulletsTo.Value.AddUnique(bullet);
}
// Add compatabible mods to weapon // Add compatabible mods to weapon
var modsForWeapon = flatModList.Where(x => x.ParentId == weapon.Id).ToList(); var modsForWeapon = flatModList.Where(x => x.ParentId == weapon.Id).ToList();
@ -73,6 +70,12 @@ namespace PMCGenerator
foreach (var mod in modsForWeapon) foreach (var mod in modsForWeapon)
{ {
weaponMods[mod.SlotId].AddUnique(mod.TemplateId); weaponMods[mod.SlotId].AddUnique(mod.TemplateId);
if (mod.SlotId == "mod_magazine")
{
// add special mod item for magazine that gives info on what cartridges can be used
AddCartridgeItemToModListWithCompatibileCartridges(output.mods, compatibleBullets, mod);
}
} }
} }
@ -110,6 +113,35 @@ namespace PMCGenerator
CreateJsonFile(outputPath, outputJson); CreateJsonFile(outputPath, outputJson);
} }
private static List<WeaponDetails> CombinePrimaryAndSecondaryWeapons(List<WeaponDetails> flatPrimaryWeaponsList, List<WeaponDetails> flatSecondaryWeaponsList)
{
var result = new List<WeaponDetails>();
result.AddRange(flatPrimaryWeaponsList);
result.AddRange(flatSecondaryWeaponsList);
return result;
}
private static void AddCartridgeItemToModListWithCompatibileCartridges(Dictionary<string, Dictionary<string, List<string>>> mods, List<string> compatibiltBullets, ModDetails mod)
{
var cartridges = new Dictionary<string, List<string>>
{
{ "cartridges", compatibiltBullets }
};
if (!mods.ContainsKey(mod.TemplateId))
{
mods.Add(mod.TemplateId, cartridges); // no item at all, create fresh
}
else
{
// Item exists, iterate over bullets and add if they dont exist
foreach (var bullet in compatibiltBullets)
{
mods[mod.TemplateId]["cartridges"].AddUnique(bullet);
}
}
}
/// <summary> /// <summary>
/// Get a strongly typed dictionary of BSGs items library /// Get a strongly typed dictionary of BSGs items library
/// </summary> /// </summary>
@ -124,6 +156,9 @@ namespace PMCGenerator
} }
/// <summary>
/// Get combatible bullets for weapon that are not blacklisted
/// </summary>
private static List<string> GetCompatibileBullets(Dictionary<string, Item> itemLibrary, WeaponDetails weapon) private static List<string> GetCompatibileBullets(Dictionary<string, Item> itemLibrary, WeaponDetails weapon)
{ {
// Lookup weapon in itemdb // Lookup weapon in itemdb
@ -132,11 +167,27 @@ namespace PMCGenerator
// Find the guns chamber and the bullets it can use // Find the guns chamber and the bullets it can use
var bullets = weaponInLibrary._props.Chambers.FirstOrDefault()?._props.filters[0]?.filter.ToList(); var bullets = weaponInLibrary._props.Chambers.FirstOrDefault()?._props.filters[0]?.filter.ToList();
// return bullets or return default ammo type // no bullets found, return the default bullet the gun can use
return bullets ?? new List<string> if (bullets == null)
{
return new List<string>
{ {
weaponInLibrary._props.defAmmo weaponInLibrary._props.defAmmo
}; };
}
var nonBlacklistedBullets = new List<string>();
foreach (var bullet in bullets)
{
if (BulletHelpers.BulletIsOnBlackList(bullet))
{
continue;
}
nonBlacklistedBullets.AddUnique(bullet);
}
return nonBlacklistedBullets;
} }
/// <summary> /// <summary>