Files
LuaCsForBarotraumaEP/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Quality.cs
2023-12-14 16:11:27 +02:00

112 lines
4.5 KiB
C#

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<StatType, float> statValues = new Dictionary<StatType, float>();
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;
}
/// <summary>
/// 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)
/// </summary>
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,
};
}
}
}
}