Data/DressinTerryRule.cs
using Sandbox;
using System;
using System.Collections.Generic;
using System.Linq;
using static DressinTerry;
[GameResource("Dressin Terry Rule", "rule", "A Dressin Terry Rule for Random Characters", Icon = "rule")]
public class DressinTerryRule : GameResource
{
[Group("Height"), Order(1), Property, Range(0.5f, 2.0f)] public float? characterHeightOverride { get; set; } = 1.0f;
[Group("Height"), Order(1), Property, Range(0.5f, 2.0f)] public Vector2 characterHeightRandomRange { get; set; } = new Vector2(0.8f, 1.2f);
[Group("Global Filters"), Order(2), Property] public List<Clothing> clothingGlobalWhiteList { get; set; } = new List<Clothing>();
[Group("Global Filters"), Order(2), Property] public List<Clothing> clothingGlobalBlacklist { get; set; } = new List<Clothing>();
[Group("Global Filters"), Order(2), Property] public List<Clothing.ClothingCategory> categoriesGlobalWhiteList { get; set; } = new List<Clothing.ClothingCategory>();
[Group("Global Filters"), Order(2), Property] public List<Clothing.ClothingCategory> categoriesGlobalBlacklist { get; set; } = new List<Clothing.ClothingCategory>();
[Group("Global Filters"), Order(2), Property] public List<string> subCategoriesGlobalWhiteList { get; set; } = new List<string>();
[Group("Global Filters"), Order(2), Property] public List<string> subCategoriesGlobalBlacklist { get; set; } = new List<string>();
[Group("Rules"), Order(3), Property, InlineEditor] public List<RuleInst> rules { get; set; } = new List<RuleInst>();
public static ClothingContainer ToClothingContainer(DressinTerryRule rule)
{
var clothingContainer = new ClothingContainer();
if (rule != null)
{
var allRules = rule.rules.ToList();
List<Clothing> currentClothing = new List<Clothing>();
foreach (var ruleInst in allRules)
{
if (ruleInst.chanceOf != null)
{
var rndChance = Game.Random.Float();
if (rndChance > ruleInst.chanceOf)
continue;
}
var entry = ruleInst.GetRandomEntry(rule, currentClothing);
if (entry?.Clothing == null)
{
continue;
}
clothingContainer.Toggle(entry.Clothing);
var entryInst = clothingContainer.FindEntry(entry.Clothing);
if (entryInst != null)
{
entryInst.Tint = entry.Tint;
}
currentClothing.Add(entry.Clothing);
}
clothingContainer.Height = rule.characterHeightOverride != null ? rule.characterHeightOverride.Value : Game.Random.Float(rule.characterHeightRandomRange.x, rule.characterHeightRandomRange.y);
}
return clothingContainer;
}
public void Apply(SkinnedModelRenderer bodyRenderer)
{
if (bodyRenderer == null)
{
Log.Error($"Tried to apply rule '{this}' to a null bodyRenderer!");
return;
}
//bodyRenderer.ApplyClothing(ToClothingContainer(this));
DressinTerry.ApplyClothing(bodyRenderer, ToClothingContainer(this));
}
}
public enum DressingTerryRuleType
{
Any,
FromListOnly,
Blacklist
}
public class RuleInst
{
[Group(/*"Clothing"*/"Rule"), Order(1), Property] public DressingTerryRuleType clothingRuleType { get; set; }
[Group(/*"Clothing"*/"Rule"), Order(2), Property, ShowIf(nameof(shouldShowClothing), true)] public List<Clothing> clothing { get; set; } = new List<Clothing>();
[Group(/*"Category"*/"Rule"), Order(3), Property, ShowIf(nameof(shouldShowCategories), true)] public DressingTerryRuleType categoriesRuleType { get; set; }
[Group(/*"Category"*/"Rule"), Order(4), Property, ShowIf(nameof(shouldShowCategoriesList), true)] public List<Clothing.ClothingCategory> categories { get; set; } = new List<Clothing.ClothingCategory>();
[Group(/*"Sub Category"*/"Rule"), Order(5), Property, ShowIf(nameof(shouldShowSubCategories), true)] public DressingTerryRuleType subCategoriesRuleType { get; set; }
[Group(/*"Sub Category"*/"Rule"), Order(6), Property, ShowIf(nameof(shouldShowSubCategoriesList), true)] public List<string> subCategories { get; set; } = new List<string>();
[Group(/*"Tint"*/"Rule"), Order(10), Property, Range(0, 1)] public float? tintOverride { get; set; }
[Group(/*"Tint"*/"Rule"), Order(11), Property, Range(0, 1)] public float? chanceOf { get; set; }
[Hide] public bool shouldShowClothing => clothingRuleType != DressingTerryRuleType.Any;
[Hide] public bool shouldShowCategories => clothingRuleType != DressingTerryRuleType.FromListOnly;
[Hide] public bool shouldShowCategoriesList => shouldShowCategories && categoriesRuleType != DressingTerryRuleType.Any;
[Hide] public bool shouldShowSubCategories => clothingRuleType != DressingTerryRuleType.FromListOnly;
[Hide] public bool shouldShowSubCategoriesList => shouldShowCategories && subCategoriesRuleType != DressingTerryRuleType.Any;
public ClothingContainer.ClothingEntry GetRandomEntry(DressinTerryRule rule, List<Clothing> currentClothing = null)
{
var whitelistedClothing = new List<Clothing>(rule.clothingGlobalWhiteList);
var blacklistedClothing = new List<Clothing>(rule.clothingGlobalBlacklist);
if (clothingRuleType == DressingTerryRuleType.FromListOnly)
{
whitelistedClothing.AddRange(clothing);
}
else if (clothingRuleType == DressingTerryRuleType.Blacklist)
{
blacklistedClothing.AddRange(clothing);
}
if (clothingRuleType == DressingTerryRuleType.FromListOnly)
{
var clothingFromList = clothing.ToList().Where(x => !blacklistedClothing.Contains(x) &&
(whitelistedClothing.Count == 0 || whitelistedClothing.Contains(x)));
if (clothingFromList.Any())
{
var entry = new ClothingContainer.ClothingEntry(RandomInList(clothingFromList));
entry.Tint = tintOverride != null ? tintOverride.Value : Game.Random.Float();
return entry;
}
return null;
}
Clothing.ClothingCategory category = Clothing.ClothingCategory.None;
if (categoriesRuleType == DressingTerryRuleType.FromListOnly)
{
if (categories.Any())
{
category = RandomInList(categories);
}
else
{
category = RandomInList(clothingCategories);
}
}
else if (categoriesRuleType == DressingTerryRuleType.Blacklist)
{
var categoriesTypes = clothingCategories.ToList().Where(x => !categories.Contains(x));
if (categoriesTypes.Any())
{
category = RandomInList(categoriesTypes);
}
else
{
Log.Error($"All Categories were blacklisted");
}
}
string subCategory = null;
if (subCategoriesRuleType == DressingTerryRuleType.FromListOnly)
{
if (subCategories.Any())
{
subCategory = RandomInList(subCategories);
}
else
{
if (clothingCategoryToSubCategory.ContainsKey(category))
{
if (clothingCategoryToSubCategory[category].Any())
{
subCategory = RandomInList(clothingCategoryToSubCategory[category]);
}
}
}
}
else if (subCategoriesRuleType == DressingTerryRuleType.Blacklist)
{
if (clothingCategoryToSubCategory.ContainsKey(category))
{
if (clothingCategoryToSubCategory[category].Any())
{
var subCategoriesTypes = clothingCategoryToSubCategory[category].ToList().Where(x => !subCategories.Contains(x));
subCategory = RandomInList(subCategoriesTypes);
}
}
}
var clothingEntry = new ClothingContainer.ClothingEntry(RandomClothing(category, subCategory, currentClothing, whitelistedClothing, blacklistedClothing));
clothingEntry.Tint = tintOverride != null ? tintOverride.Value : Game.Random.Float();
return clothingEntry;
}
public static T RandomInList<T>(IEnumerable<T> collection)
{
if (collection.Any())
{
var rndIndex = Game.Random.Int(0, collection.Count()-1);
return collection.ElementAt(rndIndex);
}
return default(T);
}
}