(965c31410a) Unstable v0.10.4.0
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
internal partial class CampaignMetadata
|
||||
{
|
||||
public CampaignMode Campaign { get; }
|
||||
|
||||
private readonly Dictionary<string, object> data = new Dictionary<string, object>();
|
||||
|
||||
public CampaignMetadata(CampaignMode campaign)
|
||||
{
|
||||
Campaign = campaign;
|
||||
}
|
||||
|
||||
public CampaignMetadata(CampaignMode campaign, XElement element)
|
||||
{
|
||||
Campaign = campaign;
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
if (string.Equals(subElement.Name.ToString(), "data", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
string identifier = subElement.GetAttributeString("key", string.Empty).ToLowerInvariant();
|
||||
string value = subElement.GetAttributeString("value", string.Empty);
|
||||
string valueType = subElement.GetAttributeString("type", string.Empty);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(identifier) || string.IsNullOrWhiteSpace(value) || string.IsNullOrWhiteSpace(valueType))
|
||||
{
|
||||
DebugConsole.ThrowError("Unable to load value because one or more of the required attributes are empty.\n" +
|
||||
$"key: \"{identifier}\", value: \"{value}\", type: \"{valueType}\"");
|
||||
continue;
|
||||
}
|
||||
|
||||
Type? type = Type.GetType(valueType);
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
DebugConsole.ThrowError($"Type for {identifier} not found ({valueType}).");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type == typeof(float))
|
||||
{
|
||||
if (!float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out float floatValue))
|
||||
{
|
||||
DebugConsole.ThrowError($"Error in campaign metadata: could not parse \"{value}\" as a float.");
|
||||
continue;
|
||||
}
|
||||
data.Add(identifier, floatValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
data.Add(identifier, Convert.ChangeType(value, type));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetValue(string identifier, object value)
|
||||
{
|
||||
identifier = identifier.ToLowerInvariant();
|
||||
|
||||
DebugConsole.Log($"Set the value \"{identifier}\" to {value}");
|
||||
|
||||
if (!data.ContainsKey(identifier))
|
||||
{
|
||||
data.Add(identifier, value);
|
||||
return;
|
||||
}
|
||||
|
||||
data[identifier] = value;
|
||||
}
|
||||
|
||||
public float GetFloat(string identifier, float? defaultValue = null)
|
||||
{
|
||||
return (float)GetTypeOrDefault(identifier, typeof(float), defaultValue ?? 0f);
|
||||
}
|
||||
|
||||
public int GetInt(string identifier, int? defaultValue = null)
|
||||
{
|
||||
return (int)GetTypeOrDefault(identifier, typeof(int), defaultValue ?? 0);
|
||||
}
|
||||
|
||||
public bool GetBoolean(string identifier, bool? defaultValue = null)
|
||||
{
|
||||
return (bool)GetTypeOrDefault(identifier, typeof(bool), defaultValue ?? false);
|
||||
}
|
||||
|
||||
public string GetString(string identifier, string? defaultValue = null)
|
||||
{
|
||||
return (string)GetTypeOrDefault(identifier, typeof(string), defaultValue ?? string.Empty);
|
||||
}
|
||||
|
||||
public bool HasKey(string identifier)
|
||||
{
|
||||
identifier = identifier.ToLowerInvariant();
|
||||
return data.ContainsKey(identifier);
|
||||
}
|
||||
|
||||
private object GetTypeOrDefault(string identifier, Type type, object defaultValue)
|
||||
{
|
||||
object? value = GetValue(identifier);
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
SetValue(identifier, defaultValue);
|
||||
}
|
||||
else if (value.GetType() == type)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError($"Attempted to get value \"{identifier}\" as a {type} but the value is {value.GetType()}.");
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public object? GetValue(string identifier)
|
||||
{
|
||||
return data.ContainsKey(identifier) ? data[identifier] : null;
|
||||
}
|
||||
|
||||
public void Save(XElement modeElement)
|
||||
{
|
||||
XElement element = new XElement("Metadata");
|
||||
|
||||
foreach (var (key, value) in data)
|
||||
{
|
||||
string valueStr = value?.ToString() ?? "";
|
||||
if (value?.GetType() == typeof(float))
|
||||
{
|
||||
valueStr = ((float)value).ToString("G", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
element.Add(new XElement("Data",
|
||||
new XAttribute("key", key),
|
||||
new XAttribute("value", valueStr),
|
||||
new XAttribute("type", value?.GetType())));
|
||||
}
|
||||
#if DEBUG || UNSTABLE
|
||||
DebugConsole.Log(element.ToString());
|
||||
#endif
|
||||
modeElement.Add(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class Faction
|
||||
{
|
||||
public Reputation Reputation { get; }
|
||||
public FactionPrefab Prefab { get; }
|
||||
|
||||
public Faction(CampaignMetadata metadata, FactionPrefab prefab)
|
||||
{
|
||||
Prefab = prefab;
|
||||
Reputation = new Reputation(metadata, $"faction.{prefab.Identifier}", prefab.MinReputation, prefab.MaxReputation, prefab.InitialReputation);
|
||||
}
|
||||
}
|
||||
|
||||
internal class FactionPrefab : IDisposable
|
||||
{
|
||||
public static List<FactionPrefab> Prefabs { get; set; }
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public string Description { get; }
|
||||
public string ShortDescription { get; }
|
||||
|
||||
public string Identifier { get; }
|
||||
|
||||
/// <summary>
|
||||
/// How low the reputation can drop on this faction
|
||||
/// </summary>
|
||||
public int MinReputation { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Maximum reputation level you can gain on this faction
|
||||
/// </summary>
|
||||
public int MaxReputation { get; }
|
||||
|
||||
/// <summary>
|
||||
/// What reputation does this faction start with
|
||||
/// </summary>
|
||||
public int InitialReputation { get; }
|
||||
|
||||
#if CLIENT
|
||||
public Sprite? Icon { get; private set; }
|
||||
|
||||
public Sprite? BackgroundPortrait { get; private set; }
|
||||
|
||||
public Color IconColor { get; }
|
||||
#endif
|
||||
|
||||
private FactionPrefab(XElement element)
|
||||
{
|
||||
Identifier = element.GetAttributeString("identifier", string.Empty);
|
||||
MinReputation = element.GetAttributeInt("minreputation", -100);
|
||||
MaxReputation = element.GetAttributeInt("maxreputation", 100);
|
||||
InitialReputation = element.GetAttributeInt("initialreputation", 0);
|
||||
Name = element.GetAttributeString("name", null) ?? TextManager.Get($"faction.{Identifier}", returnNull: true) ?? "Unnamed";
|
||||
Description = element.GetAttributeString("description", null) ?? TextManager.Get($"faction.{Identifier}.description", returnNull: true) ?? "";
|
||||
ShortDescription = element.GetAttributeString("shortdescription", null) ?? TextManager.Get($"faction.{Identifier}.shortdescription", returnNull: true) ?? "";
|
||||
#if CLIENT
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
|
||||
if (subElement.Name.ToString().Equals("icon", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
IconColor = subElement.GetAttributeColor("color", Color.White);
|
||||
Icon = new Sprite(subElement);
|
||||
}
|
||||
else if (subElement.Name.ToString().Equals("portrait", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
BackgroundPortrait = new Sprite(subElement);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void LoadFactions()
|
||||
{
|
||||
Prefabs?.ForEach(set => set.Dispose());
|
||||
Prefabs = new List<FactionPrefab>();
|
||||
IEnumerable<ContentFile> files = GameMain.Instance.GetFilesOfType(ContentType.Factions);
|
||||
foreach (ContentFile file in files)
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(file.Path);
|
||||
XElement? rootElement = doc?.Root;
|
||||
|
||||
if (doc == null || rootElement == null) { continue; }
|
||||
|
||||
if (doc.Root.IsOverride())
|
||||
{
|
||||
Prefabs.Clear();
|
||||
DebugConsole.NewMessage($"Overriding all factions with '{file.Path}'", Color.Yellow);
|
||||
}
|
||||
|
||||
foreach (XElement element in rootElement.Elements())
|
||||
{
|
||||
bool isOverride = element.IsOverride();
|
||||
XElement sourceElement = isOverride ? element.FirstElement() : element;
|
||||
string elementName = sourceElement.Name.ToString().ToLowerInvariant();
|
||||
string identifier = sourceElement.GetAttributeString("identifier", null);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(identifier))
|
||||
{
|
||||
DebugConsole.ThrowError($"No identifier defined for the faction config '{elementName}' in file '{file.Path}'");
|
||||
continue;
|
||||
}
|
||||
|
||||
var existingParams = Prefabs.Find(set => set.Identifier == identifier);
|
||||
if (existingParams != null)
|
||||
{
|
||||
if (isOverride)
|
||||
{
|
||||
DebugConsole.NewMessage($"Overriding faction config '{identifier}' using the file '{file.Path}'", Color.Yellow);
|
||||
Prefabs.Remove(existingParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError($"Duplicate faction config: '{identifier}' defined in {elementName} of '{file.Path}'");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Prefabs.Add(new FactionPrefab(element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
#if CLIENT
|
||||
Icon?.Remove();
|
||||
Icon = null;
|
||||
#endif
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class Reputation
|
||||
{
|
||||
public const float HostileThreshold = 0.1f;
|
||||
public const float ReputationLossPerNPCDamage = 0.1f;
|
||||
public const float ReputationLossPerStolenItemPrice = 0.01f;
|
||||
public const float MinReputationLossPerStolenItem = 0.5f;
|
||||
public const float MaxReputationLossPerStolenItem = 10.0f;
|
||||
|
||||
public string Identifier { get; }
|
||||
public int MinReputation { get; }
|
||||
public int MaxReputation { get; }
|
||||
public int InitialReputation { get; }
|
||||
public CampaignMetadata Metadata { get; }
|
||||
|
||||
private readonly string metaDataIdentifier;
|
||||
|
||||
/// <summary>
|
||||
/// Reputation value normalized to the range of 0-1
|
||||
/// </summary>
|
||||
public float NormalizedValue
|
||||
{
|
||||
get { return MathUtils.InverseLerp(MinReputation, MaxReputation, Value); }
|
||||
}
|
||||
|
||||
public float Value
|
||||
{
|
||||
get => Math.Min(MaxReputation, Metadata.GetFloat(metaDataIdentifier, InitialReputation));
|
||||
set => Metadata.SetValue(metaDataIdentifier, Math.Clamp(value, MinReputation, MaxReputation));
|
||||
}
|
||||
|
||||
public Reputation(CampaignMetadata metadata, string identifier, int minReputation, int maxReputation, int initialReputation)
|
||||
{
|
||||
System.Diagnostics.Debug.Assert(metadata != null);
|
||||
Metadata = metadata;
|
||||
Identifier = identifier.ToLowerInvariant();
|
||||
metaDataIdentifier = $"reputation.{Identifier}";
|
||||
MinReputation = minReputation;
|
||||
MaxReputation = maxReputation;
|
||||
InitialReputation = initialReputation;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user