2021-09-01 19:19:44 +03:00
|
|
|
|
using System;
|
2021-09-18 22:36:59 +01:00
|
|
|
|
using Common.Models.Input;
|
|
|
|
|
using Common.Models.Output;
|
2021-08-13 19:49:32 +01:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
2021-09-06 17:34:10 +01:00
|
|
|
|
using Common.Models;
|
2023-08-21 16:32:20 +01:00
|
|
|
|
using Generator.Weighting;
|
2021-08-13 16:24:05 +01:00
|
|
|
|
|
|
|
|
|
namespace Generator.Helpers.Gear
|
|
|
|
|
{
|
|
|
|
|
public static class GearChanceHelpers
|
|
|
|
|
{
|
2021-08-13 19:49:32 +01:00
|
|
|
|
public static void CalculateModChances(Bot bot, List<Datum> baseBots)
|
2021-08-13 16:24:05 +01:00
|
|
|
|
{
|
2021-09-01 17:39:50 +03:00
|
|
|
|
// TODO: Further split these counts by equipment slot? (ex. "FirstPrimaryWeapon", "Holster", etc.)
|
|
|
|
|
|
2024-01-01 20:29:58 +00:00
|
|
|
|
var validSlots = new List<string> { "FirstPrimaryWeapon", "SecondPrimaryWeapon", "Holster", "Headwear", "ArmorVest" };
|
2021-09-01 17:39:50 +03:00
|
|
|
|
|
|
|
|
|
var modCounts = new Dictionary<string, int>();
|
|
|
|
|
var slotCounts = new Dictionary<string, int>();
|
2021-08-13 19:49:32 +01:00
|
|
|
|
|
|
|
|
|
foreach (var baseBot in baseBots)
|
2021-08-13 16:24:05 +01:00
|
|
|
|
{
|
2021-09-01 17:39:50 +03:00
|
|
|
|
var validParents = new List<string>();
|
|
|
|
|
|
|
|
|
|
foreach (var inventoryItem in baseBot.Inventory.items)
|
|
|
|
|
{
|
|
|
|
|
if (validSlots.Contains(inventoryItem.slotId))
|
|
|
|
|
{
|
|
|
|
|
validParents.Add(inventoryItem._id);
|
|
|
|
|
}
|
|
|
|
|
else if (validParents.Contains(inventoryItem.parentId))
|
|
|
|
|
{
|
|
|
|
|
validParents.Add(inventoryItem._id);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var template = ItemTemplateHelper.GetTemplateById(inventoryItem._tpl);
|
|
|
|
|
var parentTemplate = ItemTemplateHelper.GetTemplateById(baseBot.Inventory.items.Single(i => i._id == inventoryItem.parentId)._tpl);
|
|
|
|
|
|
2024-01-01 20:29:58 +00:00
|
|
|
|
if (!(parentTemplate?._props?.Slots?.FirstOrDefault(slot => slot._name == inventoryItem.slotId)?._required ?? false))
|
2021-09-01 17:39:50 +03:00
|
|
|
|
{
|
2024-01-01 20:29:58 +00:00
|
|
|
|
if (modCounts.ContainsKey(inventoryItem.slotId.ToLower()))
|
2021-09-01 17:39:50 +03:00
|
|
|
|
{
|
2024-01-01 20:29:58 +00:00
|
|
|
|
modCounts[inventoryItem.slotId.ToLower()]++;
|
2021-09-01 17:39:50 +03:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-01-01 20:29:58 +00:00
|
|
|
|
modCounts.Add(inventoryItem.slotId.ToLower(), 1);
|
2021-09-01 17:39:50 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((template?._props?.Slots?.Count ?? 0) < 1)
|
|
|
|
|
{
|
|
|
|
|
// Item has no slots, nothing to count here
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-01 20:29:58 +00:00
|
|
|
|
foreach (var slot in template._props.Slots)
|
2021-09-01 17:39:50 +03:00
|
|
|
|
{
|
2024-01-01 20:29:58 +00:00
|
|
|
|
if (slot._name == "Back_plate")
|
|
|
|
|
{
|
|
|
|
|
var x = 1;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-01 17:39:50 +03:00
|
|
|
|
if (slot._required)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-01 20:29:58 +00:00
|
|
|
|
if (slot._name.StartsWith("camora"))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (slotCounts.ContainsKey(slot._name.ToLower()))
|
2021-09-01 17:39:50 +03:00
|
|
|
|
{
|
2024-01-01 20:29:58 +00:00
|
|
|
|
slotCounts[slot._name.ToLower()]++;
|
2021-09-01 17:39:50 +03:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-01-01 20:29:58 +00:00
|
|
|
|
slotCounts.Add(slot._name.ToLower(), 1);
|
2021-09-01 17:39:50 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-08-13 16:24:05 +01:00
|
|
|
|
}
|
2021-08-13 19:49:32 +01:00
|
|
|
|
|
2021-09-01 17:39:50 +03:00
|
|
|
|
bot.chances.mods = slotCounts.ToDictionary(
|
|
|
|
|
kvp => kvp.Key,
|
|
|
|
|
kvp => GetPercent(kvp.Value, modCounts.GetValueOrDefault(kvp.Key)));
|
2021-08-13 19:49:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-08 09:44:38 +01:00
|
|
|
|
internal static void ApplyEquipmentChanceOverrides(Bot botToUpdate)
|
|
|
|
|
{
|
|
|
|
|
switch (botToUpdate.botType)
|
|
|
|
|
{
|
|
|
|
|
case BotType.bosstagilla:
|
2021-10-08 09:58:55 +01:00
|
|
|
|
botToUpdate.chances.equipment.FaceCover = 100;
|
2021-10-08 09:44:38 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-08 08:00:39 +01:00
|
|
|
|
public static void ApplyModChanceOverrides(Bot botToUpdate)
|
|
|
|
|
{
|
|
|
|
|
switch (botToUpdate.botType)
|
|
|
|
|
{
|
2021-09-08 08:30:42 +01:00
|
|
|
|
case BotType.bosskojaniy:
|
|
|
|
|
botToUpdate.chances.mods["mod_stock"] = 100;
|
|
|
|
|
botToUpdate.chances.mods["mod_scope"] = 100;
|
|
|
|
|
break;
|
2021-09-08 08:00:39 +01:00
|
|
|
|
case BotType.bosstagilla:
|
|
|
|
|
botToUpdate.chances.mods["mod_tactical"] = 100; // force ultima thermal camera
|
|
|
|
|
botToUpdate.chances.mods["mod_stock"] = 100;
|
2021-09-18 22:36:59 +01:00
|
|
|
|
break;
|
2021-10-09 13:59:30 +01:00
|
|
|
|
case BotType.bossbully:
|
|
|
|
|
botToUpdate.chances.mods["mod_stock"] = 100;
|
|
|
|
|
break;
|
2021-12-20 10:45:19 +00:00
|
|
|
|
case BotType.bosskilla:
|
|
|
|
|
botToUpdate.chances.mods["mod_stock"] = 100;
|
|
|
|
|
botToUpdate.chances.mods["mod_stock_001"] = 100;
|
|
|
|
|
break;
|
|
|
|
|
case BotType.bosssanitar:
|
|
|
|
|
botToUpdate.chances.mods["mod_scope"] = 100;
|
|
|
|
|
break;
|
2023-08-15 09:29:16 +00:00
|
|
|
|
case BotType.pmcbot:
|
2021-09-18 22:36:59 +01:00
|
|
|
|
botToUpdate.chances.mods["mod_stock"] = 100;
|
2021-09-08 08:00:39 +01:00
|
|
|
|
break;
|
2021-10-08 09:14:29 +01:00
|
|
|
|
case BotType.followerbully:
|
|
|
|
|
botToUpdate.chances.mods["mod_stock"] = 100;
|
2021-12-20 10:45:19 +00:00
|
|
|
|
botToUpdate.chances.mods["mod_stock_000"] = 100;
|
2021-10-08 09:14:29 +01:00
|
|
|
|
break;
|
|
|
|
|
case BotType.followergluharassault:
|
|
|
|
|
case BotType.followergluharscout:
|
|
|
|
|
case BotType.followergluharsecurity:
|
|
|
|
|
case BotType.followergluharsnipe:
|
|
|
|
|
botToUpdate.chances.mods["mod_stock"] = 100;
|
|
|
|
|
break;
|
|
|
|
|
case BotType.followerkojaniy:
|
|
|
|
|
botToUpdate.chances.mods["mod_stock"] = 100;
|
|
|
|
|
break;
|
|
|
|
|
case BotType.sectantpriest:
|
|
|
|
|
botToUpdate.chances.mods["mod_stock"] = 100;
|
|
|
|
|
break;
|
|
|
|
|
case BotType.sectantwarrior:
|
|
|
|
|
botToUpdate.chances.mods["mod_stock"] = 100;
|
2021-10-08 09:48:26 +01:00
|
|
|
|
break;
|
|
|
|
|
case BotType.marksman:
|
|
|
|
|
botToUpdate.chances.mods["mod_scope"] = 100;
|
2021-12-20 10:45:19 +00:00
|
|
|
|
botToUpdate.chances.mods["mod_stock"] = 100;
|
|
|
|
|
break;
|
2023-08-15 09:29:16 +00:00
|
|
|
|
case BotType.exusec:
|
|
|
|
|
botToUpdate.chances.mods["mod_stock"] = 100;
|
2021-12-20 10:45:19 +00:00
|
|
|
|
botToUpdate.chances.mods["mod_stock_000"] = 100;
|
2023-08-15 09:29:16 +00:00
|
|
|
|
botToUpdate.chances.mods["mod_stock_001"] = 100;
|
2021-10-08 09:14:29 +01:00
|
|
|
|
break;
|
|
|
|
|
|
2021-09-08 08:00:39 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-18 17:15:30 +01:00
|
|
|
|
public static void AddGenerationChances(Bot bot, WeightingService weightingService)
|
2021-08-13 16:24:05 +01:00
|
|
|
|
{
|
2023-08-21 16:32:20 +01:00
|
|
|
|
var weightsData = weightingService.GetBotGenerationWeights(bot.botType);
|
2021-09-06 17:34:10 +01:00
|
|
|
|
bot.generation = new GenerationChances(
|
2023-08-21 16:32:20 +01:00
|
|
|
|
weightsData["specialItems"],
|
|
|
|
|
weightsData["healing"],
|
|
|
|
|
weightsData["drugs"],
|
|
|
|
|
weightsData["stims"],
|
|
|
|
|
weightsData["backpackLoot"],
|
|
|
|
|
weightsData["pocketLoot"],
|
|
|
|
|
weightsData["vestLoot"],
|
|
|
|
|
weightsData["magazines"],
|
|
|
|
|
weightsData["grenades"]);
|
|
|
|
|
|
|
|
|
|
// it makes some crazy values, one assault bot has 10 grenades!
|
|
|
|
|
//AddGrenadeMinMax(bot, rawBots);
|
|
|
|
|
|
2021-08-13 16:24:05 +01:00
|
|
|
|
}
|
2021-09-06 17:34:10 +01:00
|
|
|
|
|
2021-08-13 19:49:32 +01:00
|
|
|
|
public static void CalculateEquipmentChances(Bot bot, List<Datum> baseBots)
|
2021-08-13 16:24:05 +01:00
|
|
|
|
{
|
2021-09-01 17:39:50 +03:00
|
|
|
|
// TODO: Convert to dynamic?
|
2021-08-13 19:49:32 +01:00
|
|
|
|
var totalBotsCount = baseBots.Count;
|
2021-08-14 09:53:00 +01:00
|
|
|
|
int headwearCount = 0, earCount = 0, faceCoverCount = 0, armorVestCount = 0, eyeWearCount = 0, armBandCount = 0,
|
2021-08-13 19:49:32 +01:00
|
|
|
|
tacticalVestCount = 0, backpackCount = 0, firstPrimaryCount = 0, secondPrimaryCount = 0, holsterCount = 0,
|
|
|
|
|
scabbardCount = 0, pocketsCount = 0, securedContainerCount = 0;
|
|
|
|
|
|
|
|
|
|
foreach (var baseBot in baseBots)
|
2021-08-13 16:24:05 +01:00
|
|
|
|
{
|
2021-08-14 09:53:00 +01:00
|
|
|
|
headwearCount += baseBot.Inventory.items.Count(x => x.slotId == "Headwear");
|
2021-08-13 19:49:32 +01:00
|
|
|
|
earCount += baseBot.Inventory.items.Count(x => x.slotId == "Earpiece");
|
|
|
|
|
faceCoverCount += baseBot.Inventory.items.Count(x => x.slotId == "FaceCover");
|
|
|
|
|
armorVestCount += baseBot.Inventory.items.Count(x => x.slotId == "ArmorVest");
|
|
|
|
|
eyeWearCount += baseBot.Inventory.items.Count(x => x.slotId == "Eyewear");
|
|
|
|
|
armBandCount += baseBot.Inventory.items.Count(x => x.slotId == "ArmBand");
|
|
|
|
|
tacticalVestCount += baseBot.Inventory.items.Count(x => x.slotId == "TacticalVest");
|
|
|
|
|
backpackCount += baseBot.Inventory.items.Count(x => x.slotId == "Backpack");
|
|
|
|
|
firstPrimaryCount += baseBot.Inventory.items.Count(x => x.slotId == "FirstPrimaryWeapon");
|
|
|
|
|
secondPrimaryCount += baseBot.Inventory.items.Count(x => x.slotId == "SecondPrimaryWeapon");
|
|
|
|
|
holsterCount += baseBot.Inventory.items.Count(x => x.slotId == "Holster");
|
|
|
|
|
scabbardCount += baseBot.Inventory.items.Count(x => x.slotId == "Scabbard");
|
|
|
|
|
pocketsCount += baseBot.Inventory.items.Count(x => x.slotId == "Pockets");
|
|
|
|
|
securedContainerCount += baseBot.Inventory.items.Count(x => x.slotId == "SecuredContainer");
|
2021-08-13 16:24:05 +01:00
|
|
|
|
}
|
2021-08-13 19:49:32 +01:00
|
|
|
|
|
|
|
|
|
bot.chances.equipment = new EquipmentChances(
|
2021-08-14 09:53:00 +01:00
|
|
|
|
GetPercent(totalBotsCount, headwearCount),
|
|
|
|
|
GetPercent(totalBotsCount, earCount),
|
|
|
|
|
GetPercent(totalBotsCount, faceCoverCount),
|
|
|
|
|
GetPercent(totalBotsCount, armorVestCount),
|
|
|
|
|
GetPercent(totalBotsCount, eyeWearCount),
|
|
|
|
|
GetPercent(totalBotsCount, armBandCount),
|
|
|
|
|
GetPercent(totalBotsCount, tacticalVestCount),
|
|
|
|
|
GetPercent(totalBotsCount, backpackCount),
|
|
|
|
|
GetPercent(totalBotsCount, firstPrimaryCount),
|
|
|
|
|
GetPercent(totalBotsCount, secondPrimaryCount),
|
|
|
|
|
GetPercent(totalBotsCount, holsterCount),
|
|
|
|
|
GetPercent(totalBotsCount, scabbardCount),
|
|
|
|
|
GetPercent(totalBotsCount, pocketsCount),
|
|
|
|
|
GetPercent(totalBotsCount, securedContainerCount));
|
2021-08-13 16:24:05 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-13 19:49:32 +01:00
|
|
|
|
private static int GetPercent(int total, int count)
|
|
|
|
|
{
|
2021-12-15 09:01:45 +00:00
|
|
|
|
var percentChance = (int)Math.Ceiling((double)(((200 * count) + 1) / (total * 2)));
|
|
|
|
|
return percentChance > 100 ? 100 : percentChance; // return 100 if value is > 100
|
2021-08-13 19:49:32 +01:00
|
|
|
|
}
|
2021-09-06 17:34:10 +01:00
|
|
|
|
|
|
|
|
|
private static MinMax GetMagazineCountByBotType(BotType botType)
|
|
|
|
|
{
|
|
|
|
|
int min;
|
|
|
|
|
int max;
|
|
|
|
|
|
|
|
|
|
switch (botType)
|
|
|
|
|
{
|
|
|
|
|
case BotType.bosskilla:
|
|
|
|
|
min = 3;
|
|
|
|
|
max = 3;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
min = 2;
|
|
|
|
|
max = 4;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new MinMax(min, max);
|
|
|
|
|
}
|
2021-12-15 09:04:11 +00:00
|
|
|
|
|
|
|
|
|
private static MinMax GetLooseLootCountByBotType(BotType botType)
|
|
|
|
|
{
|
|
|
|
|
int min;
|
|
|
|
|
int max;
|
|
|
|
|
|
|
|
|
|
switch (botType)
|
|
|
|
|
{
|
2023-08-15 09:29:16 +00:00
|
|
|
|
case BotType.assault:
|
|
|
|
|
min= 0;
|
|
|
|
|
max= 6;
|
|
|
|
|
break;
|
|
|
|
|
case BotType.marksman:
|
|
|
|
|
min = 0;
|
|
|
|
|
max = 0;
|
|
|
|
|
break;
|
|
|
|
|
case BotType.exusec:
|
|
|
|
|
min = 2;
|
2021-12-15 09:04:11 +00:00
|
|
|
|
max = 4;
|
|
|
|
|
break;
|
2023-08-15 09:29:16 +00:00
|
|
|
|
case BotType.bossbully:
|
|
|
|
|
min = 3;
|
|
|
|
|
max= 7;
|
|
|
|
|
break;
|
|
|
|
|
case BotType.bossgluhar:
|
|
|
|
|
min = 2;
|
|
|
|
|
max = 9;
|
|
|
|
|
break;
|
|
|
|
|
case BotType.bosskilla:
|
|
|
|
|
min = 4;
|
|
|
|
|
max = 10;
|
|
|
|
|
break;
|
|
|
|
|
case BotType.bosskojaniy:
|
|
|
|
|
min = 0;
|
|
|
|
|
max = 7;
|
|
|
|
|
break;
|
|
|
|
|
case BotType.bosssanitar:
|
|
|
|
|
case BotType.followersanitar:
|
|
|
|
|
min = 2;
|
|
|
|
|
max = 5;
|
|
|
|
|
break;
|
2021-12-15 09:04:11 +00:00
|
|
|
|
default:
|
|
|
|
|
min = 1;
|
|
|
|
|
max = 4;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new MinMax(min, max);
|
|
|
|
|
}
|
2022-01-15 12:10:58 +00:00
|
|
|
|
|
|
|
|
|
private static MinMax GetMedicalItemCountByBotType(BotType botType)
|
|
|
|
|
{
|
|
|
|
|
int min;
|
|
|
|
|
int max;
|
|
|
|
|
|
|
|
|
|
switch (botType)
|
|
|
|
|
{
|
|
|
|
|
case BotType.bosssanitar:
|
2023-08-15 09:29:16 +00:00
|
|
|
|
case BotType.followersanitar:
|
2022-01-15 12:10:58 +00:00
|
|
|
|
min = 4;
|
2023-08-15 09:29:16 +00:00
|
|
|
|
max = 7;
|
2022-01-15 12:10:58 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
min = 1;
|
|
|
|
|
max = 2;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new MinMax(min, max);
|
|
|
|
|
}
|
2021-08-13 16:24:05 +01:00
|
|
|
|
}
|
|
|
|
|
}
|