using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; namespace Barotrauma.Items.Components { partial class Quality : ItemComponent { public const int MaxQuality = 3; public enum StatType { Condition, ExplosionRadius, ExplosionDamage, RepairSpeed, RepairToolStructureRepairMultiplier, RepairToolStructureDamageMultiplier, RepairToolDeattachTimeMultiplier, FirepowerMultiplier, StrikingPowerMultiplier, StrikingSpeedMultiplier, FiringRateMultiplier } private readonly Dictionary statValues = new Dictionary(); private int qualityLevel; [Editable(MinValueInt = 0, MaxValueInt = MaxQuality), Serialize(0, IsPropertySaveable.Yes)] public int QualityLevel { get { return qualityLevel; } set { if (value == qualityLevel) { return; } bool wasInFullCondition = item.IsFullCondition; qualityLevel = MathHelper.Clamp(value, 0, MaxQuality); item.RecalculateConditionValues(); //set the condition to the new max condition if (wasInFullCondition && statValues.ContainsKey(StatType.Condition)) { item.Condition = item.MaxCondition; } } } public Quality(Item item, ContentXElement element) : base(item, element) { foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString().ToLower()) { case "stattype": case "statvalue": case "qualitystat": string statTypeString = subElement.GetAttributeString("stattype", ""); if (!Enum.TryParse(statTypeString, true, out StatType statType)) { DebugConsole.ThrowError("Invalid stat type type \"" + statTypeString + "\" in item (" + ((MapEntity)item).Prefab.Identifier + ")", contentPackage: element.ContentPackage); } float statValue = subElement.GetAttributeFloat("value", 0f); statValues.TryAdd(statType, statValue); break; } } } public float GetValue(StatType statType) { if (!statValues.ContainsKey(statType)) { return 0.0f; } return statValues[statType] * qualityLevel; } /// /// Get a random quality for an item spawning in some sub, taking into account the type of the submarine and the difficulty of the current level /// (high-quality items become more common as difficulty increases) /// public static int GetSpawnedItemQuality(Submarine submarine, Level level, Rand.RandSync randSync = Rand.RandSync.ServerAndClient) { if (submarine?.Info == null || level == null || submarine.Info.Type == SubmarineType.Player) { return 0; } float difficultyFactor = MathHelper.Clamp(level.Difficulty, 0.0f, level.LevelData.Biome.ActualMaxDifficulty / 100.0f); if (level.Type == LevelData.LevelType.Outpost && level.StartLocation?.Type?.OutpostTeam == CharacterTeamType.FriendlyNPC) { //no high-quality spawns in friendly outposts difficultyFactor = 0.0f; } return ToolBox.SelectWeightedRandom(Enumerable.Range(0, MaxQuality + 1), q => GetCommonness(q, difficultyFactor), randSync); static float GetCommonness(int quality, float difficultyFactor) { return quality switch { 0 => 1, 1 => MathHelper.Lerp(0.0f, 1f, difficultyFactor), 2 => MathHelper.Lerp(0.0f, 1f, Math.Max(difficultyFactor-0.15f, 0f)), //15 difficulty transition to next biome - unlock Excellent loot 3 => MathHelper.Lerp(0.0f, 1f, Math.Max(difficultyFactor-0.35f, 0f)), //35 difficulty transition to next biome - unlock Masterwork loot _ => 0.0f, }; } } } }