mirror of
https://github.com/Wincent01/InfectedRose.git
synced 2025-12-16 17:49:50 -06:00
Lots of changes, too late to describe it all.
This commit is contained in:
@@ -9,6 +9,12 @@ namespace InfectedRose.Core
|
||||
public static string ReadNiString(this BitReader @this, bool wide = false, bool small = false)
|
||||
{
|
||||
var len = small ? @this.Read<byte>() : @this.Read<uint>();
|
||||
|
||||
if (len == uint.MaxValue)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var str = new char[len];
|
||||
|
||||
for (var i = 0; i < len; i++)
|
||||
|
||||
@@ -62,6 +62,27 @@ namespace InfectedRose.Database
|
||||
}
|
||||
}
|
||||
|
||||
public int GetFieldIndex(string name)
|
||||
{
|
||||
var index = -1;
|
||||
|
||||
for (var i = 0; i < Table.TableInfo.Count; i++)
|
||||
{
|
||||
var column = Table.TableInfo[i];
|
||||
|
||||
if (column.Name == name) index = i;
|
||||
}
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
throw new KeyNotFoundException(
|
||||
$"The given field key of '{name}' does not exist in the {Table.Name} table"
|
||||
);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
public IEnumerator<Field> GetEnumerator()
|
||||
{
|
||||
int index = default;
|
||||
|
||||
@@ -285,7 +285,25 @@ namespace InfectedRose.Database
|
||||
|
||||
return Create(max + 1);
|
||||
}
|
||||
|
||||
public Row CreateMin(int minKey)
|
||||
{
|
||||
if (TableInfo[0].Type != DataType.Integer)
|
||||
throw new NotSupportedException("AccessDatabase can only generate primary keys for Int32 types.");
|
||||
|
||||
var max = Count > 0 ? this.Max(c => c.Key) : 0;
|
||||
|
||||
for (var i = minKey; i < max; i++)
|
||||
{
|
||||
if (!ContainsKey(i) && !ClaimedKeys.Contains(i))
|
||||
{
|
||||
return Create(i);
|
||||
}
|
||||
}
|
||||
|
||||
return Create(max + 1);
|
||||
}
|
||||
|
||||
public Row CreateWithFilter(ICollection<int> exclude)
|
||||
{
|
||||
if (TableInfo[0].Type != DataType.Integer)
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace InfectedRose.Interface
|
||||
namespace InfectedRose.Interface;
|
||||
|
||||
/// <summary>
|
||||
/// A list of items that were generated by the mod and put into the main resource directory
|
||||
///
|
||||
/// These items are deleted upon startup.
|
||||
/// </summary>
|
||||
public class Artifacts : List<string>
|
||||
{
|
||||
/// <summary>
|
||||
/// A list of items that were generated by the mod and put into the main resource directory
|
||||
///
|
||||
/// These items are deleted upon startup.
|
||||
/// </summary>
|
||||
public class Artifacts : Dictionary<string, string>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
151
InfectedRose.Interface/JsonExtensions.cs
Normal file
151
InfectedRose.Interface/JsonExtensions.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace InfectedRose.Interface;
|
||||
|
||||
public static class JsonExtensions
|
||||
{
|
||||
public static T? ToObject<T>(this JsonElement element, JsonSerializerOptions? options = null)
|
||||
{
|
||||
var bufferWriter = new ArrayBufferWriter<byte>();
|
||||
using (var writer = new Utf8JsonWriter(bufferWriter))
|
||||
element.WriteTo(writer);
|
||||
return JsonSerializer.Deserialize<T>(bufferWriter.WrittenSpan, options);
|
||||
}
|
||||
|
||||
public static T? ToObject<T>(this JsonDocument document, JsonSerializerOptions? options = null)
|
||||
{
|
||||
if (document == null)
|
||||
throw new ArgumentNullException(nameof(document));
|
||||
return document.RootElement.ToObject<T>(options);
|
||||
}
|
||||
|
||||
public static T? ToObject<T>(this JsonValue element, JsonSerializerOptions? options = null)
|
||||
{
|
||||
var bufferWriter = new ArrayBufferWriter<byte>();
|
||||
using (var writer = new Utf8JsonWriter(bufferWriter))
|
||||
element.WriteTo(writer);
|
||||
return JsonSerializer.Deserialize<T>(bufferWriter.WrittenSpan, options);
|
||||
}
|
||||
|
||||
public static Dictionary<string, object> ToDictionary(this JsonValue element)
|
||||
{
|
||||
var dictionary = new Dictionary<string, object>();
|
||||
|
||||
var str = element.ToString();
|
||||
|
||||
var json = JsonDocument.Parse(str);
|
||||
|
||||
var root = json.RootElement;
|
||||
|
||||
foreach (var property in root.EnumerateObject())
|
||||
{
|
||||
var value = property.Value;
|
||||
|
||||
if (value.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
var array = new List<object>();
|
||||
|
||||
foreach (var item in value.EnumerateArray())
|
||||
{
|
||||
if (item.ValueKind == JsonValueKind.Object)
|
||||
{
|
||||
array.Add(item.ToDictionary());
|
||||
}
|
||||
else
|
||||
{
|
||||
array.Add(item.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
dictionary.Add(property.Name, array);
|
||||
}
|
||||
else if (value.ValueKind == JsonValueKind.Object)
|
||||
{
|
||||
dictionary.Add(property.Name, value.ToDictionary());
|
||||
}
|
||||
else if (value.ValueKind == JsonValueKind.String)
|
||||
{
|
||||
dictionary.Add(property.Name, value.ToString());
|
||||
}
|
||||
else if (value.ValueKind == JsonValueKind.Number)
|
||||
{
|
||||
dictionary.Add(property.Name, value.GetDouble());
|
||||
}
|
||||
else if (value.ValueKind == JsonValueKind.True)
|
||||
{
|
||||
dictionary.Add(property.Name, true);
|
||||
}
|
||||
else if (value.ValueKind == JsonValueKind.False)
|
||||
{
|
||||
dictionary.Add(property.Name, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary.Add(property.Name, value.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
public static Dictionary<string, object> ToDictionary(this JsonElement element)
|
||||
{
|
||||
var dictionary = new Dictionary<string, object>();
|
||||
|
||||
foreach (var property in element.EnumerateObject())
|
||||
{
|
||||
var value = property.Value;
|
||||
|
||||
if (value.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
var array = new List<object>();
|
||||
|
||||
foreach (var item in value.EnumerateArray())
|
||||
{
|
||||
if (item.ValueKind == JsonValueKind.Object)
|
||||
{
|
||||
array.Add(item.ToDictionary());
|
||||
}
|
||||
else
|
||||
{
|
||||
array.Add(item.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
dictionary.Add(property.Name, array);
|
||||
}
|
||||
else if (value.ValueKind == JsonValueKind.Object)
|
||||
{
|
||||
dictionary.Add(property.Name, value.ToDictionary());
|
||||
}
|
||||
else if (value.ValueKind == JsonValueKind.String)
|
||||
{
|
||||
dictionary.Add(property.Name, value.ToString());
|
||||
}
|
||||
else if (value.ValueKind == JsonValueKind.Number)
|
||||
{
|
||||
dictionary.Add(property.Name, value.GetDouble());
|
||||
}
|
||||
else if (value.ValueKind == JsonValueKind.True)
|
||||
{
|
||||
dictionary.Add(property.Name, true);
|
||||
}
|
||||
else if (value.ValueKind == JsonValueKind.False)
|
||||
{
|
||||
dictionary.Add(property.Name, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary.Add(property.Name, value.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,58 +1,57 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface
|
||||
namespace InfectedRose.Interface;
|
||||
|
||||
[XmlRoot("locales")]
|
||||
public class Locales
|
||||
{
|
||||
[XmlRoot("locales")]
|
||||
public class Locales
|
||||
{
|
||||
[XmlAttribute("count")]
|
||||
public int Count { get; set; }
|
||||
[XmlAttribute("count")]
|
||||
public int Count { get; set; }
|
||||
|
||||
[XmlElement("locale")]
|
||||
public string[] Locale { get; set; }
|
||||
}
|
||||
[XmlElement("locale")]
|
||||
public string[] Locale { get; set; }
|
||||
}
|
||||
|
||||
[XmlRoot("translation")]
|
||||
public class Translation
|
||||
{
|
||||
[XmlAttribute("locale")]
|
||||
public string Locale { get; set; }
|
||||
[XmlRoot("translation")]
|
||||
public class Translation
|
||||
{
|
||||
[XmlAttribute("locale")]
|
||||
public string Locale { get; set; }
|
||||
|
||||
[XmlText]
|
||||
public string Text { get; set; }
|
||||
}
|
||||
[XmlText]
|
||||
public string Text { get; set; }
|
||||
}
|
||||
|
||||
[XmlRoot("phrase")]
|
||||
public class Phrase
|
||||
{
|
||||
[XmlAttribute("id")]
|
||||
public string Id { get; set; }
|
||||
[XmlRoot("phrase")]
|
||||
public class Phrase
|
||||
{
|
||||
[XmlAttribute("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[XmlElement("translation")]
|
||||
public List<Translation> Translations { get; set; }
|
||||
}
|
||||
[XmlElement("translation")]
|
||||
public List<Translation> Translations { get; set; }
|
||||
}
|
||||
|
||||
[XmlRoot("phrases")]
|
||||
public class Phrases
|
||||
{
|
||||
[XmlAttribute("count")]
|
||||
public int Count { get; set; }
|
||||
[XmlRoot("phrases")]
|
||||
public class Phrases
|
||||
{
|
||||
[XmlAttribute("count")]
|
||||
public int Count { get; set; }
|
||||
|
||||
[XmlElement("phrase")]
|
||||
public List<Phrase> Phrase { get; set; }
|
||||
}
|
||||
[XmlElement("phrase")]
|
||||
public List<Phrase> Phrase { get; set; }
|
||||
}
|
||||
|
||||
[XmlRoot("localization")]
|
||||
public class Localization
|
||||
{
|
||||
[XmlAttribute("version")]
|
||||
public float Version { get; set; } = 1.200000f;
|
||||
[XmlRoot("localization")]
|
||||
public class Localization
|
||||
{
|
||||
[XmlAttribute("version")]
|
||||
public float Version { get; set; } = 1.200000f;
|
||||
|
||||
[XmlElement("locales")]
|
||||
public Locales Locales { get; set; }
|
||||
[XmlElement("locales")]
|
||||
public Locales Locales { get; set; }
|
||||
|
||||
[XmlElement("phrases")]
|
||||
public Phrases Phrases { get; set; }
|
||||
}
|
||||
[XmlElement("phrases")]
|
||||
public Phrases Phrases { get; set; }
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface
|
||||
namespace InfectedRose.Interface;
|
||||
|
||||
public class Lookup : Dictionary<string, int>
|
||||
{
|
||||
public class Lookup : Dictionary<string, int>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,15 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface
|
||||
{
|
||||
public class Manifest
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = "mod-name";
|
||||
namespace InfectedRose.Interface;
|
||||
|
||||
[JsonPropertyName("files")]
|
||||
public string[] Files { get; set; } = {"mod.json"};
|
||||
}
|
||||
public class Manifest
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = "mod-name";
|
||||
|
||||
[JsonPropertyName("files")]
|
||||
public string[] Files { get; set; } = {"mod.json"};
|
||||
|
||||
[JsonPropertyName("resources")]
|
||||
public string Resources { get; set; } = "resources";
|
||||
}
|
||||
@@ -6,110 +6,106 @@ using System.Text.Json.Serialization;
|
||||
using InfectedRose.Interface.Templates;
|
||||
using InfectedRose.Interface.Templates.ValueTypes;
|
||||
|
||||
namespace InfectedRose.Interface
|
||||
namespace InfectedRose.Interface;
|
||||
|
||||
public class Mod
|
||||
{
|
||||
public class Mod
|
||||
[JsonPropertyName("id")]
|
||||
public string Id { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("explicit-id")]
|
||||
public int? ExplicitId { get; set; }
|
||||
|
||||
[JsonPropertyName("old-ids")]
|
||||
public string[]? OldIds { get; set; }
|
||||
|
||||
[JsonPropertyName("type")]
|
||||
public string Type { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("action")]
|
||||
public string Action { get; set; }
|
||||
|
||||
[JsonPropertyName("show-defaults")]
|
||||
public bool? ShowDefaults { get; set; }
|
||||
|
||||
[JsonPropertyName("components")]
|
||||
public string[]? Components { get; set; }
|
||||
|
||||
[JsonPropertyName("table")]
|
||||
public string? Table { get; set; }
|
||||
|
||||
[JsonPropertyName("items")]
|
||||
public JsonValue[]? Items { get; set; }
|
||||
|
||||
[JsonPropertyName("skills")]
|
||||
public ObjectSkillEntry[]? Skills { get; set; }
|
||||
|
||||
[JsonPropertyName("tasks")]
|
||||
public MissionModTask[]? Tasks { get; set; }
|
||||
|
||||
[JsonPropertyName("missions")]
|
||||
public MissionOffer[]? MissionOffers { get; set; }
|
||||
|
||||
[JsonPropertyName("behaviors")]
|
||||
public Dictionary<string, Behavior> Behaviors { get; set; }
|
||||
|
||||
[JsonPropertyName("zone")]
|
||||
public Zone? Zone { get; set; }
|
||||
|
||||
[JsonPropertyName("locale")]
|
||||
public Dictionary<string, string>? Locale { get; set; }
|
||||
|
||||
[JsonPropertyName("values")]
|
||||
public Dictionary<string, object?> Values { get; set; } = new Dictionary<string, object?>();
|
||||
|
||||
[JsonIgnore]
|
||||
public Dictionary<string, object?> Defaults { get; set; } = new Dictionary<string, object?>();
|
||||
|
||||
public T GetValue<T>(string id)
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public string Id { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("explicit-id")]
|
||||
public int? ExplicitId { get; set; }
|
||||
|
||||
[JsonPropertyName("old-ids")]
|
||||
public string[]? OldIds { get; set; }
|
||||
|
||||
[JsonPropertyName("type")]
|
||||
public string Type { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("action")]
|
||||
public string Action { get; set; } = "add";
|
||||
|
||||
[JsonPropertyName("show-defaults")]
|
||||
public bool? ShowDefaults { get; set; }
|
||||
|
||||
[JsonPropertyName("components")]
|
||||
public string[]? Components { get; set; }
|
||||
|
||||
[JsonPropertyName("table")]
|
||||
public string? Table { get; set; }
|
||||
|
||||
[JsonPropertyName("items")]
|
||||
public JsonValue[]? Items { get; set; }
|
||||
|
||||
[JsonPropertyName("skills")]
|
||||
public ObjectSkillEntry[]? Skills { get; set; }
|
||||
|
||||
[JsonPropertyName("tasks")]
|
||||
public MissionModTask[]? Tasks { get; set; }
|
||||
|
||||
[JsonPropertyName("missions")]
|
||||
public MissionOffer[]? MissionOffers { get; set; }
|
||||
|
||||
[JsonPropertyName("behaviors")]
|
||||
public Dictionary<string, Behavior> Behaviors { get; set; }
|
||||
|
||||
[JsonPropertyName("zone")]
|
||||
public Zone? Zone { get; set; }
|
||||
|
||||
[JsonPropertyName("locale")]
|
||||
public Dictionary<string, string>? Locale { get; set; } = new Dictionary<string, string>
|
||||
if (Values[id] is JsonElement jsonElement)
|
||||
{
|
||||
{"en_US", ""}
|
||||
};
|
||||
|
||||
[JsonPropertyName("values")]
|
||||
public Dictionary<string, object?> Values { get; set; } = new Dictionary<string, object?>();
|
||||
|
||||
[JsonIgnore]
|
||||
public Dictionary<string, object?> Defaults { get; set; } = new Dictionary<string, object?>();
|
||||
|
||||
public T GetValue<T>(string id)
|
||||
{
|
||||
if (Values[id] is JsonElement jsonElement)
|
||||
{
|
||||
return jsonElement.Deserialize<T>()!;
|
||||
}
|
||||
return jsonElement.Deserialize<T>()!;
|
||||
}
|
||||
|
||||
if (Values[id] is T value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
if (Values[id] is null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return (T) Convert.ChangeType(Values[id], typeof(T));
|
||||
}
|
||||
|
||||
public bool HasValue(string id)
|
||||
if (Values[id] is T value)
|
||||
{
|
||||
return Values.ContainsKey(id);
|
||||
return value;
|
||||
}
|
||||
|
||||
public void Default<T>(string id, T value)
|
||||
if (Values[id] is null)
|
||||
{
|
||||
Defaults[id] = value;
|
||||
|
||||
if (HasValue(id)) return;
|
||||
|
||||
Values[id] = value;
|
||||
return default;
|
||||
}
|
||||
|
||||
public void DefaultNull(string id)
|
||||
{
|
||||
Defaults[id] = null;
|
||||
|
||||
if (HasValue(id)) return;
|
||||
return (T) Convert.ChangeType(Values[id], typeof(T));
|
||||
}
|
||||
|
||||
Values[id] = null;
|
||||
}
|
||||
public bool HasValue(string id)
|
||||
{
|
||||
return Values.ContainsKey(id);
|
||||
}
|
||||
|
||||
public void Default<T>(string id, T value)
|
||||
{
|
||||
Defaults[id] = value;
|
||||
|
||||
public int GetComponentType()
|
||||
{
|
||||
return (int) Enum.Parse(typeof(ComponentId), Type);
|
||||
}
|
||||
if (HasValue(id)) return;
|
||||
|
||||
Values[id] = value;
|
||||
}
|
||||
|
||||
public void DefaultNull(string id)
|
||||
{
|
||||
Defaults[id] = null;
|
||||
|
||||
if (HasValue(id)) return;
|
||||
|
||||
Values[id] = null;
|
||||
}
|
||||
|
||||
public int GetComponentType()
|
||||
{
|
||||
return (int) Enum.Parse(typeof(ComponentId), Type);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
||||
namespace InfectedRose.Interface
|
||||
namespace InfectedRose.Interface;
|
||||
|
||||
public abstract class ModType
|
||||
{
|
||||
public abstract class ModType
|
||||
{
|
||||
public abstract void Apply(Mod mod);
|
||||
}
|
||||
public abstract void Apply(Mod mod);
|
||||
}
|
||||
@@ -1,15 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace InfectedRose.Interface
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class ModTypeAttribute : Attribute
|
||||
{
|
||||
public string Type { get; set; }
|
||||
namespace InfectedRose.Interface;
|
||||
|
||||
public ModTypeAttribute(string type)
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class ModTypeAttribute : Attribute
|
||||
{
|
||||
public string Type { get; set; }
|
||||
|
||||
public ModTypeAttribute(string type)
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface
|
||||
namespace InfectedRose.Interface;
|
||||
|
||||
public class ModPriority
|
||||
{
|
||||
public class ModPriority
|
||||
{
|
||||
[JsonPropertyName("directory")]
|
||||
public string Directory { get; set; }
|
||||
[JsonPropertyName("directory")]
|
||||
public string Directory { get; set; }
|
||||
|
||||
[JsonPropertyName("priority")]
|
||||
public int Priority { get; set; }
|
||||
}
|
||||
[JsonPropertyName("priority")]
|
||||
public int Priority { get; set; }
|
||||
}
|
||||
|
||||
public class Mods
|
||||
{
|
||||
[JsonPropertyName("version")]
|
||||
public string Version { get; set; } = "";
|
||||
public class Mods
|
||||
{
|
||||
[JsonPropertyName("version")]
|
||||
public string Version { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("database")]
|
||||
public string Database { get; set; } = "cdclient.fdb";
|
||||
[JsonPropertyName("database")]
|
||||
public string Database { get; set; } = "cdclient.fdb";
|
||||
|
||||
[JsonPropertyName("sqlite")]
|
||||
public string Sqlite { get; set; } = "CDServer.sqlite";
|
||||
[JsonPropertyName("sqlite")]
|
||||
public string Sqlite { get; set; } = "CDServer.sqlite";
|
||||
|
||||
[JsonPropertyName("copy-mods")]
|
||||
public string? Copy { get; set; }
|
||||
|
||||
[JsonPropertyName("resource-folder")]
|
||||
public string ResourceFolder { get; set; }
|
||||
[JsonPropertyName("copy-mods")]
|
||||
public string? Copy { get; set; }
|
||||
|
||||
[JsonPropertyName("priorities")]
|
||||
public List<ModPriority> Priorities { get; set; } = new List<ModPriority>();
|
||||
}
|
||||
[JsonPropertyName("resource-folder")]
|
||||
public string ResourceFolder { get; set; } = "../res/maps/__mods__";
|
||||
|
||||
[JsonPropertyName("priorities")]
|
||||
public List<ModPriority> Priorities { get; set; } = new List<ModPriority>();
|
||||
}
|
||||
@@ -2,179 +2,178 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using InfectedRose.Database;
|
||||
|
||||
namespace InfectedRose.Interface
|
||||
namespace InfectedRose.Interface;
|
||||
|
||||
public class PrimaryKeyRegistry
|
||||
{
|
||||
public class PrimaryKeyRegistry
|
||||
public Dictionary<string, string[]> PrimaryKeys { get; } = new Dictionary<string, string[]>
|
||||
{
|
||||
{"AICombatRoles", new[] {"id"}},
|
||||
{"AccessoryDefaultLoc", new[] {"GroupID"}},
|
||||
{"Activities", new[] {"ActivityID"}},
|
||||
{"ActivityRewards", new[] {"objectTemplate", "ActivityRewardIndex"}},
|
||||
{"ActivityText", new[] {"activityID", "type"}},
|
||||
{"AnimationIndex", new[] {"animationGroupID"}},
|
||||
{"Animations", new[] {"animationGroupID", "animation_type"}},
|
||||
{"BaseCombatAIComponent", new[] {"id"}},
|
||||
{"BehaviorEffect", new[] {"effectID", "effectType"}},
|
||||
{"BehaviorParameter", new[] {"behaviorID", "parameterID"}},
|
||||
{"BehaviorTemplate", new[] {"behaviorID"}},
|
||||
{"BehaviorTemplateName", new[] {"templateID"}},
|
||||
{"Blueprints", new[] {"id"}},
|
||||
{"BrickColors", new[] {"id"}},
|
||||
{"BrickIDTable", new[] {"NDObjectID"}},
|
||||
{"BuffDefinitions", new[] {"ID"}},
|
||||
{"BuffParameters", new[] {"BuffID", "ParameterName"}},
|
||||
{"Camera", new[] {"camera_name"}},
|
||||
{"CelebrationParameters", new[] {"id"}},
|
||||
{"ChoiceBuildComponent", new[] {"id"}},
|
||||
{"CollectibleComponent", new[] {"id"}},
|
||||
{"ComponentsRegistry", new[] {"id", "component_type"}},
|
||||
{"ControlSchemes", new[] {"control_scheme"}},
|
||||
{"CurrencyDenominations", new[] {"value"}},
|
||||
{"CurrencyTable", new[] {"currencyIndex", "npcminlevel"}},
|
||||
{"DBExclude", new[] {"table", "column"}},
|
||||
{"DeletionRestrictions", new[] {"id"}},
|
||||
{"DestructibleComponent", new[] {"id"}},
|
||||
{"DevModelBehaviors", new[] {"ModelID"}},
|
||||
{"Emotes", new[] {"id"}},
|
||||
{"EventGating", new[] {"eventName"}},
|
||||
{"ExhibitComponent", new[] {"id"}},
|
||||
{"Factions", new[] {"faction"}},
|
||||
{"FeatureGating", new[] {"featureName"}},
|
||||
{"FlairTable", new[] {"id"}},
|
||||
{"Icons", new[] {"IconID"}},
|
||||
{"InventoryComponent", new[] {"id", "itemid"}},
|
||||
{"ItemComponent", new[] {"id"}},
|
||||
{"ItemEggData", new[] {"id"}},
|
||||
{"ItemFoodData", new[] {"id"}},
|
||||
{"ItemSetSkills", new[] {"SkillSetID", "SkillID"}},
|
||||
{"ItemSets", new[] {"setID"}},
|
||||
{"JetPackPadComponent", new[] {"id"}},
|
||||
{"LUPExhibitComponent", new[] {"id"}},
|
||||
{"LUPExhibitModelData", new[] {"LOT"}},
|
||||
{"LUPZoneIDs", new[] {"zoneID"}},
|
||||
{"LanguageType", new[] {"LanguageID"}},
|
||||
{"LevelProgressionLookup", new[] {"id"}},
|
||||
{"LootMatrix", new[] {"LootMatrixIndex", "LootTableIndex", "RarityTableIndex"}},
|
||||
{"LootMatrixIndex", new[] {"LootMatrixIndex"}},
|
||||
{"LootTable", new[] {"itemid", "LootTableIndex", "id"}},
|
||||
{"LootTableIndex", new[] {"LootTableIndex"}},
|
||||
{"MinifigComponent", new[] {"id"}},
|
||||
{"MinifigDecals_Eyebrows", new[] {"ID"}},
|
||||
{"MinifigDecals_Eyes", new[] {"ID"}},
|
||||
{"MinifigDecals_Legs", new[] {"ID"}},
|
||||
{"MinifigDecals_Mouths", new[] {"ID"}},
|
||||
{"MinifigDecals_Torsos", new[] {"ID"}},
|
||||
{"MissionEmail", new[] {"ID"}},
|
||||
{"MissionNPCComponent", new[] {"id", "missionID"}},
|
||||
{"MissionTasks", new[] {"id", "uid"}},
|
||||
{"MissionText", new[] {"id"}},
|
||||
{"Missions", new[] {"id"}},
|
||||
{"ModelBehavior", new[] {"id"}},
|
||||
{"ModularBuildComponent", new[] {"id"}},
|
||||
{"ModuleComponent", new[] {"id"}},
|
||||
{"MotionFX", new[] {"id"}},
|
||||
{"MovementAIComponent", new[] {"id"}},
|
||||
{"MovingPlatforms", new[] {"id"}},
|
||||
{"NpcIcons", new[] {"id"}},
|
||||
{"ObjectBehaviorXREF", new[] {"LOT"}},
|
||||
{"ObjectBehaviors", new[] {"BehaviorID"}},
|
||||
{"ObjectSkills", new[] {"objectTemplate", "skillID"}},
|
||||
{"Objects", new[] {"id"}},
|
||||
{"PackageComponent", new[] {"id"}},
|
||||
{"PetAbilities", new[] {"id"}},
|
||||
{"PetComponent", new[] {"id"}},
|
||||
{"PetNestComponent", new[] {"id"}},
|
||||
{"PhysicsComponent", new[] {"id"}},
|
||||
{"PlayerFlags", new[] {"id"}},
|
||||
{"PlayerStatistics", new[] {"statID"}},
|
||||
{"PossessableComponent", new[] {"id"}},
|
||||
{"Preconditions", new[] {"id"}},
|
||||
{"PropertyEntranceComponent", new[] {"id"}},
|
||||
{"PropertyTemplate", new[] {"id"}},
|
||||
{"ProximityMonitorComponent", new[] {"id"}},
|
||||
{"ProximityTypes", new[] {"id"}},
|
||||
{"RacingModuleComponent", new[] {"id"}},
|
||||
{"RailActivatorComponent", new[] {"id"}},
|
||||
{"RarityTable", new[] {"id"}},
|
||||
{"RarityTableIndex", new[] {"RarityTableIndex"}},
|
||||
{"RebuildComponent", new[] {"id"}},
|
||||
{"RebuildSections", new[] {"id"}},
|
||||
{"Release_Version", new[] {"ReleaseVersion"}},
|
||||
{"RenderComponent", new[] {"id"}},
|
||||
{"RenderComponentFlash", new[] {"id", "interactive", "animated", "nodeName", "flashPath", "elementName", "_uid"}},
|
||||
{"RenderComponentWrapper", new[] {"id"}},
|
||||
{"RenderIconAssets", new[] {"id"}},
|
||||
{"ReputationRewards", new[] {"repLevel"}},
|
||||
{"RewardCodes", new[] {"id"}},
|
||||
{"Rewards", new[] {"id"}},
|
||||
{"RocketLaunchpadControlComponent", new[] {"id"}},
|
||||
{"SceneTable", new[] {"sceneID"}},
|
||||
{"ScriptComponent", new[] {"id"}},
|
||||
{"SkillBehavior", new[] {"skillID"}},
|
||||
{"SmashableChain", new[] {"chainIndex", "chainLevel"}},
|
||||
{"SmashableChainIndex", new[] {"id"}},
|
||||
{"SmashableComponent", new[] {"id"}},
|
||||
{"SmashableElements", new[] {"elementID"}},
|
||||
{"SpeedchatMenu", new[] {"id"}},
|
||||
{"SubscriptionPricing", new[] {"id"}},
|
||||
{"SurfaceType", new[] {"SurfaceType"}},
|
||||
{"TamingBuildPuzzles", new[] {"id"}},
|
||||
{"TextDescription", new[] {"TextID"}},
|
||||
{"TextLanguage", new[] {"TextID"}},
|
||||
{"TrailEffects", new[] {"trailID"}},
|
||||
{"UGBehaviorSounds", new[] {"id"}},
|
||||
{"VehiclePhysics", new[] {"id"}},
|
||||
{"VehicleStatMap", new[] {"id", "ModuleStat", "HavokStat"}},
|
||||
{"VendorComponent", new[] {"id"}},
|
||||
{"WhatsCoolItemSpotlight", new[] {"id"}},
|
||||
{"WhatsCoolNewsAndTips", new[] {"id"}},
|
||||
{"WorldConfig", new[] {"WorldConfigID"}},
|
||||
{"ZoneLoadingTips", new[] {"id"}},
|
||||
{"ZoneSummary", new[] {"zoneID", "type", "value", "_uniqueID"}},
|
||||
{"ZoneTable", new[] {"zoneID"}},
|
||||
{"brickAttributes", new[] {"ID"}},
|
||||
{"dtproperties", new[] {"id"}},
|
||||
{"mapAnimationPriorities", new[] {"id"}},
|
||||
{"mapAssetType", new[] {"id"}},
|
||||
{"mapIcon", new[] {"LOT", "iconID", "iconState"}},
|
||||
{"mapItemTypes", new[] {"id"}},
|
||||
{"mapRenderEffects", new[] {"id"}},
|
||||
{"mapShaders", new[] {"id"}},
|
||||
{"mapTextureResource", new[] {"id"}},
|
||||
{"map_BlueprintCategory", new[] {"id"}},
|
||||
{"sysdiagrams", new[] {"name"}}
|
||||
};
|
||||
|
||||
public void Generate(AccessDatabase accessDatabase)
|
||||
{
|
||||
public Dictionary<string, string[]> PrimaryKeys { get; } = new Dictionary<string, string[]>
|
||||
{
|
||||
{"AICombatRoles", new[] {"id"}},
|
||||
{"AccessoryDefaultLoc", new[] {"GroupID"}},
|
||||
{"Activities", new[] {"ActivityID"}},
|
||||
{"ActivityRewards", new[] {"objectTemplate", "ActivityRewardIndex"}},
|
||||
{"ActivityText", new[] {"activityID", "type"}},
|
||||
{"AnimationIndex", new[] {"animationGroupID"}},
|
||||
{"Animations", new[] {"animationGroupID", "animation_type"}},
|
||||
{"BaseCombatAIComponent", new[] {"id"}},
|
||||
{"BehaviorEffect", new[] {"effectID", "effectType"}},
|
||||
{"BehaviorParameter", new[] {"behaviorID", "parameterID"}},
|
||||
{"BehaviorTemplate", new[] {"behaviorID"}},
|
||||
{"BehaviorTemplateName", new[] {"templateID"}},
|
||||
{"Blueprints", new[] {"id"}},
|
||||
{"BrickColors", new[] {"id"}},
|
||||
{"BrickIDTable", new[] {"NDObjectID"}},
|
||||
{"BuffDefinitions", new[] {"ID"}},
|
||||
{"BuffParameters", new[] {"BuffID", "ParameterName"}},
|
||||
{"Camera", new[] {"camera_name"}},
|
||||
{"CelebrationParameters", new[] {"id"}},
|
||||
{"ChoiceBuildComponent", new[] {"id"}},
|
||||
{"CollectibleComponent", new[] {"id"}},
|
||||
{"ComponentsRegistry", new[] {"id", "component_type"}},
|
||||
{"ControlSchemes", new[] {"control_scheme"}},
|
||||
{"CurrencyDenominations", new[] {"value"}},
|
||||
{"CurrencyTable", new[] {"currencyIndex", "npcminlevel"}},
|
||||
{"DBExclude", new[] {"table", "column"}},
|
||||
{"DeletionRestrictions", new[] {"id"}},
|
||||
{"DestructibleComponent", new[] {"id"}},
|
||||
{"DevModelBehaviors", new[] {"ModelID"}},
|
||||
{"Emotes", new[] {"id"}},
|
||||
{"EventGating", new[] {"eventName"}},
|
||||
{"ExhibitComponent", new[] {"id"}},
|
||||
{"Factions", new[] {"faction"}},
|
||||
{"FeatureGating", new[] {"featureName"}},
|
||||
{"FlairTable", new[] {"id"}},
|
||||
{"Icons", new[] {"IconID"}},
|
||||
{"InventoryComponent", new[] {"id", "itemid"}},
|
||||
{"ItemComponent", new[] {"id"}},
|
||||
{"ItemEggData", new[] {"id"}},
|
||||
{"ItemFoodData", new[] {"id"}},
|
||||
{"ItemSetSkills", new[] {"SkillSetID", "SkillID"}},
|
||||
{"ItemSets", new[] {"setID"}},
|
||||
{"JetPackPadComponent", new[] {"id"}},
|
||||
{"LUPExhibitComponent", new[] {"id"}},
|
||||
{"LUPExhibitModelData", new[] {"LOT"}},
|
||||
{"LUPZoneIDs", new[] {"zoneID"}},
|
||||
{"LanguageType", new[] {"LanguageID"}},
|
||||
{"LevelProgressionLookup", new[] {"id"}},
|
||||
{"LootMatrix", new[] {"LootMatrixIndex", "LootTableIndex", "RarityTableIndex"}},
|
||||
{"LootMatrixIndex", new[] {"LootMatrixIndex"}},
|
||||
{"LootTable", new[] {"itemid", "LootTableIndex", "id"}},
|
||||
{"LootTableIndex", new[] {"LootTableIndex"}},
|
||||
{"MinifigComponent", new[] {"id"}},
|
||||
{"MinifigDecals_Eyebrows", new[] {"ID"}},
|
||||
{"MinifigDecals_Eyes", new[] {"ID"}},
|
||||
{"MinifigDecals_Legs", new[] {"ID"}},
|
||||
{"MinifigDecals_Mouths", new[] {"ID"}},
|
||||
{"MinifigDecals_Torsos", new[] {"ID"}},
|
||||
{"MissionEmail", new[] {"ID"}},
|
||||
{"MissionNPCComponent", new[] {"id", "missionID"}},
|
||||
{"MissionTasks", new[] {"id", "uid"}},
|
||||
{"MissionText", new[] {"id"}},
|
||||
{"Missions", new[] {"id"}},
|
||||
{"ModelBehavior", new[] {"id"}},
|
||||
{"ModularBuildComponent", new[] {"id"}},
|
||||
{"ModuleComponent", new[] {"id"}},
|
||||
{"MotionFX", new[] {"id"}},
|
||||
{"MovementAIComponent", new[] {"id"}},
|
||||
{"MovingPlatforms", new[] {"id"}},
|
||||
{"NpcIcons", new[] {"id"}},
|
||||
{"ObjectBehaviorXREF", new[] {"LOT"}},
|
||||
{"ObjectBehaviors", new[] {"BehaviorID"}},
|
||||
{"ObjectSkills", new[] {"objectTemplate", "skillID"}},
|
||||
{"Objects", new[] {"id"}},
|
||||
{"PackageComponent", new[] {"id"}},
|
||||
{"PetAbilities", new[] {"id"}},
|
||||
{"PetComponent", new[] {"id"}},
|
||||
{"PetNestComponent", new[] {"id"}},
|
||||
{"PhysicsComponent", new[] {"id"}},
|
||||
{"PlayerFlags", new[] {"id"}},
|
||||
{"PlayerStatistics", new[] {"statID"}},
|
||||
{"PossessableComponent", new[] {"id"}},
|
||||
{"Preconditions", new[] {"id"}},
|
||||
{"PropertyEntranceComponent", new[] {"id"}},
|
||||
{"PropertyTemplate", new[] {"id"}},
|
||||
{"ProximityMonitorComponent", new[] {"id"}},
|
||||
{"ProximityTypes", new[] {"id"}},
|
||||
{"RacingModuleComponent", new[] {"id"}},
|
||||
{"RailActivatorComponent", new[] {"id"}},
|
||||
{"RarityTable", new[] {"id"}},
|
||||
{"RarityTableIndex", new[] {"RarityTableIndex"}},
|
||||
{"RebuildComponent", new[] {"id"}},
|
||||
{"RebuildSections", new[] {"id"}},
|
||||
{"Release_Version", new[] {"ReleaseVersion"}},
|
||||
{"RenderComponent", new[] {"id"}},
|
||||
{"RenderComponentFlash", new[] {"id", "interactive", "animated", "nodeName", "flashPath", "elementName", "_uid"}},
|
||||
{"RenderComponentWrapper", new[] {"id"}},
|
||||
{"RenderIconAssets", new[] {"id"}},
|
||||
{"ReputationRewards", new[] {"repLevel"}},
|
||||
{"RewardCodes", new[] {"id"}},
|
||||
{"Rewards", new[] {"id"}},
|
||||
{"RocketLaunchpadControlComponent", new[] {"id"}},
|
||||
{"SceneTable", new[] {"sceneID"}},
|
||||
{"ScriptComponent", new[] {"id"}},
|
||||
{"SkillBehavior", new[] {"skillID"}},
|
||||
{"SmashableChain", new[] {"chainIndex", "chainLevel"}},
|
||||
{"SmashableChainIndex", new[] {"id"}},
|
||||
{"SmashableComponent", new[] {"id"}},
|
||||
{"SmashableElements", new[] {"elementID"}},
|
||||
{"SpeedchatMenu", new[] {"id"}},
|
||||
{"SubscriptionPricing", new[] {"id"}},
|
||||
{"SurfaceType", new[] {"SurfaceType"}},
|
||||
{"TamingBuildPuzzles", new[] {"id"}},
|
||||
{"TextDescription", new[] {"TextID"}},
|
||||
{"TextLanguage", new[] {"TextID"}},
|
||||
{"TrailEffects", new[] {"trailID"}},
|
||||
{"UGBehaviorSounds", new[] {"id"}},
|
||||
{"VehiclePhysics", new[] {"id"}},
|
||||
{"VehicleStatMap", new[] {"id", "ModuleStat", "HavokStat"}},
|
||||
{"VendorComponent", new[] {"id"}},
|
||||
{"WhatsCoolItemSpotlight", new[] {"id"}},
|
||||
{"WhatsCoolNewsAndTips", new[] {"id"}},
|
||||
{"WorldConfig", new[] {"WorldConfigID"}},
|
||||
{"ZoneLoadingTips", new[] {"id"}},
|
||||
{"ZoneSummary", new[] {"zoneID", "type", "value", "_uniqueID"}},
|
||||
{"ZoneTable", new[] {"zoneID"}},
|
||||
{"brickAttributes", new[] {"ID"}},
|
||||
{"dtproperties", new[] {"id"}},
|
||||
{"mapAnimationPriorities", new[] {"id"}},
|
||||
{"mapAssetType", new[] {"id"}},
|
||||
{"mapIcon", new[] {"LOT", "iconID", "iconState"}},
|
||||
{"mapItemTypes", new[] {"id"}},
|
||||
{"mapRenderEffects", new[] {"id"}},
|
||||
{"mapShaders", new[] {"id"}},
|
||||
{"mapTextureResource", new[] {"id"}},
|
||||
{"map_BlueprintCategory", new[] {"id"}},
|
||||
{"sysdiagrams", new[] {"name"}}
|
||||
};
|
||||
|
||||
public void Generate(AccessDatabase accessDatabase)
|
||||
foreach (var table in accessDatabase)
|
||||
{
|
||||
foreach (var table in accessDatabase)
|
||||
{
|
||||
var info = table.TableInfo;
|
||||
var rows = table.ToArray();
|
||||
var info = table.TableInfo;
|
||||
var rows = table.ToArray();
|
||||
|
||||
var primaryKey = new List<string>();
|
||||
var primaryKey = new List<string>();
|
||||
|
||||
for (var i = 0; i < info.Count; ++i)
|
||||
for (var i = 0; i < info.Count; ++i)
|
||||
{
|
||||
primaryKey.Add(info[i].Name);
|
||||
|
||||
// Check if there are duplicates of this value in the table.
|
||||
var index = i;
|
||||
|
||||
var values = rows.Where(r => r[index].Value != null).Select(r => r[index].Value).ToArray();
|
||||
|
||||
var containsDuplicates = values.Count() != values.Distinct().Count();
|
||||
|
||||
if (!containsDuplicates)
|
||||
{
|
||||
primaryKey.Add(info[i].Name);
|
||||
|
||||
// Check if there are duplicates of this value in the table.
|
||||
var index = i;
|
||||
|
||||
var values = rows.Where(r => r[index].Value != null).Select(r => r[index].Value).ToArray();
|
||||
|
||||
var containsDuplicates = values.Count() != values.Distinct().Count();
|
||||
|
||||
if (!containsDuplicates)
|
||||
{
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
PrimaryKeys.Add(table.Name, primaryKey.ToArray());
|
||||
}
|
||||
|
||||
PrimaryKeys.Add(table.Name, primaryKey.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,43 +1,42 @@
|
||||
using System.Collections.Generic;
|
||||
using InfectedRose.Database;
|
||||
|
||||
namespace InfectedRose.Interface
|
||||
{
|
||||
public static class TableExtensions
|
||||
{
|
||||
public static Row FromLookup(this Table @this, string id)
|
||||
{
|
||||
return !ModContext.Lookup.TryGetValue(id, out var value) ? @this.Create() : @this.Create(value);
|
||||
}
|
||||
|
||||
public static Row FromLookup(this Table @this, Mod mod)
|
||||
{
|
||||
if (mod.Id.StartsWith("lego-universe:"))
|
||||
{
|
||||
@this.Seek(int.Parse(mod.Id[14..]), out var row);
|
||||
namespace InfectedRose.Interface;
|
||||
|
||||
return row;
|
||||
}
|
||||
public static class TableExtensions
|
||||
{
|
||||
public static Row FromLookup(this Table @this, string id)
|
||||
{
|
||||
return !ModContext.Lookup.TryGetValue(id, out var value) ? @this.Create() : @this.Create(value);
|
||||
}
|
||||
|
||||
public static Row FromLookup(this Table @this, Mod mod)
|
||||
{
|
||||
if (mod.Id.StartsWith("lego-universe:"))
|
||||
{
|
||||
@this.Seek(int.Parse(mod.Id[14..]), out var row);
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
if (ModContext.Lookup.TryGetValue(mod.Id, out var value))
|
||||
if (ModContext.Lookup.TryGetValue(mod.Id, out var value))
|
||||
{
|
||||
return @this.Create(value);
|
||||
}
|
||||
|
||||
if (mod.OldIds == null)
|
||||
{
|
||||
return @this.CreateWithFilter(ModContext.Lookup.Values);
|
||||
}
|
||||
|
||||
foreach (var oldId in mod.OldIds)
|
||||
{
|
||||
if (ModContext.Lookup.TryGetValue(oldId, out value))
|
||||
{
|
||||
return @this.Create(value);
|
||||
}
|
||||
|
||||
if (mod.OldIds == null)
|
||||
{
|
||||
return @this.CreateWithFilter(ModContext.Lookup.Values);
|
||||
}
|
||||
|
||||
foreach (var oldId in mod.OldIds)
|
||||
{
|
||||
if (ModContext.Lookup.TryGetValue(oldId, out value))
|
||||
{
|
||||
return @this.Create(value);
|
||||
}
|
||||
}
|
||||
|
||||
throw new KeyNotFoundException($"Could not determine the ID of {mod.Id}, no old ids match lookup.json.");
|
||||
}
|
||||
|
||||
throw new KeyNotFoundException($"Could not determine the ID of {mod.Id}, no old ids match lookup.json.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,77 +3,93 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface.Templates
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
public class Behavior
|
||||
{
|
||||
public class Behavior
|
||||
{
|
||||
[JsonPropertyName("template-id")]
|
||||
public string Template { get; set; }
|
||||
[JsonPropertyName("template")]
|
||||
public string Template { get; set; }
|
||||
|
||||
[JsonPropertyName("effect")]
|
||||
public Effect? Effect { get; set; }
|
||||
[JsonPropertyName("effect")]
|
||||
public Effect? Effect { get; set; }
|
||||
|
||||
[JsonPropertyName("effect-handle")]
|
||||
public string? EffectHandle { get; set; }
|
||||
[JsonPropertyName("effect-handle")]
|
||||
public string? EffectHandle { get; set; }
|
||||
|
||||
[JsonPropertyName("parameters")]
|
||||
public Dictionary<string, object> Parameters { get; set; }
|
||||
[JsonPropertyName("parameters")]
|
||||
public Dictionary<string, object>? Parameters { get; set; }
|
||||
|
||||
public int Apply(string id)
|
||||
public int Apply(string id)
|
||||
{
|
||||
var behaviorTemplateTable = ModContext.Database["BehaviorTemplate"]!;
|
||||
var behaviorParameterTable = ModContext.Database["BehaviorParameter"]!;
|
||||
var behaviorTemplateNameTable = ModContext.Database["BehaviorTemplateName"]!;
|
||||
|
||||
var templateName = behaviorTemplateNameTable.FirstOrDefault(t => (string) t["name"].Value == Template);
|
||||
|
||||
if (templateName == null)
|
||||
{
|
||||
var behaviorTemplateTable = ModContext.Database["BehaviorTemplate"]!;
|
||||
var behaviorParameterTable = ModContext.Database["BehaviorParameter"]!;
|
||||
var behaviorTemplateNameTable = ModContext.Database["BehaviorTemplateName"]!;
|
||||
|
||||
var templateName = behaviorTemplateNameTable.FirstOrDefault(t => (string) t["name"].Value == Template);
|
||||
|
||||
if (templateName == null)
|
||||
{
|
||||
throw new Exception($"Invalid behavior template {Template}!");
|
||||
}
|
||||
|
||||
var behaviorTemplate = behaviorTemplateTable.FromLookup(id);
|
||||
|
||||
ModContext.RegisterId(id, behaviorTemplate.Key);
|
||||
|
||||
behaviorTemplate["templateID"].Value = (int) templateName["templateID"].Value;
|
||||
var effectId = behaviorTemplate["effectID"];
|
||||
if (Effect == null)
|
||||
{
|
||||
effectId.Value = 0;
|
||||
}
|
||||
else if (Effect.Id.StartsWith("lego-universe"))
|
||||
{
|
||||
effectId.Value = Effect.Id.Split(":")[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
effectId.Value = Effect.Apply();
|
||||
}
|
||||
|
||||
behaviorTemplate["effectHandle"].Value = EffectHandle;
|
||||
|
||||
foreach (var (key, value) in Parameters)
|
||||
{
|
||||
var parameter = behaviorParameterTable.Create(behaviorTemplate.Key);
|
||||
parameter["parameterID"].Value = key;
|
||||
|
||||
var valueField = parameter["value"];
|
||||
|
||||
if (float.TryParse(value.ToString(), out var f))
|
||||
{
|
||||
valueField.Value = f;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
ModContext.AwaitId(value.ToString()!, i =>
|
||||
{
|
||||
valueField.Value = (float) i;
|
||||
});
|
||||
}
|
||||
|
||||
return behaviorTemplate.Key;
|
||||
throw new Exception($"Invalid behavior template {Template}!");
|
||||
}
|
||||
|
||||
var behaviorTemplate = behaviorTemplateTable.FromLookup(id);
|
||||
|
||||
ModContext.RegisterId(id, behaviorTemplate.Key);
|
||||
|
||||
behaviorTemplate["templateID"].Value = (int) templateName["templateID"].Value;
|
||||
var effectId = behaviorTemplate["effectID"];
|
||||
if (Effect == null)
|
||||
{
|
||||
effectId.Value = 0;
|
||||
}
|
||||
else if (Effect.Id.StartsWith("lego-universe"))
|
||||
{
|
||||
effectId.Value = Effect.Id.Split(":")[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
effectId.Value = Effect.Apply();
|
||||
}
|
||||
|
||||
behaviorTemplate["effectHandle"].Value = EffectHandle;
|
||||
|
||||
if (Parameters == null) return behaviorTemplate.Key;
|
||||
|
||||
foreach (var (key, value) in Parameters)
|
||||
{
|
||||
var parameter = behaviorParameterTable.Create(behaviorTemplate.Key);
|
||||
parameter["parameterID"].Value = key;
|
||||
|
||||
var valueField = parameter["value"];
|
||||
|
||||
if (float.TryParse(value.ToString(), out var f))
|
||||
{
|
||||
valueField.Value = f;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if true or false
|
||||
if (value.ToString()!.Equals("true", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
valueField.Value = 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value.ToString()!.Equals("false", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
valueField.Value = 0;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
ModContext.AwaitId(value.ToString()!, i =>
|
||||
{
|
||||
valueField.Value = (float) i;
|
||||
});
|
||||
}
|
||||
|
||||
return behaviorTemplate.Key;
|
||||
}
|
||||
}
|
||||
@@ -1,109 +1,108 @@
|
||||
namespace InfectedRose.Interface.Templates
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
public enum ComponentId
|
||||
{
|
||||
public enum ComponentId
|
||||
{
|
||||
ControllablePhysicsComponent = 1,
|
||||
RenderComponent = 2,
|
||||
SimplePhysicsComponent = 3,
|
||||
CharacterComponent = 4,
|
||||
ScriptComponent = 5,
|
||||
BouncerComponent = 6,
|
||||
DestructibleComponent = 7,
|
||||
GhostComponent = 8,
|
||||
SkillComponent = 9,
|
||||
SpawnerComponent = 10,
|
||||
ItemComponent = 11,
|
||||
RebuildComponent = 12,
|
||||
RebuildStartComponent = 13,
|
||||
RebuildActivatorComponent = 14,
|
||||
IconOnlyComponent = 15,
|
||||
VendorComponent = 16,
|
||||
InventoryComponent = 17,
|
||||
ProjectilePhysicsComponent = 18,
|
||||
ShootingGalleryComponent = 19,
|
||||
RigidBodyPhantomPhysicsComponent = 20,
|
||||
DropEffectComponent = 21,
|
||||
ChestComponent = 22,
|
||||
CollectibleComponent = 23,
|
||||
BlueprintComponent = 24,
|
||||
MovingPlatformComponent = 25,
|
||||
PetComponent = 26,
|
||||
PlatformBoundaryComponent = 27,
|
||||
ModuleComponent = 28,
|
||||
ArcadeComponent = 29,
|
||||
VehiclePhysicsComponent = 30,
|
||||
MovementAIComponent = 31,
|
||||
ExhibitComponent = 32,
|
||||
OverheadIconComponent = 33,
|
||||
PetControlComponent = 34,
|
||||
MinifigComponent = 35,
|
||||
PropertyComponent = 36,
|
||||
PetCreatorComponent = 37,
|
||||
ModelBuilderComponent = 38,
|
||||
ScriptedActivityComponent = 39,
|
||||
PhantomPhysicsComponent = 40,
|
||||
SpringpadComponent = 41,
|
||||
B3BehaviorsComponent = 42,
|
||||
PropertyEntranceComponent = 43,
|
||||
FXComponent = 44,
|
||||
PropertyManagementComponent = 45,
|
||||
SecondVehiclePhysicsComponent = 46,
|
||||
PhysicsSystemComponent = 47,
|
||||
QuickBuildComponent = 48,
|
||||
SwitchComponent = 49,
|
||||
MinigameComponent = 50,
|
||||
ChanglingComponent = 51,
|
||||
ChoiceBuildComponent = 52,
|
||||
PackageComponent = 53,
|
||||
SoundRepeaterComponent = 54,
|
||||
SoundAmbient2DComponent = 55,
|
||||
SoundAmbient3DComponent = 56,
|
||||
PreconditionComponent = 57,
|
||||
PlayerFlagsComponent = 58,
|
||||
CustomBuildAssemblyComponent = 59,
|
||||
BaseCombatAIComponent = 60,
|
||||
ModuleAssemblyComponent = 61,
|
||||
ShowcaseModelHandlerComponent = 62,
|
||||
RacingModuleComponent = 63,
|
||||
GenericActivatorComponent = 64,
|
||||
PropertyVendorComponent = 65,
|
||||
HFLightDirectionGadgetComponent = 66,
|
||||
RocketLaunchComponent = 67,
|
||||
RocketLandingComponent = 68,
|
||||
TriggerComponent = 69,
|
||||
DroppedLootComponent = 70,
|
||||
RacingControlComponent = 71,
|
||||
FactionTriggerComponent = 72,
|
||||
MissionNPCComponent = 73,
|
||||
RacingStatsComponent = 74,
|
||||
LUPExhibitComponent = 75,
|
||||
BBBComponent = 76,
|
||||
SoundTriggerComponent = 77,
|
||||
ProximityMonitorComponent = 78,
|
||||
RacingSoundTriggerComponent = 79,
|
||||
ChatComponent = 80,
|
||||
FriendsListComponent = 81,
|
||||
GuildComponent = 82,
|
||||
LocalSystemComponent = 83,
|
||||
MissionComponent = 84,
|
||||
MutableModelBehaviorsComponent = 85,
|
||||
PathfindingControlComponent = 86,
|
||||
PetTamingControlComponent = 87,
|
||||
PropertyEditorComponent = 88,
|
||||
SkinnedRenderComponent = 89,
|
||||
SlashCommandComponent = 90,
|
||||
StatusEffectComponent = 91,
|
||||
TeamsComponent = 92,
|
||||
TextEffectComponent = 93,
|
||||
TradeComponent = 94,
|
||||
UserControlComponent = 95,
|
||||
IgnoreListComponent = 96,
|
||||
LUPLaunchpadComponent = 97,
|
||||
BuffComponent = 98,
|
||||
InteractionManagerComponent = 98,
|
||||
DonationVendorComponent = 100,
|
||||
CombatMediatorComponent = 101,
|
||||
Component107 = 107,
|
||||
Possesable = 108
|
||||
}
|
||||
ControllablePhysicsComponent = 1,
|
||||
RenderComponent = 2,
|
||||
SimplePhysicsComponent = 3,
|
||||
CharacterComponent = 4,
|
||||
ScriptComponent = 5,
|
||||
BouncerComponent = 6,
|
||||
DestructibleComponent = 7,
|
||||
GhostComponent = 8,
|
||||
SkillComponent = 9,
|
||||
SpawnerComponent = 10,
|
||||
ItemComponent = 11,
|
||||
RebuildComponent = 12,
|
||||
RebuildStartComponent = 13,
|
||||
RebuildActivatorComponent = 14,
|
||||
IconOnlyComponent = 15,
|
||||
VendorComponent = 16,
|
||||
InventoryComponent = 17,
|
||||
ProjectilePhysicsComponent = 18,
|
||||
ShootingGalleryComponent = 19,
|
||||
RigidBodyPhantomPhysicsComponent = 20,
|
||||
DropEffectComponent = 21,
|
||||
ChestComponent = 22,
|
||||
CollectibleComponent = 23,
|
||||
BlueprintComponent = 24,
|
||||
MovingPlatformComponent = 25,
|
||||
PetComponent = 26,
|
||||
PlatformBoundaryComponent = 27,
|
||||
ModuleComponent = 28,
|
||||
ArcadeComponent = 29,
|
||||
VehiclePhysicsComponent = 30,
|
||||
MovementAIComponent = 31,
|
||||
ExhibitComponent = 32,
|
||||
OverheadIconComponent = 33,
|
||||
PetControlComponent = 34,
|
||||
MinifigComponent = 35,
|
||||
PropertyComponent = 36,
|
||||
PetCreatorComponent = 37,
|
||||
ModelBuilderComponent = 38,
|
||||
ScriptedActivityComponent = 39,
|
||||
PhantomPhysicsComponent = 40,
|
||||
SpringpadComponent = 41,
|
||||
B3BehaviorsComponent = 42,
|
||||
PropertyEntranceComponent = 43,
|
||||
FXComponent = 44,
|
||||
PropertyManagementComponent = 45,
|
||||
SecondVehiclePhysicsComponent = 46,
|
||||
PhysicsSystemComponent = 47,
|
||||
QuickBuildComponent = 48,
|
||||
SwitchComponent = 49,
|
||||
MinigameComponent = 50,
|
||||
ChanglingComponent = 51,
|
||||
ChoiceBuildComponent = 52,
|
||||
PackageComponent = 53,
|
||||
SoundRepeaterComponent = 54,
|
||||
SoundAmbient2DComponent = 55,
|
||||
SoundAmbient3DComponent = 56,
|
||||
PreconditionComponent = 57,
|
||||
PlayerFlagsComponent = 58,
|
||||
CustomBuildAssemblyComponent = 59,
|
||||
BaseCombatAIComponent = 60,
|
||||
ModuleAssemblyComponent = 61,
|
||||
ShowcaseModelHandlerComponent = 62,
|
||||
RacingModuleComponent = 63,
|
||||
GenericActivatorComponent = 64,
|
||||
PropertyVendorComponent = 65,
|
||||
HFLightDirectionGadgetComponent = 66,
|
||||
RocketLaunchComponent = 67,
|
||||
RocketLandingComponent = 68,
|
||||
TriggerComponent = 69,
|
||||
DroppedLootComponent = 70,
|
||||
RacingControlComponent = 71,
|
||||
FactionTriggerComponent = 72,
|
||||
MissionNPCComponent = 73,
|
||||
RacingStatsComponent = 74,
|
||||
LUPExhibitComponent = 75,
|
||||
BBBComponent = 76,
|
||||
SoundTriggerComponent = 77,
|
||||
ProximityMonitorComponent = 78,
|
||||
RacingSoundTriggerComponent = 79,
|
||||
ChatComponent = 80,
|
||||
FriendsListComponent = 81,
|
||||
GuildComponent = 82,
|
||||
LocalSystemComponent = 83,
|
||||
MissionComponent = 84,
|
||||
MutableModelBehaviorsComponent = 85,
|
||||
PathfindingControlComponent = 86,
|
||||
PetTamingControlComponent = 87,
|
||||
PropertyEditorComponent = 88,
|
||||
SkinnedRenderComponent = 89,
|
||||
SlashCommandComponent = 90,
|
||||
StatusEffectComponent = 91,
|
||||
TeamsComponent = 92,
|
||||
TextEffectComponent = 93,
|
||||
TradeComponent = 94,
|
||||
UserControlComponent = 95,
|
||||
IgnoreListComponent = 96,
|
||||
LUPLaunchpadComponent = 97,
|
||||
BuffComponent = 98,
|
||||
InteractionManagerComponent = 98,
|
||||
DonationVendorComponent = 100,
|
||||
CombatMediatorComponent = 101,
|
||||
Component107 = 107,
|
||||
Possesable = 108
|
||||
}
|
||||
@@ -1,60 +1,59 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface.Templates
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
public class Effect
|
||||
{
|
||||
public class Effect
|
||||
[JsonPropertyName("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonPropertyName("type")]
|
||||
public string EffectType { get; set; }
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string EffectName { get; set; }
|
||||
|
||||
[JsonPropertyName("animation")]
|
||||
public string AnimationName { get; set; }
|
||||
|
||||
[JsonPropertyName("bone")]
|
||||
public string BoneName { get; set; }
|
||||
|
||||
[JsonPropertyName("values")]
|
||||
public Dictionary<string, object> Values { get; set; }
|
||||
|
||||
public int Apply()
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public string Id { get; set; }
|
||||
var behaviorEffectTable = ModContext.Database["BehaviorEffect"];
|
||||
|
||||
[JsonPropertyName("type")]
|
||||
public string EffectType { get; set; }
|
||||
var behaviorEffect = behaviorEffectTable.FromLookup(Id);
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string EffectName { get; set; }
|
||||
ModContext.RegisterId(Id, behaviorEffect.Key);
|
||||
|
||||
[JsonPropertyName("animation")]
|
||||
public string AnimationName { get; set; }
|
||||
|
||||
[JsonPropertyName("bone")]
|
||||
public string BoneName { get; set; }
|
||||
|
||||
[JsonPropertyName("values")]
|
||||
public Dictionary<string, object> Values { get; set; }
|
||||
|
||||
public int Apply()
|
||||
foreach (var field in behaviorEffect)
|
||||
{
|
||||
var behaviorEffectTable = ModContext.Database["BehaviorEffect"];
|
||||
|
||||
var behaviorEffect = behaviorEffectTable.FromLookup(Id);
|
||||
|
||||
ModContext.RegisterId(Id, behaviorEffect.Key);
|
||||
|
||||
foreach (var field in behaviorEffect)
|
||||
switch (field.Name)
|
||||
{
|
||||
switch (field.Name)
|
||||
{
|
||||
case "effectID":
|
||||
break;
|
||||
case "effectType":
|
||||
field.Value = EffectType;
|
||||
break;
|
||||
case "effectName":
|
||||
field.Value = EffectName;
|
||||
break;
|
||||
case "animationName":
|
||||
field.Value = AnimationName;
|
||||
break;
|
||||
case "boneName":
|
||||
field.Value = BoneName;
|
||||
break;
|
||||
}
|
||||
case "effectID":
|
||||
break;
|
||||
case "effectType":
|
||||
field.Value = EffectType;
|
||||
break;
|
||||
case "effectName":
|
||||
field.Value = EffectName;
|
||||
break;
|
||||
case "animationName":
|
||||
field.Value = AnimationName;
|
||||
break;
|
||||
case "boneName":
|
||||
field.Value = BoneName;
|
||||
break;
|
||||
}
|
||||
|
||||
ModContext.ApplyValues(Values, behaviorEffect, behaviorEffectTable, true);
|
||||
|
||||
return behaviorEffect.Key;
|
||||
}
|
||||
|
||||
ModContext.ApplyValues(Values, behaviorEffect, behaviorEffectTable, true);
|
||||
|
||||
return behaviorEffect.Key;
|
||||
}
|
||||
}
|
||||
@@ -1,104 +1,103 @@
|
||||
namespace InfectedRose.Interface.Templates
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
[ModType("enemy")]
|
||||
public class EnemyMod : ModType
|
||||
{
|
||||
[ModType("enemy")]
|
||||
public class EnemyMod : ModType
|
||||
public override void Apply(Mod mod)
|
||||
{
|
||||
public override void Apply(Mod mod)
|
||||
if (mod.Action != "add")
|
||||
{
|
||||
if (mod.Action != "add")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Controller
|
||||
mod.Default("physics_asset", @"miscellaneous\standard_enemy.hkx");
|
||||
mod.Default("static", 0);
|
||||
mod.Default("jump", 4);
|
||||
mod.Default("doublejump", 0);
|
||||
mod.Default("speed", 8);
|
||||
mod.Default("rotSpeed", 720);
|
||||
mod.Default("playerHeight", 4.4f);
|
||||
mod.Default("playerRadius", 1.7f);
|
||||
mod.Default("pcShapeType", 0);
|
||||
mod.Default("collisionGroup", 12);
|
||||
mod.Default("airSpeed", 5);
|
||||
mod.Default("jumpAirSpeed", 25);
|
||||
|
||||
// Render
|
||||
mod.Default("render_asset", @"animations\\creatures\\cre_strombie.kfm");
|
||||
mod.Default("animationGroupIDs", "513,535");
|
||||
mod.Default("shader_id", 66);
|
||||
mod.DefaultNull("interactionDistance");
|
||||
mod.DefaultNull("chatBubbleOffset");
|
||||
mod.Default("fade", true);
|
||||
mod.Default("fadeInTime", 0.1f);
|
||||
mod.DefaultNull("billboardHeight");
|
||||
mod.DefaultNull("AudioMetaEventSet");
|
||||
mod.Default("usedropshadow", false);
|
||||
mod.Default("preloadAnimations", false);
|
||||
mod.Default("ignoreCameraCollision", false);
|
||||
mod.Default("gradualSnap", false);
|
||||
mod.Default("staticBillboard", false);
|
||||
mod.Default("attachIndicatorsToNode", false);
|
||||
|
||||
// Destroyable
|
||||
mod.Default("life", 1);
|
||||
mod.Default("armor", 0);
|
||||
mod.Default("imagination", 0);
|
||||
mod.Default("level", 1);
|
||||
mod.Default("faction", 4);
|
||||
mod.Default("factionList", "4");
|
||||
mod.Default("isnpc", true);
|
||||
mod.Default("isSmashable", true);
|
||||
mod.Default("attack_priority", 1);
|
||||
mod.Default("death_behavior", 2);
|
||||
mod.Default("CurrencyIndex", 1);
|
||||
mod.Default("LootMatrixIndex", 160);
|
||||
mod.DefaultNull("difficultyLevel");
|
||||
|
||||
// Movement
|
||||
mod.Default("MovementType", "Wander");
|
||||
mod.Default("WanderChance", 90);
|
||||
mod.Default("WanderDelayMin", 3);
|
||||
mod.Default("WanderDelayMax", 6);
|
||||
mod.Default("WanderSpeed", 0.5f);
|
||||
mod.Default("WanderRadius", 8);
|
||||
mod.DefaultNull("attachedPath");
|
||||
|
||||
// BaseCombatAI
|
||||
mod.Default("behaviorType", 1);
|
||||
mod.Default("minRoundLength", 3);
|
||||
mod.Default("maxRoundLength", 5);
|
||||
mod.Default("pursuitSpeed", 2);
|
||||
mod.Default("spawnTimer", 1);
|
||||
mod.Default("tetherSpeed", 4);
|
||||
mod.Default("softTetherRadius", 25);
|
||||
mod.Default("hardTetherRadius", 101);
|
||||
mod.Default("tetherEffectID", 6270);
|
||||
mod.Default("combatRoundLength", 4);
|
||||
mod.Default("combatRole", 5);
|
||||
mod.Default("combatStartDelay", 1.5f);
|
||||
mod.Default("aggroRadius", 25);
|
||||
mod.Default("ignoreMediator", true);
|
||||
mod.Default("ignoreStatReset", false);
|
||||
mod.Default("ignoreParent", false);
|
||||
|
||||
// Object
|
||||
mod.DefaultNull("npcTemplateID");
|
||||
mod.Default("nametag", true);
|
||||
mod.Default("placeable", true);
|
||||
mod.Default("localize", true);
|
||||
mod.Default("locStatus", 2);
|
||||
|
||||
var obj = ObjectMod.CreateObject(mod);
|
||||
|
||||
obj["type"].Value = "Enemies";
|
||||
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.ControllablePhysicsComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.RenderComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.DestructibleComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.MovementAIComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.BaseCombatAIComponent);
|
||||
return;
|
||||
}
|
||||
|
||||
// Controller
|
||||
mod.Default("physics_asset", @"miscellaneous\standard_enemy.hkx");
|
||||
mod.Default("static", 0);
|
||||
mod.Default("jump", 4);
|
||||
mod.Default("doublejump", 0);
|
||||
mod.Default("speed", 8);
|
||||
mod.Default("rotSpeed", 720);
|
||||
mod.Default("playerHeight", 4.4f);
|
||||
mod.Default("playerRadius", 1.7f);
|
||||
mod.Default("pcShapeType", 0);
|
||||
mod.Default("collisionGroup", 12);
|
||||
mod.Default("airSpeed", 5);
|
||||
mod.Default("jumpAirSpeed", 25);
|
||||
|
||||
// Render
|
||||
mod.Default("render_asset", @"animations\\creatures\\cre_strombie.kfm");
|
||||
mod.Default("animationGroupIDs", "513,535");
|
||||
mod.Default("shader_id", 66);
|
||||
mod.DefaultNull("interactionDistance");
|
||||
mod.DefaultNull("chatBubbleOffset");
|
||||
mod.Default("fade", true);
|
||||
mod.Default("fadeInTime", 0.1f);
|
||||
mod.DefaultNull("billboardHeight");
|
||||
mod.DefaultNull("AudioMetaEventSet");
|
||||
mod.Default("usedropshadow", false);
|
||||
mod.Default("preloadAnimations", false);
|
||||
mod.Default("ignoreCameraCollision", false);
|
||||
mod.Default("gradualSnap", false);
|
||||
mod.Default("staticBillboard", false);
|
||||
mod.Default("attachIndicatorsToNode", false);
|
||||
|
||||
// Destroyable
|
||||
mod.Default("life", 1);
|
||||
mod.Default("armor", 0);
|
||||
mod.Default("imagination", 0);
|
||||
mod.Default("level", 1);
|
||||
mod.Default("faction", 4);
|
||||
mod.Default("factionList", "4");
|
||||
mod.Default("isnpc", true);
|
||||
mod.Default("isSmashable", true);
|
||||
mod.Default("attack_priority", 1);
|
||||
mod.Default("death_behavior", 2);
|
||||
mod.Default("CurrencyIndex", 1);
|
||||
mod.Default("LootMatrixIndex", 160);
|
||||
mod.DefaultNull("difficultyLevel");
|
||||
|
||||
// Movement
|
||||
mod.Default("MovementType", "Wander");
|
||||
mod.Default("WanderChance", 90);
|
||||
mod.Default("WanderDelayMin", 3);
|
||||
mod.Default("WanderDelayMax", 6);
|
||||
mod.Default("WanderSpeed", 0.5f);
|
||||
mod.Default("WanderRadius", 8);
|
||||
mod.DefaultNull("attachedPath");
|
||||
|
||||
// BaseCombatAI
|
||||
mod.Default("behaviorType", 1);
|
||||
mod.Default("minRoundLength", 3);
|
||||
mod.Default("maxRoundLength", 5);
|
||||
mod.Default("pursuitSpeed", 2);
|
||||
mod.Default("spawnTimer", 1);
|
||||
mod.Default("tetherSpeed", 4);
|
||||
mod.Default("softTetherRadius", 25);
|
||||
mod.Default("hardTetherRadius", 101);
|
||||
mod.Default("tetherEffectID", 6270);
|
||||
mod.Default("combatRoundLength", 4);
|
||||
mod.Default("combatRole", 5);
|
||||
mod.Default("combatStartDelay", 1.5f);
|
||||
mod.Default("aggroRadius", 25);
|
||||
mod.Default("ignoreMediator", true);
|
||||
mod.Default("ignoreStatReset", false);
|
||||
mod.Default("ignoreParent", false);
|
||||
|
||||
// Object
|
||||
mod.DefaultNull("npcTemplateID");
|
||||
mod.Default("nametag", true);
|
||||
mod.Default("placeable", true);
|
||||
mod.Default("localize", true);
|
||||
mod.Default("locStatus", 2);
|
||||
|
||||
var obj = ObjectMod.CreateObject(mod);
|
||||
|
||||
obj["type"].Value = "Enemies";
|
||||
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.ControllablePhysicsComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.RenderComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.DestructibleComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.MovementAIComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.BaseCombatAIComponent);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,23 @@
|
||||
namespace InfectedRose.Interface.Templates
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
[ModType("environmental")]
|
||||
public class EnvironmentalMod : ModType
|
||||
{
|
||||
[ModType("environmental")]
|
||||
public class EnvironmentalMod : ModType
|
||||
public override void Apply(Mod mod)
|
||||
{
|
||||
public override void Apply(Mod mod)
|
||||
if (mod.Action != "add")
|
||||
{
|
||||
if (mod.Action != "add")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mod.Default("static", 1);
|
||||
mod.Default("shader_id", 1);
|
||||
|
||||
var obj = ObjectMod.CreateObject(mod);
|
||||
|
||||
obj["type"].Value = "Environmental";
|
||||
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.RenderComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.SimplePhysicsComponent);
|
||||
return;
|
||||
}
|
||||
|
||||
mod.Default("static", 1);
|
||||
mod.Default("shader_id", 1);
|
||||
|
||||
var obj = ObjectMod.CreateObject(mod);
|
||||
|
||||
obj["type"].Value = "Environmental";
|
||||
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.RenderComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.SimplePhysicsComponent);
|
||||
}
|
||||
}
|
||||
13
InfectedRose.Interface/Templates/FileMod.cs
Normal file
13
InfectedRose.Interface/Templates/FileMod.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
[ModType("file")]
|
||||
public class FileMod : ModType
|
||||
{
|
||||
public override void Apply(Mod mod)
|
||||
{
|
||||
var source = mod.GetValue<string>("source");
|
||||
var destination = mod.GetValue<string>("destination");
|
||||
|
||||
ModContext.CreateArtifactFrom(source, destination);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,25 @@
|
||||
namespace InfectedRose.Interface.Templates
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
[ModType("flag")]
|
||||
public class FlagMod : ModType
|
||||
{
|
||||
[ModType("flag")]
|
||||
public class FlagMod : ModType
|
||||
public override void Apply(Mod mod)
|
||||
{
|
||||
public override void Apply(Mod mod)
|
||||
if (mod.Action != "add")
|
||||
{
|
||||
if (mod.Action != "add")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mod.Default("SessionOnly", false);
|
||||
mod.Default("OnlySetByServer", false);
|
||||
mod.Default("SessionZoneOnly", false);
|
||||
|
||||
var flags = ModContext.Database["PlayerFlags"]!;
|
||||
|
||||
var row = flags.Create();
|
||||
|
||||
ModContext.ApplyValues(mod, row, flags);
|
||||
|
||||
ModContext.RegisterId(mod.Id, row.Key);
|
||||
return;
|
||||
}
|
||||
|
||||
mod.Default("SessionOnly", false);
|
||||
mod.Default("OnlySetByServer", false);
|
||||
mod.Default("SessionZoneOnly", false);
|
||||
|
||||
var flags = ModContext.Database["PlayerFlags"]!;
|
||||
|
||||
var row = flags.Create();
|
||||
|
||||
ModContext.ApplyValues(mod, row, flags);
|
||||
|
||||
ModContext.RegisterId(mod.Id, row.Key);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,47 @@
|
||||
namespace InfectedRose.Interface.Templates
|
||||
using System;
|
||||
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
[ModType("item")]
|
||||
public class ItemMod : ModType
|
||||
{
|
||||
[ModType("item")]
|
||||
public class ItemMod : ModType
|
||||
public override void Apply(Mod mod)
|
||||
{
|
||||
public override void Apply(Mod mod)
|
||||
if (mod.Action != "add")
|
||||
{
|
||||
if (mod.Action != "add")
|
||||
{
|
||||
return;
|
||||
}
|
||||
throw new Exception("ItemMod can only be used with the add action");
|
||||
}
|
||||
|
||||
mod.Default("nametag", false);
|
||||
mod.Default("placeable", false);
|
||||
mod.Default("localize", true);
|
||||
mod.Default("locStatus", 2);
|
||||
mod.Default("offsetGroupID", 78);
|
||||
mod.Default("itemInfo", 0);
|
||||
mod.Default("fade", true);
|
||||
mod.Default("fadeInTime", 1);
|
||||
mod.Default("shader_id", 23);
|
||||
mod.Default("audioEquipMetaEventSet", "Weapon_Hammer_Generic");
|
||||
mod.Default("nametag", false);
|
||||
mod.Default("placeable", false);
|
||||
mod.Default("localize", true);
|
||||
mod.Default("locStatus", 2);
|
||||
mod.Default("offsetGroupID", 78);
|
||||
mod.Default("itemInfo", 0);
|
||||
mod.Default("fade", true);
|
||||
mod.Default("fadeInTime", 1);
|
||||
mod.Default("shader_id", 23);
|
||||
mod.Default("audioEquipMetaEventSet", "Weapon_Hammer_Generic");
|
||||
|
||||
if (mod.HasValue("icon"))
|
||||
{
|
||||
var iconId = ModContext.AddIcon(mod.GetValue<string>("icon"), out var path);
|
||||
|
||||
var obj = ObjectMod.CreateObject(mod);
|
||||
mod.Values["icon_asset"] = path;
|
||||
mod.Values["IconID"] = iconId;
|
||||
}
|
||||
|
||||
obj["type"].Value = "Loot";
|
||||
var obj = ObjectMod.CreateObject(mod, false);
|
||||
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.RenderComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.ItemComponent);
|
||||
obj["type"].Value = "Loot";
|
||||
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.RenderComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.ItemComponent);
|
||||
|
||||
if (mod.HasValue("icon"))
|
||||
{
|
||||
mod.Values.Remove("icon_asset");
|
||||
mod.Values.Remove("IconID");
|
||||
}
|
||||
}
|
||||
}
|
||||
13
InfectedRose.Interface/Templates/LocaleMod.cs
Normal file
13
InfectedRose.Interface/Templates/LocaleMod.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
[ModType("locale")]
|
||||
public class LocaleMod : ModType
|
||||
{
|
||||
public override void Apply(Mod mod)
|
||||
{
|
||||
foreach (var value in mod.Values)
|
||||
{
|
||||
ModContext.AddToLocale(value.Key, value.Key, mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
82
InfectedRose.Interface/Templates/LootMatrixMod.cs
Normal file
82
InfectedRose.Interface/Templates/LootMatrixMod.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using InfectedRose.Database;
|
||||
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
[ModType("loot-matrix")]
|
||||
public class LootMatrixMod : ModType
|
||||
{
|
||||
class LootMatrix
|
||||
{
|
||||
[JsonPropertyName("rarity-table")]
|
||||
public int? RarityTableIndex { get; set; }
|
||||
|
||||
[JsonPropertyName("percent")]
|
||||
public float? Percent { get; set; }
|
||||
|
||||
[JsonPropertyName("min-quantity")]
|
||||
public int? MinQuantity { get; set; }
|
||||
|
||||
[JsonPropertyName("max-quantity")]
|
||||
public int? MaxQuantity { get; set; }
|
||||
|
||||
[JsonPropertyName("id")]
|
||||
public int? Id { get; set; }
|
||||
|
||||
[JsonPropertyName("flag-id")]
|
||||
public string? FlagId { get; set; }
|
||||
}
|
||||
|
||||
public override void Apply(Mod mod)
|
||||
{
|
||||
var lootMatrix = ModContext.Database["LootMatrix"]!;
|
||||
var lootMatrixIndex = ModContext.Database["LootMatrixIndex"]!;
|
||||
|
||||
int modId;
|
||||
|
||||
if (mod.ExplicitId.HasValue)
|
||||
{
|
||||
modId = mod.ExplicitId.Value;
|
||||
}
|
||||
else if (mod.Id.StartsWith("lego-universe:"))
|
||||
{
|
||||
modId = int.Parse(mod.Id[14..]);
|
||||
}
|
||||
else
|
||||
{
|
||||
var indexRow = lootMatrixIndex.Create();
|
||||
|
||||
modId = indexRow.Key;
|
||||
}
|
||||
|
||||
ModContext.RegisterId(mod.Id, modId);
|
||||
|
||||
foreach (var (key, _) in mod.Values)
|
||||
{
|
||||
ModContext.AwaitId(key, lootTableIndex =>
|
||||
{
|
||||
var row = lootMatrix.Create(modId);
|
||||
|
||||
row["LootTableIndex"].Value = modId;
|
||||
|
||||
var value = mod.GetValue<LootMatrix>(key);
|
||||
|
||||
row["LootTableIndex"].Value = lootTableIndex;
|
||||
row["RarityTableIndex"].Value = value.RarityTableIndex ?? 4;
|
||||
row["percent"].Value = value.Percent ?? 1;
|
||||
row["minToDrop"].Value = value.MinQuantity ?? 1;
|
||||
row["maxToDrop"].Value = value.MaxQuantity ?? 1;
|
||||
row["id"].Value = value.Id ?? lootMatrix.Max(l => (int)l[6].Value);
|
||||
if (value.FlagId != null)
|
||||
{
|
||||
ModContext.AwaitId(value.FlagId, flagId =>
|
||||
{
|
||||
row["flagID"].Value = flagId;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
72
InfectedRose.Interface/Templates/LootTableMod.cs
Normal file
72
InfectedRose.Interface/Templates/LootTableMod.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using InfectedRose.Database;
|
||||
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
[ModType("loot-table")]
|
||||
public class LootTableMod : ModType
|
||||
{
|
||||
class LootTable
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public int? Id { get; set; }
|
||||
|
||||
[JsonPropertyName("mission-drop")]
|
||||
public bool? MissionDrop { get; set; }
|
||||
|
||||
[JsonPropertyName("sort-priority")]
|
||||
public int? SortPriority { get; set; }
|
||||
}
|
||||
|
||||
public override void Apply(Mod mod)
|
||||
{
|
||||
var lootTable = ModContext.Database["LootTable"]!;
|
||||
var lootTableIndex = ModContext.Database["LootTableIndex"]!;
|
||||
|
||||
int modId;
|
||||
|
||||
if (mod.ExplicitId.HasValue)
|
||||
{
|
||||
modId = mod.ExplicitId.Value;
|
||||
}
|
||||
else if (mod.Id.StartsWith("lego-universe:"))
|
||||
{
|
||||
modId = int.Parse(mod.Id[14..]);
|
||||
}
|
||||
else
|
||||
{
|
||||
var indexRow = lootTableIndex.Create();
|
||||
|
||||
modId = indexRow.Key;
|
||||
}
|
||||
|
||||
ModContext.RegisterId(mod.Id, modId);
|
||||
|
||||
foreach (var (key, _) in mod.Values)
|
||||
{
|
||||
ModContext.AwaitId(key, itemId =>
|
||||
{
|
||||
var row = lootTable.Create(itemId);
|
||||
|
||||
row["LootTableIndex"].Value = modId;
|
||||
|
||||
var value = mod.GetValue<LootTable?>(key);
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
row["id"].Value = lootTable.Max(l => (int)l[2].Value);
|
||||
row["MissionDrop"].Value = false;
|
||||
row["sortPriority"].Value = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
row["id"].Value = value.Id ?? lootTable.Max(l => (int)l[2].Value);
|
||||
row["MissionDrop"].Value = value.MissionDrop ?? false;
|
||||
row["sortPriority"].Value = value.SortPriority ?? 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,353 +2,339 @@ using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace InfectedRose.Interface.Templates
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
[ModType("mission")]
|
||||
public class MissionMod : ModType
|
||||
{
|
||||
[ModType("mission")]
|
||||
public class MissionMod : ModType
|
||||
// Proud of this one :D
|
||||
public static void ParsePrerequisites(StringBuilder builder, StringBuilder missionId, string str, int i, Action<string> done)
|
||||
{
|
||||
// Proud of this one :D
|
||||
public static void ParsePrerequisites(StringBuilder builder, StringBuilder missionId, string str, int i, Action<string> done)
|
||||
if (i >= str.Length)
|
||||
{
|
||||
if (i >= str.Length)
|
||||
{
|
||||
done(builder.ToString());
|
||||
done(builder.ToString());
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var c = str[i];
|
||||
var c = str[i];
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '(':
|
||||
break;
|
||||
case ')':
|
||||
break;
|
||||
case '&' or ',' or ';':
|
||||
break;
|
||||
case '|':
|
||||
break;
|
||||
case ' ':
|
||||
ParsePrerequisites(builder, missionId, str, i + 1, done);
|
||||
return;
|
||||
default:
|
||||
missionId.Append(c);
|
||||
|
||||
ParsePrerequisites(builder, missionId, str, i + 1, done);
|
||||
return;
|
||||
}
|
||||
|
||||
if (missionId.Length == 0)
|
||||
{
|
||||
builder.Append(c);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '(':
|
||||
break;
|
||||
case ')':
|
||||
break;
|
||||
case '&' or ',' or ';':
|
||||
break;
|
||||
case '|':
|
||||
break;
|
||||
case ' ':
|
||||
ParsePrerequisites(builder, missionId, str, i + 1, done);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var missionIdString = missionId.ToString();
|
||||
|
||||
if (string.IsNullOrEmpty(missionIdString))
|
||||
{
|
||||
builder.Append(c);
|
||||
default:
|
||||
missionId.Append(c);
|
||||
|
||||
ParsePrerequisites(builder, missionId, str, i + 1, done);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
missionIdString = missionIdString.Trim();
|
||||
if (missionId.Length == 0)
|
||||
{
|
||||
builder.Append(c);
|
||||
|
||||
ParsePrerequisites(builder, missionId, str, i + 1, done);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var missionIdString = missionId.ToString();
|
||||
|
||||
if (string.IsNullOrEmpty(missionIdString))
|
||||
{
|
||||
builder.Append(c);
|
||||
|
||||
ParsePrerequisites(builder, missionId, str, i + 1, done);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
missionIdString = missionIdString.Trim();
|
||||
|
||||
// If the string ends with ":2" state is true
|
||||
var state = missionIdString.EndsWith(":2");
|
||||
// If the string ends with ":2" state is true
|
||||
var state = missionIdString.EndsWith(":2");
|
||||
|
||||
// Remove the ":2" from the string
|
||||
if (state)
|
||||
{
|
||||
missionIdString = missionIdString.Substring(0, missionIdString.Length - 2);
|
||||
}
|
||||
|
||||
// Get the mission ID
|
||||
ModContext.AwaitId(missionIdString, id =>
|
||||
{
|
||||
builder.Append(id);
|
||||
|
||||
// Remove the ":2" from the string
|
||||
if (state)
|
||||
{
|
||||
missionIdString = missionIdString.Substring(0, missionIdString.Length - 2);
|
||||
builder.Append(":2");
|
||||
}
|
||||
|
||||
missionId.Clear();
|
||||
|
||||
// Get the mission ID
|
||||
ModContext.AwaitId(missionIdString, id =>
|
||||
builder.Append(c);
|
||||
|
||||
ParsePrerequisites(builder, missionId, str, i + 1, done);
|
||||
});
|
||||
}
|
||||
|
||||
public override void Apply(Mod mod)
|
||||
{
|
||||
mod.Default("locStatus", 2);
|
||||
mod.DefaultNull("UIPrereqID");
|
||||
mod.Default("localize", true);
|
||||
mod.Default("isMission", false);
|
||||
mod.Default("isChoiceReward", false);
|
||||
mod.DefaultNull("missionIconID");
|
||||
|
||||
if (mod.HasValue("repeatable") && mod.GetValue<bool>("repeatable"))
|
||||
{
|
||||
mod.Default("time_limit", 1300);
|
||||
}
|
||||
else
|
||||
{
|
||||
mod.DefaultNull("time_limit");
|
||||
}
|
||||
|
||||
mod.Default("reward_item1", -1);
|
||||
mod.Default("reward_item2", -1);
|
||||
mod.Default("reward_item3", -1);
|
||||
mod.Default("reward_item4", -1);
|
||||
mod.Default("reward_item1_repeatable", -1);
|
||||
mod.Default("reward_item2_repeatable", -1);
|
||||
mod.Default("reward_item3_repeatable", -1);
|
||||
mod.Default("reward_item4_repeatable", -1);
|
||||
mod.Default("reward_emote", -1);
|
||||
mod.Default("reward_emote2", -1);
|
||||
mod.Default("reward_emote3", -1);
|
||||
mod.Default("reward_emote4", -1);
|
||||
mod.Default("reward_maxwallet", 0);
|
||||
mod.Default("reward_reputation", 0);
|
||||
mod.Default("reward_currency_repeatable", 0);
|
||||
|
||||
var missionsTable = ModContext.Database["Missions"];
|
||||
var missionTasksTable = ModContext.Database["MissionTasks"];
|
||||
|
||||
var mission = missionsTable.FromLookup(mod);
|
||||
|
||||
foreach (var (locale, text) in mod.Locale!)
|
||||
{
|
||||
ModContext.AddToLocale($"Missions_{mission.Key}_name", text, locale);
|
||||
}
|
||||
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_accept_chat_bubble", "accept_chat_bubble", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_accept_chat_bubble", "chat_accept", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_chat_state_1", "chat_state_1", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_chat_state_2", "chat_state_2", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_chat_state_3", "chat_state_3", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_chat_state_4", "chat_state_4", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_chat_state_1", "chat_available", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_chat_state_2", "chat_active", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_chat_state_3", "chat_ready_to_complete", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_chat_state_4", "chat_complete", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_completion_succeed_tip", "completion_succeed_tip", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_in_progress", "in_progress", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_offer", "offer", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_ready_to_complete", "ready_to_complete", mod);
|
||||
|
||||
var missionTextTable = ModContext.Database["MissionText"];
|
||||
var missionText = missionTextTable.FromLookup(mod)!;
|
||||
|
||||
missionText["localize"].Value = true;
|
||||
missionText["locStatus"].Value = 2;
|
||||
missionText["IconID"].Value = null;
|
||||
if (mod.HasValue("icon-turn-in"))
|
||||
{
|
||||
var turnInIconAsset = ModContext.ParseValue(mod.GetValue<string>("icon-turn-in"), true);
|
||||
var turnInIconId = ModContext.AddIcon(turnInIconAsset);
|
||||
missionText["turnInIconID"].Value = turnInIconId;
|
||||
}
|
||||
else
|
||||
{
|
||||
missionText["turnInIconID"].Value = null;
|
||||
}
|
||||
|
||||
ModContext.ApplyValues(mod, mission, missionsTable);
|
||||
|
||||
if (mod.HasValue("reward_item1"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_item1"), id =>
|
||||
{
|
||||
builder.Append(id);
|
||||
|
||||
if (state)
|
||||
{
|
||||
builder.Append(":2");
|
||||
}
|
||||
|
||||
missionId.Clear();
|
||||
|
||||
builder.Append(c);
|
||||
|
||||
ParsePrerequisites(builder, missionId, str, i + 1, done);
|
||||
mission["reward_item1"].Value = id == 0 ? -1 : id;
|
||||
});
|
||||
}
|
||||
|
||||
public override void Apply(Mod mod)
|
||||
|
||||
if (mod.HasValue("reward_item2"))
|
||||
{
|
||||
mod.Default("locStatus", 2);
|
||||
mod.DefaultNull("UIPrereqID");
|
||||
mod.Default("localize", true);
|
||||
mod.Default("isMission", false);
|
||||
mod.Default("isChoiceReward", false);
|
||||
mod.DefaultNull("missionIconID");
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_item2"), id =>
|
||||
{
|
||||
mission["reward_item2"].Value = id == 0 ? -1 : id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_item3"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_item3"), id =>
|
||||
{
|
||||
mission["reward_item3"].Value = id == 0 ? -1 : id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_item4"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_item4"), id =>
|
||||
{
|
||||
mission["reward_item4"].Value = id == 0 ? -1 : id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_item1_repeatable"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_item1_repeatable"), id =>
|
||||
{
|
||||
mission["reward_item1_repeatable"].Value = id == 0 ? -1 : id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_item2_repeatable"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_item2_repeatable"), id =>
|
||||
{
|
||||
mission["reward_item2_repeatable"].Value = id == 0 ? -1 : id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_item3_repeatable"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_item3_repeatable"), id =>
|
||||
{
|
||||
mission["reward_item3_repeatable"].Value = id == 0 ? -1 : id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_item4_repeatable"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_item4_repeatable"), id =>
|
||||
{
|
||||
mission["reward_item4_repeatable"].Value = id == 0 ? -1 : id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_emote"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_emote"), id =>
|
||||
{
|
||||
mission["reward_emote"].Value = id == 0 ? -1 : id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_emote2"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_emote2"), id =>
|
||||
{
|
||||
mission["reward_emote2"].Value = id == 0 ? -1 : id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_emote3"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_emote3"), id =>
|
||||
{
|
||||
mission["reward_emote3"].Value = id == 0 ? -1 : id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_emote4"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_emote4"), id =>
|
||||
{
|
||||
mission["reward_emote4"].Value = id == 0 ? -1 : id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("repeatable") && mod.GetValue<bool>("repeatable"))
|
||||
{
|
||||
mod.Default("time_limit", 1300);
|
||||
}
|
||||
else
|
||||
{
|
||||
mod.DefaultNull("time_limit");
|
||||
}
|
||||
|
||||
mod.Default("reward_item1", -1);
|
||||
mod.Default("reward_item2", -1);
|
||||
mod.Default("reward_item3", -1);
|
||||
mod.Default("reward_item4", -1);
|
||||
mod.Default("reward_item1_repeatable", -1);
|
||||
mod.Default("reward_item2_repeatable", -1);
|
||||
mod.Default("reward_item3_repeatable", -1);
|
||||
mod.Default("reward_item4_repeatable", -1);
|
||||
mod.Default("reward_emote", -1);
|
||||
mod.Default("reward_emote2", -1);
|
||||
mod.Default("reward_emote3", -1);
|
||||
mod.Default("reward_emote4", -1);
|
||||
mod.Default("reward_maxwallet", 0);
|
||||
mod.Default("reward_reputation", 0);
|
||||
mod.Default("reward_currency_repeatable", 0);
|
||||
if (mod.HasValue("prereqMissionID"))
|
||||
{
|
||||
var prereqMissionId = mod.GetValue<string>("prereqMissionID");
|
||||
|
||||
var missionsTable = ModContext.Database["Missions"];
|
||||
var missionTasksTable = ModContext.Database["MissionTasks"];
|
||||
|
||||
var mission = missionsTable.FromLookup(mod);
|
||||
|
||||
foreach (var (locale, text) in mod.Locale!)
|
||||
{
|
||||
ModContext.AddToLocale($"Missions_{mission.Key}_name", text, locale);
|
||||
}
|
||||
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_accept_chat_bubble", "accept_chat_bubble", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_accept_chat_bubble", "chat_accept", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_chat_state_1", "chat_state_1", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_chat_state_2", "chat_state_2", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_chat_state_3", "chat_state_3", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_chat_state_4", "chat_state_4", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_chat_state_1", "chat_available", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_chat_state_2", "chat_active", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_chat_state_3", "chat_ready_to_complete", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_chat_state_4", "chat_complete", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_completion_succeed_tip", "completion_succeed_tip", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_in_progress", "in_progress", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_offer", "offer", mod);
|
||||
ModContext.AddToLocale($"MissionText_{mission.Key}_ready_to_complete", "ready_to_complete", mod);
|
||||
|
||||
var missionTextTable = ModContext.Database["MissionText"];
|
||||
var missionText = missionTextTable.FromLookup(mod)!;
|
||||
|
||||
missionText["localize"].Value = true;
|
||||
missionText["locStatus"].Value = 2;
|
||||
missionText["IconID"].Value = null;
|
||||
if (mod.HasValue("icon-turn-in"))
|
||||
{
|
||||
var turnInIconAsset = ModContext.ParseValue(mod.GetValue<string>("icon-turn-in"), true);
|
||||
var turnInIconId = ModContext.AddIcon(turnInIconAsset);
|
||||
missionText["turnInIconID"].Value = turnInIconId;
|
||||
}
|
||||
else
|
||||
{
|
||||
missionText["turnInIconID"].Value = null;
|
||||
}
|
||||
|
||||
ModContext.ApplyValues(mod, mission, missionsTable);
|
||||
|
||||
if (mod.HasValue("reward_item1"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_item1"), id =>
|
||||
{
|
||||
mission["reward_item1"].Value = id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_item2"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_item2"), id =>
|
||||
{
|
||||
mission["reward_item2"].Value = id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_item3"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_item3"), id =>
|
||||
{
|
||||
mission["reward_item3"].Value = id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_item4"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_item4"), id =>
|
||||
{
|
||||
mission["reward_item4"].Value = id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_item1_repeatable"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_item1_repeatable"), id =>
|
||||
{
|
||||
mission["reward_item1_repeatable"].Value = id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_item2_repeatable"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_item2_repeatable"), id =>
|
||||
{
|
||||
mission["reward_item2_repeatable"].Value = id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_item3_repeatable"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_item3_repeatable"), id =>
|
||||
{
|
||||
mission["reward_item3_repeatable"].Value = id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_item4_repeatable"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_item4_repeatable"), id =>
|
||||
{
|
||||
mission["reward_item4_repeatable"].Value = id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_emote"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_emote"), id =>
|
||||
{
|
||||
mission["reward_emote"].Value = id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_emote2"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_emote2"), id =>
|
||||
{
|
||||
mission["reward_emote2"].Value = id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_emote3"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_emote3"), id =>
|
||||
{
|
||||
mission["reward_emote3"].Value = id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("reward_emote4"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("reward_emote4"), id =>
|
||||
{
|
||||
mission["reward_emote4"].Value = id;
|
||||
});
|
||||
}
|
||||
|
||||
if (mod.HasValue("prereqMissionID"))
|
||||
{
|
||||
var prereqMissionId = mod.GetValue<string>("prereqMissionID");
|
||||
|
||||
var builder = new StringBuilder();
|
||||
var builder = new StringBuilder();
|
||||
|
||||
var missionId = new StringBuilder();
|
||||
var missionId = new StringBuilder();
|
||||
|
||||
ParsePrerequisites(builder, missionId, prereqMissionId, 0, done =>
|
||||
{
|
||||
mission["prereqMissionID"].Value = done;
|
||||
});
|
||||
}
|
||||
ParsePrerequisites(builder, missionId, prereqMissionId, 0, done =>
|
||||
{
|
||||
mission["prereqMissionID"].Value = done;
|
||||
});
|
||||
}
|
||||
|
||||
ModContext.RegisterId(mod.Id, mission.Key);
|
||||
ModContext.RegisterId(mod.Id, mission.Key);
|
||||
|
||||
if (mod.HasValue("icon") && !ModContext.ShouldBeNull(mod.GetValue<string>("icon")))
|
||||
{
|
||||
var missionIconId = ModContext.AddIcon(mod.GetValue<string>("icon"));
|
||||
mission["missionIconID"].Value = missionIconId;
|
||||
}
|
||||
else if (mod.HasValue("missionIconID") && !ModContext.ShouldBeNull(mod.GetValue<string>("missionIconID")))
|
||||
{
|
||||
var missionIconId = ModContext.AddIcon(mod.GetValue<string>("missionIconID"));
|
||||
mission["missionIconID"].Value = missionIconId;
|
||||
}
|
||||
else
|
||||
{
|
||||
mission["missionIconID"].Value = null;
|
||||
}
|
||||
if (mod.HasValue("icon") && !ModContext.ShouldBeNull(mod.GetValue<string>("icon")))
|
||||
{
|
||||
var missionIconId = ModContext.AddIcon(mod.GetValue<string>("icon"));
|
||||
mission["missionIconID"].Value = missionIconId;
|
||||
}
|
||||
else if (mod.HasValue("missionIconID") && !ModContext.ShouldBeNull(mod.GetValue<string>("missionIconID")))
|
||||
{
|
||||
var missionIconId = ModContext.AddIcon(mod.GetValue<string>("missionIconID"));
|
||||
mission["missionIconID"].Value = missionIconId;
|
||||
}
|
||||
else
|
||||
{
|
||||
mission["missionIconID"].Value = null;
|
||||
}
|
||||
|
||||
var uid = (int) missionTasksTable.Max(t => t["uid"].Value)!;
|
||||
var uid = (int) missionTasksTable.Max(t => t["uid"].Value)!;
|
||||
|
||||
foreach (var task in missionTasksTable.SeekMultiple(mission.Key))
|
||||
{
|
||||
missionTasksTable.Remove(task);
|
||||
}
|
||||
foreach (var task in missionTasksTable.SeekMultiple(mission.Key))
|
||||
{
|
||||
missionTasksTable.Remove(task);
|
||||
}
|
||||
|
||||
foreach (var task in mod.Tasks!)
|
||||
foreach (var task in mod.Tasks!)
|
||||
{
|
||||
var missionTask = missionTasksTable.Create(mission.Key)!;
|
||||
|
||||
missionTask["locStatus"].Value = 2;
|
||||
missionTask["localize"].Value = true;
|
||||
missionTask["taskType"].Value = (int) ModContext.ParseEnum<MissionTaskType>(task.Type);
|
||||
missionTask["largeTaskIcon"].Value = null;
|
||||
missionTask["targetValue"].Value = task.Count;
|
||||
missionTask["uid"].Value = ++uid;
|
||||
|
||||
var iconAsset = ModContext.ParseValue(task.Icon, true);
|
||||
var iconId = ModContext.AddIcon(iconAsset);
|
||||
missionTask["largeTaskIconID"].Value = iconId;
|
||||
|
||||
var smallIcon = string.IsNullOrWhiteSpace(task.SmallIcon) ? task.Icon : task.SmallIcon;
|
||||
|
||||
var smallIconAsset = ModContext.ParseValue(smallIcon, true);
|
||||
var smallIconId = ModContext.AddIcon(smallIconAsset);
|
||||
missionTask["IconID"].Value = smallIconId;
|
||||
|
||||
foreach (var (locale, text) in task.Locale!)
|
||||
{
|
||||
var missionTask = missionTasksTable.Create(mission.Key)!;
|
||||
ModContext.AddToLocale($"MissionTasks_{missionTask["uid"].Value}_description", text, locale);
|
||||
}
|
||||
|
||||
ModContext.AwaitId(task.Target, value => missionTask["target"].Value = value);
|
||||
|
||||
missionTask["locStatus"].Value = 2;
|
||||
missionTask["localize"].Value = true;
|
||||
missionTask["taskType"].Value = (int) ModContext.ParseEnum<MissionTaskType>(task.Type);
|
||||
missionTask["largeTaskIcon"].Value = null;
|
||||
missionTask["targetValue"].Value = task.Count;
|
||||
missionTask["uid"].Value = ++uid;
|
||||
|
||||
var iconAsset = ModContext.ParseValue(task.Icon, true);
|
||||
var iconId = ModContext.AddIcon(iconAsset);
|
||||
missionTask["largeTaskIconID"].Value = iconId;
|
||||
|
||||
var smallIcon = string.IsNullOrWhiteSpace(task.SmallIcon) ? task.Icon : task.SmallIcon;
|
||||
|
||||
var smallIconAsset = ModContext.ParseValue(smallIcon, true);
|
||||
var smallIconId = ModContext.AddIcon(smallIconAsset);
|
||||
missionTask["IconID"].Value = smallIconId;
|
||||
|
||||
foreach (var (locale, text) in task.Locale!)
|
||||
foreach (var groupTarget in task.Group)
|
||||
{
|
||||
var value = groupTarget!.AsValue();
|
||||
|
||||
if (ModContext.IsId(value))
|
||||
{
|
||||
ModContext.AddToLocale($"MissionTasks_{missionTask["uid"].Value}_description", text, locale);
|
||||
}
|
||||
|
||||
ModContext.AwaitId(task.Target, value => missionTask["target"].Value = value);
|
||||
|
||||
foreach (var groupTarget in task.Group)
|
||||
{
|
||||
var value = groupTarget!.AsValue();
|
||||
|
||||
if (ModContext.IsId(value))
|
||||
{
|
||||
ModContext.AwaitId(groupTarget!.AsValue(), value =>
|
||||
{
|
||||
var current = missionTask["targetGroup"].Value?.ToString() ?? "";
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(current))
|
||||
{
|
||||
current += ",";
|
||||
}
|
||||
|
||||
current += value.ToString();
|
||||
|
||||
missionTask["targetGroup"].Value = current;
|
||||
});
|
||||
}
|
||||
else
|
||||
ModContext.AwaitId(groupTarget!.AsValue(), value =>
|
||||
{
|
||||
var current = missionTask["targetGroup"].Value?.ToString() ?? "";
|
||||
|
||||
@@ -357,35 +343,35 @@ namespace InfectedRose.Interface.Templates
|
||||
current += ",";
|
||||
}
|
||||
|
||||
current += groupTarget!.AsValue().ToString();
|
||||
current += value.ToString();
|
||||
|
||||
missionTask["targetGroup"].Value = current;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var parameter in task.Parameters)
|
||||
else
|
||||
{
|
||||
// taskParam1
|
||||
|
||||
var value = parameter!.AsValue();
|
||||
|
||||
if (ModContext.IsId(value))
|
||||
var current = missionTask["targetGroup"].Value?.ToString() ?? "";
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(current))
|
||||
{
|
||||
ModContext.AwaitId(parameter!.AsValue(), value =>
|
||||
{
|
||||
var current = missionTask["taskParam1"].Value?.ToString() ?? "";
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(current))
|
||||
{
|
||||
current += ",";
|
||||
}
|
||||
|
||||
current += value.ToString();
|
||||
|
||||
missionTask["taskParam1"].Value = current;
|
||||
});
|
||||
current += ",";
|
||||
}
|
||||
else
|
||||
|
||||
current += groupTarget!.AsValue().ToString();
|
||||
|
||||
missionTask["targetGroup"].Value = current;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var parameter in task.Parameters)
|
||||
{
|
||||
// taskParam1
|
||||
|
||||
var value = parameter!.AsValue();
|
||||
|
||||
if (ModContext.IsId(value))
|
||||
{
|
||||
ModContext.AwaitId(parameter!.AsValue(), value =>
|
||||
{
|
||||
var current = missionTask["taskParam1"].Value?.ToString() ?? "";
|
||||
|
||||
@@ -394,10 +380,23 @@ namespace InfectedRose.Interface.Templates
|
||||
current += ",";
|
||||
}
|
||||
|
||||
current += parameter!.AsValue().ToString();
|
||||
current += value.ToString();
|
||||
|
||||
missionTask["taskParam1"].Value = current;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
var current = missionTask["taskParam1"].Value?.ToString() ?? "";
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(current))
|
||||
{
|
||||
current += ",";
|
||||
}
|
||||
|
||||
current += parameter!.AsValue().ToString();
|
||||
|
||||
missionTask["taskParam1"].Value = current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,38 +2,37 @@ using System.Collections.Generic;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface.Templates
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
public class MissionModTask
|
||||
{
|
||||
public class MissionModTask
|
||||
[JsonPropertyName("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonPropertyName("target")]
|
||||
public JsonValue Target { get; set; }
|
||||
|
||||
[JsonPropertyName("count")]
|
||||
public int Count { get; set; }
|
||||
|
||||
[JsonPropertyName("group")]
|
||||
public JsonArray Group { get; set; }
|
||||
|
||||
[JsonPropertyName("location")]
|
||||
public string Location { get; set; }
|
||||
|
||||
[JsonPropertyName("parameters")]
|
||||
public JsonArray Parameters { get; set; }
|
||||
|
||||
[JsonPropertyName("icon")]
|
||||
public string Icon { get; set; }
|
||||
|
||||
[JsonPropertyName("small-icon")]
|
||||
public string SmallIcon { get; set; }
|
||||
|
||||
[JsonPropertyName("locale")]
|
||||
public Dictionary<string, string>? Locale { get; set; } = new Dictionary<string, string>
|
||||
{
|
||||
[JsonPropertyName("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonPropertyName("target")]
|
||||
public JsonValue Target { get; set; }
|
||||
|
||||
[JsonPropertyName("count")]
|
||||
public int Count { get; set; }
|
||||
|
||||
[JsonPropertyName("group")]
|
||||
public JsonArray Group { get; set; }
|
||||
|
||||
[JsonPropertyName("location")]
|
||||
public string Location { get; set; }
|
||||
|
||||
[JsonPropertyName("parameters")]
|
||||
public JsonArray Parameters { get; set; }
|
||||
|
||||
[JsonPropertyName("icon")]
|
||||
public string Icon { get; set; }
|
||||
|
||||
[JsonPropertyName("small-icon")]
|
||||
public string SmallIcon { get; set; }
|
||||
|
||||
[JsonPropertyName("locale")]
|
||||
public Dictionary<string, string>? Locale { get; set; } = new Dictionary<string, string>
|
||||
{
|
||||
{"en_US", ""}
|
||||
};
|
||||
}
|
||||
{"en_US", ""}
|
||||
};
|
||||
}
|
||||
@@ -1,17 +1,16 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface.Templates
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
public class MissionOffer
|
||||
{
|
||||
public class MissionOffer
|
||||
{
|
||||
[JsonPropertyName("mission")]
|
||||
public JsonValue Mission { get; set; }
|
||||
[JsonPropertyName("mission")]
|
||||
public JsonValue Mission { get; set; }
|
||||
|
||||
[JsonPropertyName("accept")]
|
||||
public bool Accept { get; set; }
|
||||
[JsonPropertyName("accept")]
|
||||
public bool Accept { get; set; }
|
||||
|
||||
[JsonPropertyName("offer")]
|
||||
public bool Offer { get; set; }
|
||||
}
|
||||
[JsonPropertyName("offer")]
|
||||
public bool Offer { get; set; }
|
||||
}
|
||||
@@ -1,24 +1,23 @@
|
||||
namespace InfectedRose.Interface.Templates
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
public enum MissionTaskType
|
||||
{
|
||||
public enum MissionTaskType
|
||||
{
|
||||
Smash = 0,
|
||||
Script = 1,
|
||||
Activity = 2,
|
||||
Environment = 3,
|
||||
MissionInteraction = 4,
|
||||
Emote = 5,
|
||||
Food = 9,
|
||||
Skill = 10,
|
||||
ItemCollection = 11,
|
||||
Location = 12,
|
||||
Minigame = 14,
|
||||
NonMissionInteraction = 15,
|
||||
MissionComplete = 16,
|
||||
Powerup = 21,
|
||||
PetTaming = 22,
|
||||
Racing = 23,
|
||||
PlayerFlag = 24,
|
||||
VisitProperty = 30
|
||||
}
|
||||
Smash = 0,
|
||||
Script = 1,
|
||||
Activity = 2,
|
||||
Environment = 3,
|
||||
MissionInteraction = 4,
|
||||
Emote = 5,
|
||||
Food = 9,
|
||||
Skill = 10,
|
||||
ItemCollection = 11,
|
||||
Location = 12,
|
||||
Minigame = 14,
|
||||
NonMissionInteraction = 15,
|
||||
MissionComplete = 16,
|
||||
Powerup = 21,
|
||||
PetTaming = 22,
|
||||
Racing = 23,
|
||||
PlayerFlag = 24,
|
||||
VisitProperty = 30
|
||||
}
|
||||
@@ -1,56 +1,55 @@
|
||||
namespace InfectedRose.Interface.Templates
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
[ModType("npc")]
|
||||
public class NpcMod : ModType
|
||||
{
|
||||
[ModType("npc")]
|
||||
public class NpcMod : ModType
|
||||
public override void Apply(Mod mod)
|
||||
{
|
||||
public override void Apply(Mod mod)
|
||||
if (mod.Action != "add")
|
||||
{
|
||||
if (mod.Action != "add")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mod.Default("render_asset", @"animations\\minifig\\mf_ambient.kfm");
|
||||
mod.Default("animationGroupIDs", "93");
|
||||
mod.Default("shader_id", 14);
|
||||
mod.Default("static", 1);
|
||||
mod.Default("jump", 0);
|
||||
mod.Default("doublejump", 0);
|
||||
mod.Default("speed", 5);
|
||||
mod.Default("rotSpeed", 360);
|
||||
mod.Default("playerHeight", 4.4f);
|
||||
mod.Default("playerRadius", 1);
|
||||
mod.Default("pcShapeType", 2);
|
||||
mod.Default("collisionGroup", 3);
|
||||
mod.Default("airSpeed", 5);
|
||||
mod.Default("jumpAirSpeed", 25);
|
||||
mod.DefaultNull("interactionDistance");
|
||||
|
||||
mod.DefaultNull("chatBubbleOffset");
|
||||
mod.Default("fade", true);
|
||||
mod.Default("fadeInTime", 1);
|
||||
mod.DefaultNull("billboardHeight");
|
||||
mod.Default("AudioMetaEventSet", "Emotes_Non_Player");
|
||||
mod.Default("usedropshadow", false);
|
||||
mod.Default("preloadAnimations", false);
|
||||
mod.Default("ignoreCameraCollision", false);
|
||||
mod.Default("gradualSnap", false);
|
||||
mod.Default("staticBillboard", false);
|
||||
mod.Default("attachIndicatorsToNode", false);
|
||||
|
||||
mod.Default("npcTemplateID", 14);
|
||||
mod.Default("nametag", true);
|
||||
mod.Default("placeable", true);
|
||||
mod.Default("localize", true);
|
||||
mod.Default("locStatus", 2);
|
||||
|
||||
var obj = ObjectMod.CreateObject(mod);
|
||||
|
||||
obj["type"].Value = "UserGeneratedNPCs";
|
||||
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.SimplePhysicsComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.RenderComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.MinifigComponent);
|
||||
return;
|
||||
}
|
||||
|
||||
mod.Default("render_asset", @"animations\\minifig\\mf_ambient.kfm");
|
||||
mod.Default("animationGroupIDs", "93");
|
||||
mod.Default("shader_id", 14);
|
||||
mod.Default("static", 1);
|
||||
mod.Default("jump", 0);
|
||||
mod.Default("doublejump", 0);
|
||||
mod.Default("speed", 5);
|
||||
mod.Default("rotSpeed", 360);
|
||||
mod.Default("playerHeight", 4.4f);
|
||||
mod.Default("playerRadius", 1);
|
||||
mod.Default("pcShapeType", 2);
|
||||
mod.Default("collisionGroup", 3);
|
||||
mod.Default("airSpeed", 5);
|
||||
mod.Default("jumpAirSpeed", 25);
|
||||
mod.DefaultNull("interactionDistance");
|
||||
|
||||
mod.DefaultNull("chatBubbleOffset");
|
||||
mod.Default("fade", true);
|
||||
mod.Default("fadeInTime", 1);
|
||||
mod.DefaultNull("billboardHeight");
|
||||
mod.Default("AudioMetaEventSet", "Emotes_Non_Player");
|
||||
mod.Default("usedropshadow", false);
|
||||
mod.Default("preloadAnimations", false);
|
||||
mod.Default("ignoreCameraCollision", false);
|
||||
mod.Default("gradualSnap", false);
|
||||
mod.Default("staticBillboard", false);
|
||||
mod.Default("attachIndicatorsToNode", false);
|
||||
|
||||
mod.Default("npcTemplateID", 14);
|
||||
mod.Default("nametag", true);
|
||||
mod.Default("placeable", true);
|
||||
mod.Default("localize", true);
|
||||
mod.Default("locStatus", 2);
|
||||
|
||||
var obj = ObjectMod.CreateObject(mod);
|
||||
|
||||
obj["type"].Value = "UserGeneratedNPCs";
|
||||
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.SimplePhysicsComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.RenderComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.MinifigComponent);
|
||||
}
|
||||
}
|
||||
@@ -1,312 +1,353 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using InfectedRose.Database;
|
||||
|
||||
namespace InfectedRose.Interface.Templates
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
[ModType("object")]
|
||||
public class ObjectMod : ModType
|
||||
{
|
||||
[ModType("object")]
|
||||
public class ObjectMod : ModType
|
||||
public static Row CreateObject(Mod mod, bool checkIcon = true)
|
||||
{
|
||||
public static Row CreateObject(Mod mod)
|
||||
var table = ModContext.Database["Objects"];
|
||||
|
||||
var row = table.FromLookup(mod);
|
||||
|
||||
row["name"].Value = mod.Id;
|
||||
row["description"].Value = mod.Id;
|
||||
|
||||
ModContext.ApplyValues(mod, row, table);
|
||||
|
||||
ModContext.RegisterId(mod.Id, row.Key);
|
||||
|
||||
if (!mod.HasValue("interactionDistance") || mod.GetValue<float>("interactionDistance") == 0.0f)
|
||||
{
|
||||
var table = ModContext.Database["Objects"];
|
||||
|
||||
var row = table.FromLookup(mod);
|
||||
|
||||
row["name"].Value = mod.Id;
|
||||
row["description"].Value = mod.Id;
|
||||
|
||||
ModContext.ApplyValues(mod, row, table);
|
||||
|
||||
ModContext.RegisterId(mod.Id, row.Key);
|
||||
|
||||
if (mod.Components != null)
|
||||
{
|
||||
foreach (var component in mod.Components)
|
||||
{
|
||||
AwaitComponent(row, component);
|
||||
}
|
||||
}
|
||||
|
||||
if (mod.Locale != null)
|
||||
{
|
||||
foreach (var (locale, text) in mod.Locale)
|
||||
{
|
||||
ModContext.AddToLocale($"Objects_{row.Key}_name", text, locale);
|
||||
}
|
||||
}
|
||||
|
||||
if (mod.Skills != null && mod.Skills.Length > 0)
|
||||
{
|
||||
AddComponent(mod, row, ComponentId.SkillComponent);
|
||||
|
||||
var objectSkillsTable = ModContext.Database["ObjectSkills"];
|
||||
|
||||
foreach (var skill in mod.Skills)
|
||||
{
|
||||
var objectSkill = objectSkillsTable.Create(row.Key);
|
||||
|
||||
objectSkill["castOnType"].Value = skill.CastOnType;
|
||||
objectSkill["AICombatWeight"].Value = skill.CombatAiWeight;
|
||||
|
||||
if (skill.SkillId.TryGetValue(out int? value))
|
||||
{
|
||||
objectSkill["skillID"].Value = value;
|
||||
}
|
||||
else if (skill.SkillId.TryGetValue(out string? itemId))
|
||||
{
|
||||
ModContext.AwaitId(itemId, lot => objectSkill["skillID"].Value = lot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mod.Items != null && mod.Items.Length > 0)
|
||||
{
|
||||
var id = 0;
|
||||
|
||||
foreach (var item in mod.Items)
|
||||
{
|
||||
var itemComponent = ObjectMod.AddComponent(mod, row, ComponentId.InventoryComponent, id)!;
|
||||
|
||||
itemComponent["count"].Value = 1;
|
||||
itemComponent["equip"].Value = true;
|
||||
|
||||
id = itemComponent.Key;
|
||||
|
||||
if (item.TryGetValue(out int? value))
|
||||
{
|
||||
itemComponent["itemid"].Value = value;
|
||||
}
|
||||
else if (item.TryGetValue(out string? itemId))
|
||||
{
|
||||
ModContext.AwaitId(itemId, lot => itemComponent["itemid"].Value = lot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mod.MissionOffers != null)
|
||||
{
|
||||
var id = 0;
|
||||
|
||||
foreach (var missionOffer in mod.MissionOffers)
|
||||
{
|
||||
var missionNpcComponent = ObjectMod.AddComponent(mod, row, ComponentId.MissionNPCComponent, id)!;
|
||||
|
||||
id = missionNpcComponent.Key;
|
||||
|
||||
missionNpcComponent["offersMission"].Value = missionOffer.Offer;
|
||||
missionNpcComponent["acceptsMission"].Value = missionOffer.Accept;
|
||||
|
||||
ModContext.AwaitId(missionOffer.Mission, value => missionNpcComponent["missionID"].Value = value);
|
||||
}
|
||||
|
||||
var mapIconTable = ModContext.Database["mapIcon"];
|
||||
var mapRow = mapIconTable.Create(row.Key);
|
||||
mapRow["iconID"].Value = 1;
|
||||
mapRow["iconState"].Value = 1;
|
||||
mapRow = mapIconTable.Create(row.Key);
|
||||
mapRow["iconID"].Value = 3;
|
||||
mapRow["iconState"].Value = 2;
|
||||
mapRow = mapIconTable.Create(row.Key);
|
||||
mapRow["iconID"].Value = 4;
|
||||
mapRow["iconState"].Value = 4;
|
||||
}
|
||||
|
||||
return row;
|
||||
row["interactionDistance"].Value = 10.0f;
|
||||
}
|
||||
|
||||
public static Row EditObject(Mod mod)
|
||||
if (checkIcon && mod.HasValue("icon"))
|
||||
{
|
||||
var table = ModContext.Database["Objects"];
|
||||
|
||||
var row = table.FromLookup(mod);
|
||||
|
||||
row["name"].Value = mod.Id;
|
||||
row["description"].Value = mod.Id;
|
||||
var iconId = ModContext.AddIcon(mod.GetValue<string>("icon"), out var path);
|
||||
|
||||
ModContext.ApplyValues(mod, row, table);
|
||||
|
||||
ModContext.RegisterId(mod.Id, row.Key);
|
||||
|
||||
var existingComponents = ModContext.Database["ComponentsRegistry"].SeekMultiple(row.Key).ToArray();
|
||||
|
||||
if (mod.Components != null)
|
||||
{
|
||||
foreach (var component in mod.Components)
|
||||
{
|
||||
AwaitComponentWithExistingRows(existingComponents, component);
|
||||
}
|
||||
}
|
||||
|
||||
if (mod.Locale != null)
|
||||
{
|
||||
foreach (var (locale, text) in mod.Locale)
|
||||
{
|
||||
ModContext.AddToLocale($"Objects_{row.Key}_name", text, locale);
|
||||
}
|
||||
}
|
||||
|
||||
if (mod.Skills != null && mod.Skills.Length > 0)
|
||||
{
|
||||
var objectSkillsTable = ModContext.Database["ObjectSkills"];
|
||||
|
||||
foreach (var objectSkill in objectSkillsTable.SeekMultiple(row.Key))
|
||||
{
|
||||
objectSkillsTable.Remove(objectSkill);
|
||||
}
|
||||
|
||||
AddComponent(mod, row, ComponentId.SkillComponent);
|
||||
|
||||
foreach (var skill in mod.Skills)
|
||||
{
|
||||
var objectSkill = objectSkillsTable.Create(row.Key);
|
||||
|
||||
objectSkill["castOnType"].Value = skill.CastOnType;
|
||||
objectSkill["AICombatWeight"].Value = skill.CombatAiWeight;
|
||||
|
||||
if (skill.SkillId.TryGetValue(out int? value))
|
||||
{
|
||||
objectSkill["skillID"].Value = value;
|
||||
}
|
||||
else if (skill.SkillId.TryGetValue(out string? itemId))
|
||||
{
|
||||
ModContext.AwaitId(itemId, lot => objectSkill["skillID"].Value = lot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mod.Items != null && mod.Items.Length > 0)
|
||||
{
|
||||
var id = 0;
|
||||
|
||||
foreach (var item in mod.Items)
|
||||
{
|
||||
var itemComponent = ObjectMod.AddComponent(mod, row, ComponentId.InventoryComponent, id)!;
|
||||
|
||||
itemComponent["count"].Value = 1;
|
||||
itemComponent["equip"].Value = true;
|
||||
|
||||
id = itemComponent.Key;
|
||||
|
||||
if (item.TryGetValue(out int? value))
|
||||
{
|
||||
itemComponent["itemid"].Value = value;
|
||||
}
|
||||
else if (item.TryGetValue(out string? itemId))
|
||||
{
|
||||
ModContext.AwaitId(itemId, lot => itemComponent["itemid"].Value = lot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mod.MissionOffers != null)
|
||||
{
|
||||
var id = 0;
|
||||
|
||||
foreach (var missionOffer in mod.MissionOffers)
|
||||
{
|
||||
var missionNpcComponent = ObjectMod.AddComponent(mod, row, ComponentId.MissionNPCComponent, id)!;
|
||||
|
||||
id = missionNpcComponent.Key;
|
||||
|
||||
missionNpcComponent["offersMission"].Value = missionOffer.Offer;
|
||||
missionNpcComponent["acceptsMission"].Value = missionOffer.Accept;
|
||||
|
||||
ModContext.AwaitId(missionOffer.Mission, value => missionNpcComponent["missionID"].Value = value);
|
||||
}
|
||||
|
||||
var mapIconTable = ModContext.Database["mapIcon"];
|
||||
var mapRow = mapIconTable.Create(row.Key);
|
||||
mapRow["iconID"].Value = 1;
|
||||
mapRow["iconState"].Value = 1;
|
||||
mapRow = mapIconTable.Create(row.Key);
|
||||
mapRow["iconID"].Value = 3;
|
||||
mapRow["iconState"].Value = 2;
|
||||
mapRow = mapIconTable.Create(row.Key);
|
||||
mapRow["iconID"].Value = 4;
|
||||
mapRow["iconState"].Value = 4;
|
||||
}
|
||||
|
||||
return row;
|
||||
mod.Values["icon_asset"] = path;
|
||||
mod.Values["IconID"] = iconId;
|
||||
}
|
||||
|
||||
public static void AwaitComponent(Row obj, string component)
|
||||
if (mod.Components != null)
|
||||
{
|
||||
foreach (var component in mod.Components)
|
||||
{
|
||||
AwaitComponent(row, component);
|
||||
}
|
||||
}
|
||||
|
||||
if (checkIcon && mod.HasValue("icon"))
|
||||
{
|
||||
mod.Values.Remove("icon_asset");
|
||||
mod.Values.Remove("IconID");
|
||||
}
|
||||
|
||||
if (mod.Locale != null)
|
||||
{
|
||||
foreach (var (locale, text) in mod.Locale)
|
||||
{
|
||||
ModContext.AddToLocale($"Objects_{row.Key}_name", text, locale);
|
||||
}
|
||||
}
|
||||
|
||||
if (mod.HasValue("description-locale"))
|
||||
{
|
||||
var description = mod.GetValue<Dictionary<string, string>>("description-locale");
|
||||
|
||||
foreach (var (locale, text) in description)
|
||||
{
|
||||
ModContext.AddToLocale($"Objects_{row.Key}_description", text, locale);
|
||||
}
|
||||
}
|
||||
|
||||
if (mod.Skills != null && mod.Skills.Length > 0)
|
||||
{
|
||||
AddComponent(mod, row, ComponentId.SkillComponent);
|
||||
|
||||
var objectSkillsTable = ModContext.Database["ObjectSkills"];
|
||||
|
||||
foreach (var skill in mod.Skills)
|
||||
{
|
||||
var objectSkill = objectSkillsTable.Create(row.Key);
|
||||
|
||||
objectSkill["castOnType"].Value = skill.CastOnType;
|
||||
objectSkill["AICombatWeight"].Value = skill.CombatAiWeight;
|
||||
|
||||
if (skill.SkillId.TryGetValue(out int? value))
|
||||
{
|
||||
objectSkill["skillID"].Value = value;
|
||||
}
|
||||
else if (skill.SkillId.TryGetValue(out string? itemId))
|
||||
{
|
||||
ModContext.AwaitId(itemId, lot => objectSkill["skillID"].Value = lot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mod.Items != null && mod.Items.Length > 0)
|
||||
{
|
||||
var id = 0;
|
||||
|
||||
foreach (var item in mod.Items)
|
||||
{
|
||||
var itemComponent = ObjectMod.AddComponent(mod, row, ComponentId.InventoryComponent, id)!;
|
||||
|
||||
itemComponent["count"].Value = 1;
|
||||
itemComponent["equip"].Value = true;
|
||||
|
||||
id = itemComponent.Key;
|
||||
|
||||
if (item.TryGetValue(out int? value))
|
||||
{
|
||||
itemComponent["itemid"].Value = value;
|
||||
}
|
||||
else if (item.TryGetValue(out string? itemId))
|
||||
{
|
||||
ModContext.AwaitId(itemId, lot => itemComponent["itemid"].Value = lot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mod.MissionOffers != null)
|
||||
{
|
||||
var id = 0;
|
||||
|
||||
foreach (var missionOffer in mod.MissionOffers)
|
||||
{
|
||||
var missionNpcComponent = ObjectMod.AddComponent(mod, row, ComponentId.MissionNPCComponent, id)!;
|
||||
|
||||
id = missionNpcComponent.Key;
|
||||
|
||||
missionNpcComponent["offersMission"].Value = missionOffer.Offer;
|
||||
missionNpcComponent["acceptsMission"].Value = missionOffer.Accept;
|
||||
|
||||
ModContext.AwaitId(missionOffer.Mission, value => missionNpcComponent["missionID"].Value = value);
|
||||
}
|
||||
|
||||
var mapIconTable = ModContext.Database["mapIcon"];
|
||||
var mapRow = mapIconTable.Create(row.Key);
|
||||
mapRow["iconID"].Value = 1;
|
||||
mapRow["iconState"].Value = 1;
|
||||
mapRow = mapIconTable.Create(row.Key);
|
||||
mapRow["iconID"].Value = 3;
|
||||
mapRow["iconState"].Value = 2;
|
||||
mapRow = mapIconTable.Create(row.Key);
|
||||
mapRow["iconID"].Value = 4;
|
||||
mapRow["iconState"].Value = 4;
|
||||
}
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
public static Row EditObject(Mod mod)
|
||||
{
|
||||
var table = ModContext.Database["Objects"];
|
||||
|
||||
var row = table.FromLookup(mod);
|
||||
|
||||
row["name"].Value = mod.Id;
|
||||
row["description"].Value = mod.Id;
|
||||
|
||||
ModContext.ApplyValues(mod, row, table);
|
||||
|
||||
ModContext.RegisterId(mod.Id, row.Key);
|
||||
|
||||
var existingComponents = ModContext.Database["ComponentsRegistry"].SeekMultiple(row.Key).ToArray();
|
||||
|
||||
if (mod.Components != null)
|
||||
{
|
||||
foreach (var component in mod.Components)
|
||||
{
|
||||
AwaitComponentWithExistingRows(existingComponents, component);
|
||||
}
|
||||
}
|
||||
|
||||
if (mod.Locale != null)
|
||||
{
|
||||
foreach (var (locale, text) in mod.Locale)
|
||||
{
|
||||
ModContext.AddToLocale($"Objects_{row.Key}_name", text, locale);
|
||||
}
|
||||
}
|
||||
|
||||
if (mod.Skills != null && mod.Skills.Length > 0)
|
||||
{
|
||||
var objectSkillsTable = ModContext.Database["ObjectSkills"];
|
||||
|
||||
foreach (var objectSkill in objectSkillsTable.SeekMultiple(row.Key))
|
||||
{
|
||||
objectSkillsTable.Remove(objectSkill);
|
||||
}
|
||||
|
||||
AddComponent(mod, row, ComponentId.SkillComponent);
|
||||
|
||||
foreach (var skill in mod.Skills)
|
||||
{
|
||||
var objectSkill = objectSkillsTable.Create(row.Key);
|
||||
|
||||
objectSkill["castOnType"].Value = skill.CastOnType;
|
||||
objectSkill["AICombatWeight"].Value = skill.CombatAiWeight;
|
||||
|
||||
if (skill.SkillId.TryGetValue(out int? value))
|
||||
{
|
||||
objectSkill["skillID"].Value = value;
|
||||
}
|
||||
else if (skill.SkillId.TryGetValue(out string? itemId))
|
||||
{
|
||||
ModContext.AwaitId(itemId, lot => objectSkill["skillID"].Value = lot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mod.Items != null && mod.Items.Length > 0)
|
||||
{
|
||||
var id = 0;
|
||||
|
||||
foreach (var item in mod.Items)
|
||||
{
|
||||
var itemComponent = ObjectMod.AddComponent(mod, row, ComponentId.InventoryComponent, id)!;
|
||||
|
||||
itemComponent["count"].Value = 1;
|
||||
itemComponent["equip"].Value = true;
|
||||
|
||||
id = itemComponent.Key;
|
||||
|
||||
if (item.TryGetValue(out int? value))
|
||||
{
|
||||
itemComponent["itemid"].Value = value;
|
||||
}
|
||||
else if (item.TryGetValue(out string? itemId))
|
||||
{
|
||||
ModContext.AwaitId(itemId, lot => itemComponent["itemid"].Value = lot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mod.MissionOffers != null)
|
||||
{
|
||||
var id = 0;
|
||||
|
||||
foreach (var missionOffer in mod.MissionOffers)
|
||||
{
|
||||
var missionNpcComponent = ObjectMod.AddComponent(mod, row, ComponentId.MissionNPCComponent, id)!;
|
||||
|
||||
id = missionNpcComponent.Key;
|
||||
|
||||
missionNpcComponent["offersMission"].Value = missionOffer.Offer;
|
||||
missionNpcComponent["acceptsMission"].Value = missionOffer.Accept;
|
||||
|
||||
ModContext.AwaitId(missionOffer.Mission, value => missionNpcComponent["missionID"].Value = value);
|
||||
}
|
||||
|
||||
var mapIconTable = ModContext.Database["mapIcon"];
|
||||
var mapRow = mapIconTable.Create(row.Key);
|
||||
mapRow["iconID"].Value = 1;
|
||||
mapRow["iconState"].Value = 1;
|
||||
mapRow = mapIconTable.Create(row.Key);
|
||||
mapRow["iconID"].Value = 3;
|
||||
mapRow["iconState"].Value = 2;
|
||||
mapRow = mapIconTable.Create(row.Key);
|
||||
mapRow["iconID"].Value = 4;
|
||||
mapRow["iconState"].Value = 4;
|
||||
}
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
public static void AwaitComponent(Row obj, string component)
|
||||
{
|
||||
var row = ModContext.Database["ComponentsRegistry"].Create(obj.Key);
|
||||
|
||||
ModContext.AwaitId(component, id =>
|
||||
{
|
||||
row["component_id"].Value = id;
|
||||
row["component_type"].Value = ModContext.GetMod(component).GetComponentType();
|
||||
}, true);
|
||||
}
|
||||
|
||||
public static void AwaitComponentWithExistingRows(Row[] rows, string component)
|
||||
{
|
||||
ModContext.AwaitId(component, id =>
|
||||
{
|
||||
var componentType = ModContext.GetMod(component).GetComponentType();
|
||||
|
||||
var row = rows.FirstOrDefault(row => (int) row["component_type"].Value == componentType);
|
||||
|
||||
if (row == null)
|
||||
{
|
||||
row = ModContext.Database["ComponentsRegistry"].Create(rows[0].Key);
|
||||
}
|
||||
|
||||
row["component_id"].Value = id;
|
||||
row["component_type"].Value = ModContext.GetMod(component).GetComponentType();
|
||||
}, true, true);
|
||||
}
|
||||
|
||||
public static Row? AddComponent(Mod mod, Row obj, ComponentId componentId, int id = 0)
|
||||
{
|
||||
var table = ModContext.GetComponentTable(componentId);
|
||||
|
||||
Row component;
|
||||
|
||||
foreach (var r in ModContext.Database["ComponentsRegistry"].SeekMultiple(obj.Key))
|
||||
{
|
||||
if ((int)r["component_type"].Value != (int)componentId) continue;
|
||||
|
||||
if (table != null && table.Seek((int) r["component_id"].Value, out var row))
|
||||
{
|
||||
return row;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (id == 0)
|
||||
{
|
||||
var row = ModContext.Database["ComponentsRegistry"].Create(obj.Key);
|
||||
|
||||
ModContext.AwaitId(component, id =>
|
||||
|
||||
row["component_type"].Value = (int) componentId;
|
||||
|
||||
if (table == null)
|
||||
{
|
||||
row["component_id"].Value = id;
|
||||
row["component_type"].Value = ModContext.GetMod(component).GetComponentType();
|
||||
}, true);
|
||||
}
|
||||
|
||||
public static void AwaitComponentWithExistingRows(Row[] rows, string component)
|
||||
{
|
||||
ModContext.AwaitId(component, id =>
|
||||
{
|
||||
var componentType = ModContext.GetMod(component).GetComponentType();
|
||||
row["component_id"].Value = 0;
|
||||
|
||||
var row = rows.FirstOrDefault(row => (int) row["component_type"].Value == componentType);
|
||||
|
||||
if (row == null)
|
||||
{
|
||||
row = ModContext.Database["ComponentsRegistry"].Create(rows[0].Key);
|
||||
}
|
||||
|
||||
row["component_id"].Value = id;
|
||||
row["component_type"].Value = ModContext.GetMod(component).GetComponentType();
|
||||
}, true, true);
|
||||
}
|
||||
|
||||
public static Row? AddComponent(Mod mod, Row obj, ComponentId componentId, int id = 0)
|
||||
{
|
||||
var table = ModContext.GetComponentTable(componentId);
|
||||
|
||||
Row component;
|
||||
|
||||
if (id == 0)
|
||||
{
|
||||
var row = ModContext.Database["ComponentsRegistry"].Create(obj.Key);
|
||||
|
||||
row["component_type"].Value = (int) componentId;
|
||||
|
||||
if (table == null)
|
||||
{
|
||||
row["component_id"].Value = 0;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
component = table.Create();
|
||||
|
||||
row["component_id"].Value = component.Key;
|
||||
|
||||
ModContext.ApplyValues(mod, component, table);
|
||||
|
||||
ModContext.RegisterId(mod.Id + ":" + componentId, component.Key);
|
||||
|
||||
return component;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (table == null) return null;
|
||||
|
||||
component = table.Create(id);
|
||||
component = table.Create();
|
||||
|
||||
row["component_id"].Value = component.Key;
|
||||
|
||||
ModContext.ApplyValues(mod, component, table);
|
||||
|
||||
ModContext.RegisterId(mod.Id + ":" + componentId, component.Key);
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
if (table == null) return null;
|
||||
|
||||
component = table.Create(id);
|
||||
|
||||
ModContext.ApplyValues(mod, component, table);
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
public override void Apply(Mod mod)
|
||||
public override void Apply(Mod mod)
|
||||
{
|
||||
if (mod.Action == "add")
|
||||
{
|
||||
if (mod.Action == "add")
|
||||
{
|
||||
CreateObject(mod);
|
||||
}
|
||||
else if (mod.Action == "edit")
|
||||
{
|
||||
EditObject(mod);
|
||||
}
|
||||
CreateObject(mod);
|
||||
}
|
||||
else if (mod.Action == "edit")
|
||||
{
|
||||
EditObject(mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,16 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface.Templates
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
public class ObjectSkillEntry
|
||||
{
|
||||
public class ObjectSkillEntry
|
||||
{
|
||||
[JsonPropertyName("skill-id")]
|
||||
public JsonValue SkillId { get; set; }
|
||||
[JsonPropertyName("skill-id")]
|
||||
public JsonValue SkillId { get; set; }
|
||||
|
||||
[JsonPropertyName("cast-on-type")]
|
||||
public int CastOnType { get; set; }
|
||||
[JsonPropertyName("cast-on-type")]
|
||||
public int CastOnType { get; set; }
|
||||
|
||||
[JsonPropertyName("combat-ai-weight")]
|
||||
public int CombatAiWeight { get; set; }
|
||||
}
|
||||
[JsonPropertyName("combat-ai-weight")]
|
||||
public int CombatAiWeight { get; set; }
|
||||
}
|
||||
@@ -1,79 +1,78 @@
|
||||
namespace InfectedRose.Interface.Templates
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
[ModType("quickbuild")]
|
||||
public class QuickBuildMod : ModType
|
||||
{
|
||||
[ModType("quickbuild")]
|
||||
public class QuickBuildMod : ModType
|
||||
public override void Apply(Mod mod)
|
||||
{
|
||||
public override void Apply(Mod mod)
|
||||
if (mod.Action != "add")
|
||||
{
|
||||
if (mod.Action != "add")
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mod.Default("render_asset", @"mesh\\re\\re_won_tesla_1-whole.nif");
|
||||
mod.Default("animationGroupIDs", "93");
|
||||
mod.Default("shader_id", 1);
|
||||
mod.Default("render_asset", @"mesh\\re\\re_won_tesla_1-whole.nif");
|
||||
mod.Default("animationGroupIDs", "93");
|
||||
mod.Default("shader_id", 1);
|
||||
|
||||
mod.Default("static", 1);
|
||||
mod.Default("jump", 0);
|
||||
mod.Default("doublejump", 0);
|
||||
mod.Default("speed", 5);
|
||||
mod.Default("rotSpeed", 360);
|
||||
mod.Default("playerHeight", 4.4f);
|
||||
mod.Default("playerRadius", 1);
|
||||
mod.Default("pcShapeType", 2);
|
||||
mod.Default("collisionGroup", 3);
|
||||
mod.Default("airSpeed", 5);
|
||||
mod.Default("jumpAirSpeed", 25);
|
||||
mod.DefaultNull("interactionDistance");
|
||||
mod.Default("physics_asset", @"re\\re_won_tesla_1-whole.hkx");
|
||||
mod.Default("static", 1);
|
||||
mod.Default("jump", 0);
|
||||
mod.Default("doublejump", 0);
|
||||
mod.Default("speed", 5);
|
||||
mod.Default("rotSpeed", 360);
|
||||
mod.Default("playerHeight", 4.4f);
|
||||
mod.Default("playerRadius", 1);
|
||||
mod.Default("pcShapeType", 2);
|
||||
mod.Default("collisionGroup", 3);
|
||||
mod.Default("airSpeed", 5);
|
||||
mod.Default("jumpAirSpeed", 25);
|
||||
mod.DefaultNull("interactionDistance");
|
||||
mod.Default("physics_asset", @"re\\re_won_tesla_1-whole.hkx");
|
||||
|
||||
mod.DefaultNull("chatBubbleOffset");
|
||||
mod.Default("fade", true);
|
||||
mod.Default("fadeInTime", 1);
|
||||
mod.DefaultNull("billboardHeight");
|
||||
mod.Default("usedropshadow", false);
|
||||
mod.Default("preloadAnimations", false);
|
||||
mod.Default("ignoreCameraCollision", false);
|
||||
mod.Default("gradualSnap", false);
|
||||
mod.Default("staticBillboard", false);
|
||||
mod.Default("attachIndicatorsToNode", false);
|
||||
mod.DefaultNull("chatBubbleOffset");
|
||||
mod.Default("fade", true);
|
||||
mod.Default("fadeInTime", 1);
|
||||
mod.DefaultNull("billboardHeight");
|
||||
mod.Default("usedropshadow", false);
|
||||
mod.Default("preloadAnimations", false);
|
||||
mod.Default("ignoreCameraCollision", false);
|
||||
mod.Default("gradualSnap", false);
|
||||
mod.Default("staticBillboard", false);
|
||||
mod.Default("attachIndicatorsToNode", false);
|
||||
|
||||
mod.Default("npcTemplateID", 14);
|
||||
mod.Default("nametag", false);
|
||||
mod.Default("placeable", true);
|
||||
mod.Default("localize", true);
|
||||
mod.Default("locStatus", 2);
|
||||
mod.Default("npcTemplateID", 14);
|
||||
mod.Default("nametag", false);
|
||||
mod.Default("placeable", true);
|
||||
mod.Default("localize", true);
|
||||
mod.Default("locStatus", 2);
|
||||
|
||||
mod.Default("reset_time", 20);
|
||||
mod.Default("complete_time", 3);
|
||||
mod.Default("take_imagination", 6);
|
||||
mod.Default("interruptible", true);
|
||||
mod.Default("self_activator", false);
|
||||
mod.Default("activityID", 6209);
|
||||
mod.Default("time_before_smash", 10);
|
||||
mod.Default("reset_time", 20);
|
||||
mod.Default("complete_time", 3);
|
||||
mod.Default("take_imagination", 6);
|
||||
mod.Default("interruptible", true);
|
||||
mod.Default("self_activator", false);
|
||||
mod.Default("activityID", 6209);
|
||||
mod.Default("time_before_smash", 10);
|
||||
|
||||
mod.Default("level", 1);
|
||||
mod.Default("life", 1);
|
||||
mod.Default("isnpc", false);
|
||||
mod.Default("isSmashable", false);
|
||||
mod.Default("death_behavior", 2);
|
||||
mod.Default("faction", 16);
|
||||
mod.Default("factionList", "16");
|
||||
mod.Default("level", 1);
|
||||
mod.Default("life", 1);
|
||||
mod.Default("isnpc", false);
|
||||
mod.Default("isSmashable", false);
|
||||
mod.Default("death_behavior", 2);
|
||||
mod.Default("faction", 16);
|
||||
mod.Default("factionList", "16");
|
||||
|
||||
var obj = ObjectMod.CreateObject(mod);
|
||||
var obj = ObjectMod.CreateObject(mod);
|
||||
|
||||
obj["type"].Value = "Rebuildables";
|
||||
obj["type"].Value = "Rebuildables";
|
||||
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.SimplePhysicsComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.RenderComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.DestructibleComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.QuickBuildComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.SimplePhysicsComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.RenderComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.DestructibleComponent);
|
||||
ObjectMod.AddComponent(mod, obj, ComponentId.QuickBuildComponent);
|
||||
|
||||
if (mod.HasValue("lxfml"))
|
||||
{
|
||||
ModContext.ParseValue(mod.GetValue<string>("lxfml"));
|
||||
}
|
||||
if (mod.HasValue("lxfml"))
|
||||
{
|
||||
ModContext.ParseValue(mod.GetValue<string>("lxfml"));
|
||||
}
|
||||
}
|
||||
}
|
||||
63
InfectedRose.Interface/Templates/RecipeMod.cs
Normal file
63
InfectedRose.Interface/Templates/RecipeMod.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using InfectedRose.Database.Generic;
|
||||
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
[ModType("recipe")]
|
||||
public class RecipeMod : ModType
|
||||
{
|
||||
class RecipeList : Dictionary<string, int>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void Apply(Mod mod)
|
||||
{
|
||||
foreach (var (key, _) in mod.Values)
|
||||
{
|
||||
ModContext.AwaitId(key, objectId =>
|
||||
{
|
||||
var itemTable = ModContext.GetComponentTable(ComponentId.ItemComponent)!;
|
||||
|
||||
var componentRegistry = ModContext.Database["ComponentsRegistry"]!;
|
||||
|
||||
var itemComponentEntry = componentRegistry.SeekMultiple(objectId).FirstOrDefault(
|
||||
c => c.Value<int>("component_type") == (int) ComponentId.ItemComponent
|
||||
);
|
||||
|
||||
if (itemComponentEntry == null)
|
||||
{
|
||||
throw new KeyNotFoundException($"Item component entry for {key} not found.");
|
||||
}
|
||||
|
||||
if (!itemTable.Seek(itemComponentEntry.Value<int>("component_id"), out var itemComponent))
|
||||
{
|
||||
throw new KeyNotFoundException($"Item component for {key} not found.");
|
||||
}
|
||||
|
||||
var field = itemComponent["currencyCosts"];
|
||||
|
||||
field.Value = "";
|
||||
|
||||
foreach (var (itemId, quantity) in mod.GetValue<RecipeList>(key))
|
||||
{
|
||||
ModContext.AwaitId(itemId, id =>
|
||||
{
|
||||
var fieldValue = (string) field.Value;
|
||||
|
||||
if (fieldValue != "")
|
||||
{
|
||||
fieldValue += ",";
|
||||
}
|
||||
|
||||
fieldValue = $"{fieldValue}{id}:{quantity}";
|
||||
|
||||
field.Value = fieldValue;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,51 @@
|
||||
namespace InfectedRose.Interface.Templates
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
[ModType("skill")]
|
||||
public class SkillMod : ModType
|
||||
{
|
||||
[ModType("skill")]
|
||||
public class SkillMod : ModType
|
||||
public override void Apply(Mod mod)
|
||||
{
|
||||
public override void Apply(Mod mod)
|
||||
if (mod.Action != "add")
|
||||
{
|
||||
if (mod.Action != "add")
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var skillBehaviorTable = ModContext.Database["SkillBehavior"]!;
|
||||
var skillBehaviorTable = ModContext.Database["SkillBehavior"]!;
|
||||
|
||||
var skillBehavior = skillBehaviorTable.FromLookup(mod);
|
||||
var skillBehavior = skillBehaviorTable.FromLookup(mod);
|
||||
|
||||
if (mod.Locale != null)
|
||||
{
|
||||
ModContext.AddToLocale($"SkillBehavior_{skillBehavior.Key}_name", mod.Locale);
|
||||
}
|
||||
|
||||
ModContext.RegisterId(mod.Id, skillBehavior.Key);
|
||||
|
||||
foreach (var (key, behavior) in mod.Behaviors)
|
||||
{
|
||||
behavior.Apply(key);
|
||||
}
|
||||
|
||||
if (mod.HasValue("icon"))
|
||||
{
|
||||
var iconId = ModContext.AddIcon(mod.GetValue<string>("icon"), out var path);
|
||||
|
||||
ModContext.RegisterId(mod.Id, skillBehavior.Key);
|
||||
mod.Values["skillIcon"] = iconId;
|
||||
}
|
||||
|
||||
foreach (var (key, behavior) in mod.Behaviors)
|
||||
{
|
||||
behavior.Apply(key);
|
||||
}
|
||||
|
||||
ModContext.ApplyValues(mod, skillBehavior, skillBehaviorTable);
|
||||
ModContext.ApplyValues(mod, skillBehavior, skillBehaviorTable);
|
||||
|
||||
if (mod.HasValue("root-behavior"))
|
||||
if (mod.HasValue("icon"))
|
||||
{
|
||||
mod.Values.Remove("skillIcon");
|
||||
}
|
||||
|
||||
if (mod.HasValue("root-behavior"))
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("root-behavior"), i =>
|
||||
{
|
||||
ModContext.AwaitId(mod.GetValue<string>("root-behavior"), i =>
|
||||
{
|
||||
skillBehavior["behaviorID"].Value = i;
|
||||
});
|
||||
}
|
||||
skillBehavior["behaviorID"].Value = i;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,18 @@
|
||||
namespace InfectedRose.Interface.Templates
|
||||
namespace InfectedRose.Interface.Templates;
|
||||
|
||||
[ModType("sql")]
|
||||
public class SqlMod : ModType
|
||||
{
|
||||
[ModType("sql")]
|
||||
public class SqlMod : ModType
|
||||
public override void Apply(Mod mod)
|
||||
{
|
||||
public override void Apply(Mod mod)
|
||||
switch (mod.Action)
|
||||
{
|
||||
switch (mod.Action)
|
||||
{
|
||||
case "run":
|
||||
ModContext.GeneralSql.Add(ModContext.ParseValue(mod.GetValue<string>("sql")));
|
||||
break;
|
||||
case "run-server":
|
||||
ModContext.ServerSql.Add(ModContext.ParseValue(mod.GetValue<string>("sql")));
|
||||
break;
|
||||
}
|
||||
case "run":
|
||||
ModContext.GeneralSql.Add(ModContext.ParseValue(mod.GetValue<string>("sql")));
|
||||
break;
|
||||
case "run-server":
|
||||
ModContext.ServerSql.Add(ModContext.ParseValue(mod.GetValue<string>("sql")));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,16 @@
|
||||
using System.Drawing;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes;
|
||||
|
||||
public struct Color3
|
||||
{
|
||||
public struct Color3
|
||||
{
|
||||
[JsonPropertyName("r")]
|
||||
public float R { get; set; }
|
||||
[JsonPropertyName("r")]
|
||||
public float R { get; set; }
|
||||
|
||||
[JsonPropertyName("g")]
|
||||
public float G { get; set; }
|
||||
[JsonPropertyName("g")]
|
||||
public float G { get; set; }
|
||||
|
||||
[JsonPropertyName("b")]
|
||||
public float B { get; set; }
|
||||
}
|
||||
[JsonPropertyName("b")]
|
||||
public float B { get; set; }
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes;
|
||||
|
||||
public class DataDictionary : Dictionary<string, DataValue>
|
||||
{
|
||||
public class DataDictionary : Dictionary<string, DataValue>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,81 +1,188 @@
|
||||
using System;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes;
|
||||
|
||||
public class DataValue
|
||||
{
|
||||
public class DataValue
|
||||
[JsonPropertyName("value")]
|
||||
public JsonValue Value { get; set; }
|
||||
|
||||
[JsonPropertyName("type")]
|
||||
public string? TypeInternal { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public FieldType Type
|
||||
{
|
||||
[JsonPropertyName("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonPropertyName("value")]
|
||||
public object Value { get; set; }
|
||||
|
||||
public static int ParseTypeString(string type)
|
||||
get
|
||||
{
|
||||
return type switch
|
||||
if (TypeInternal == null)
|
||||
{
|
||||
"int" => 1,
|
||||
"float" => 3,
|
||||
"double" => 4,
|
||||
"uint" => 5,
|
||||
"bool" => 7,
|
||||
"long" => 8,
|
||||
"blob" => 13,
|
||||
"string" => 0,
|
||||
"id" => 100,
|
||||
_ => 0
|
||||
};
|
||||
}
|
||||
|
||||
public static string ParseType(int type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
1 => "int",
|
||||
3 => "float",
|
||||
4 => "double",
|
||||
5 => "uint",
|
||||
7 => "bool",
|
||||
8 => "long",
|
||||
13 => "blob",
|
||||
0 => "string",
|
||||
100 => "id",
|
||||
_ => "string"
|
||||
};
|
||||
}
|
||||
var str = Value.ToString();
|
||||
|
||||
if (int.TryParse(str, out var i))
|
||||
{
|
||||
return FieldType.Integer;
|
||||
}
|
||||
|
||||
if (float.TryParse(str, out var f))
|
||||
{
|
||||
return FieldType.Float;
|
||||
}
|
||||
|
||||
// Count instances of \u001f
|
||||
var instances = str.Split("\u001f").Length;
|
||||
|
||||
if (instances == 3)
|
||||
{
|
||||
return FieldType.Position;
|
||||
}
|
||||
|
||||
if (instances == 4)
|
||||
{
|
||||
return FieldType.Rotation;
|
||||
}
|
||||
|
||||
|
||||
[JsonIgnore]
|
||||
public int TypeId
|
||||
{
|
||||
get => ParseTypeString(Type);
|
||||
set => Type = ParseType(value);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var type = TypeId;
|
||||
var value = Value;
|
||||
|
||||
if (value is false) value = 0;
|
||||
else if (value is true) value = 1;
|
||||
else if (type == 0 || type == 13) value = value.ToString();
|
||||
|
||||
if (type == 100)
|
||||
{
|
||||
value = ModContext.AssertId((string)value!);
|
||||
type = 1;
|
||||
return FieldType.String;
|
||||
}
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
value = value.ToString();
|
||||
|
||||
if (value == "True") value = "1";
|
||||
else if (value == "False") value = "0";
|
||||
if (Enum.TryParse<FieldType>(TypeInternal, out var fieldType)) return fieldType;
|
||||
|
||||
fieldType = ParseFieldType(TypeInternal);
|
||||
|
||||
TypeInternal = fieldType.ToString();
|
||||
|
||||
return fieldType;
|
||||
}
|
||||
set => TypeInternal = value.ToString();
|
||||
}
|
||||
|
||||
public static string ParseFieldType(FieldType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
FieldType.Id => "id",
|
||||
FieldType.Object => "id",
|
||||
FieldType.WorldObject => "id",
|
||||
FieldType.Integer => "int",
|
||||
FieldType.UnsignedInteger => "uint",
|
||||
FieldType.String => "string",
|
||||
FieldType.Buffer => "blob",
|
||||
FieldType.Skill => "id",
|
||||
FieldType.Flag => "id",
|
||||
FieldType.Mission => "id",
|
||||
FieldType.Float => "float",
|
||||
FieldType.Double => "double",
|
||||
FieldType.Boolean => "bool",
|
||||
FieldType.Model => "id",
|
||||
FieldType.Physics => "id",
|
||||
FieldType.Icon => "id",
|
||||
FieldType.None => "string",
|
||||
FieldType.Position => "string",
|
||||
FieldType.Rotation => "string",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
|
||||
};
|
||||
}
|
||||
|
||||
public static FieldType ParseFieldType(string type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
"id" => FieldType.Object,
|
||||
"int" => FieldType.Integer,
|
||||
"uint" => FieldType.UnsignedInteger,
|
||||
"string" => FieldType.String,
|
||||
"blob" => FieldType.Buffer,
|
||||
"float" => FieldType.Float,
|
||||
"double" => FieldType.Double,
|
||||
"bool" => FieldType.Boolean,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type), type, $"Unknown type: {type}")
|
||||
};
|
||||
}
|
||||
|
||||
public static string ParseType(int type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
1 => "int",
|
||||
3 => "float",
|
||||
4 => "double",
|
||||
5 => "uint",
|
||||
7 => "bool",
|
||||
8 => "long",
|
||||
13 => "blob",
|
||||
0 => "string",
|
||||
100 => "id",
|
||||
_ => "string"
|
||||
};
|
||||
}
|
||||
|
||||
public static int ParseType(string type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
"int" => 1,
|
||||
"float" => 3,
|
||||
"double" => 4,
|
||||
"uint" => 5,
|
||||
"bool" => 7,
|
||||
"long" => 8,
|
||||
"blob" => 13,
|
||||
"string" => 0,
|
||||
"id" => 0,
|
||||
_ => 0
|
||||
};
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public int TypeId
|
||||
{
|
||||
set => ParseFieldType(ParseType(value));
|
||||
get => ParseType(ParseFieldType(Type));
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public object? ObjectValue
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
case FieldType.None:
|
||||
return null;
|
||||
case FieldType.Id:
|
||||
case FieldType.Object:
|
||||
case FieldType.WorldObject:
|
||||
case FieldType.String:
|
||||
case FieldType.Buffer:
|
||||
case FieldType.Rotation:
|
||||
case FieldType.Position:
|
||||
case FieldType.Skill:
|
||||
case FieldType.Flag:
|
||||
case FieldType.Mission:
|
||||
case FieldType.Model:
|
||||
case FieldType.Physics:
|
||||
case FieldType.Icon:
|
||||
return Value.ToString();
|
||||
case FieldType.Integer:
|
||||
return Value.GetValue<int>();
|
||||
case FieldType.UnsignedInteger:
|
||||
return Value.GetValue<uint>();
|
||||
case FieldType.Float:
|
||||
return Value.GetValue<float>();
|
||||
case FieldType.Double:
|
||||
return Value.GetValue<double>();
|
||||
case FieldType.Boolean:
|
||||
return Value.GetValue<bool>();
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
return $"{type}:{value}";
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{TypeId}:{Value}";
|
||||
}
|
||||
}
|
||||
24
InfectedRose.Interface/Templates/ValueTypes/FieldType.cs
Normal file
24
InfectedRose.Interface/Templates/ValueTypes/FieldType.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes;
|
||||
|
||||
public enum FieldType
|
||||
{
|
||||
None,
|
||||
Id,
|
||||
Object,
|
||||
WorldObject,
|
||||
Integer,
|
||||
UnsignedInteger,
|
||||
String,
|
||||
Buffer,
|
||||
Position,
|
||||
Rotation,
|
||||
Skill,
|
||||
Flag,
|
||||
Mission,
|
||||
Float,
|
||||
Double,
|
||||
Boolean,
|
||||
Model,
|
||||
Physics,
|
||||
Icon,
|
||||
}
|
||||
@@ -1,29 +1,28 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes;
|
||||
|
||||
public class LevelTemplate
|
||||
{
|
||||
public class LevelTemplate
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public JsonValue Id { get; set; }
|
||||
[JsonPropertyName("id")]
|
||||
public JsonValue Id { get; set; }
|
||||
|
||||
[JsonPropertyName("type")]
|
||||
public int? Type { get; set; }
|
||||
|
||||
[JsonPropertyName("type")]
|
||||
public int Type { get; set; }
|
||||
[JsonPropertyName("object-id")]
|
||||
public ulong? ObjectId { get; set; }
|
||||
|
||||
[JsonPropertyName("object-id")]
|
||||
public ulong? ObjectId { get; set; }
|
||||
[JsonPropertyName("position")]
|
||||
public Point3 Position { get; set; }
|
||||
|
||||
[JsonPropertyName("position")]
|
||||
public Point3 Position { get; set; }
|
||||
[JsonPropertyName("rotation")]
|
||||
public Point4 Rotation { get; set; }
|
||||
|
||||
[JsonPropertyName("rotation")]
|
||||
public Point4 Rotation { get; set; }
|
||||
[JsonPropertyName("scale")]
|
||||
public float? Scale { get; set; }
|
||||
|
||||
[JsonPropertyName("scale")]
|
||||
public float Scale { get; set; }
|
||||
|
||||
[JsonPropertyName("data")]
|
||||
public DataDictionary Data { get; set; }
|
||||
}
|
||||
[JsonPropertyName("data")]
|
||||
public DataDictionary Data { get; set; }
|
||||
}
|
||||
@@ -1,16 +1,15 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes;
|
||||
|
||||
public class Particle
|
||||
{
|
||||
public class Particle
|
||||
{
|
||||
[JsonPropertyName("position")]
|
||||
public Point3 Position { get; set; }
|
||||
[JsonPropertyName("position")]
|
||||
public Point3 Position { get; set; }
|
||||
|
||||
[JsonPropertyName("rotation")]
|
||||
public Point4 Rotation { get; set; }
|
||||
[JsonPropertyName("rotation")]
|
||||
public Point4 Rotation { get; set; }
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
@@ -1,135 +1,134 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes;
|
||||
|
||||
public class PathData
|
||||
{
|
||||
public class PathData
|
||||
public class Waypoint
|
||||
{
|
||||
public class Waypoint
|
||||
public class Config
|
||||
{
|
||||
public class Config
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonPropertyName("value")]
|
||||
public DataValue Value { get; set; }
|
||||
}
|
||||
|
||||
[JsonPropertyName("position")]
|
||||
public Point3 Position { get; set; }
|
||||
|
||||
[JsonPropertyName("rotation")]
|
||||
public Point4? Rotation { get; set; }
|
||||
|
||||
// Camera
|
||||
[JsonPropertyName("time")]
|
||||
public float? Time { get; set; }
|
||||
|
||||
[JsonPropertyName("tension")]
|
||||
public float? Tension { get; set; }
|
||||
|
||||
[JsonPropertyName("continuity")]
|
||||
public float? Continuity { get; set; }
|
||||
|
||||
[JsonPropertyName("bias")]
|
||||
public float? Bias { get; set; }
|
||||
|
||||
[JsonPropertyName("field-of-view")]
|
||||
public float? FieldOfView { get; set; }
|
||||
|
||||
[JsonPropertyName("config")]
|
||||
public Config[]? Configuration { get; set; }
|
||||
|
||||
// Moving platform
|
||||
[JsonPropertyName("lock-player")]
|
||||
public bool? LockPlayer { get; set; }
|
||||
|
||||
[JsonPropertyName("speed")]
|
||||
public float? Speed { get; set; }
|
||||
|
||||
[JsonPropertyName("wait")]
|
||||
public float? Wait { get; set; }
|
||||
|
||||
[JsonPropertyName("depart-sound")]
|
||||
public string? DepartSound { get; set; }
|
||||
|
||||
[JsonPropertyName("arrive-sound")]
|
||||
public string? ArriveSound { get; set; }
|
||||
[JsonPropertyName("value")]
|
||||
public DataValue Value { get; set; }
|
||||
}
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonPropertyName("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonPropertyName("behavior")]
|
||||
public string Behavior { get; set; }
|
||||
|
||||
[JsonPropertyName("waypoints")]
|
||||
public Waypoint[] Waypoints { get; set; }
|
||||
|
||||
|
||||
[JsonPropertyName("position")]
|
||||
public Point3 Position { get; set; }
|
||||
|
||||
[JsonPropertyName("rotation")]
|
||||
public Point4? Rotation { get; set; }
|
||||
|
||||
// Camera
|
||||
[JsonPropertyName("time")]
|
||||
public float? Time { get; set; }
|
||||
|
||||
[JsonPropertyName("tension")]
|
||||
public float? Tension { get; set; }
|
||||
|
||||
[JsonPropertyName("continuity")]
|
||||
public float? Continuity { get; set; }
|
||||
|
||||
[JsonPropertyName("bias")]
|
||||
public float? Bias { get; set; }
|
||||
|
||||
[JsonPropertyName("field-of-view")]
|
||||
public float? FieldOfView { get; set; }
|
||||
|
||||
[JsonPropertyName("config")]
|
||||
public Config[]? Configuration { get; set; }
|
||||
|
||||
// Moving platform
|
||||
[JsonPropertyName("next-path")]
|
||||
public string? NextPath { get; set; }
|
||||
|
||||
[JsonPropertyName("sound")]
|
||||
public string? Sound { get; set; }
|
||||
|
||||
[JsonPropertyName("time-based")]
|
||||
public bool? TimeBased { get; set; }
|
||||
|
||||
// Property
|
||||
[JsonPropertyName("price")]
|
||||
public int? Price { get; set; }
|
||||
[JsonPropertyName("lock-player")]
|
||||
public bool? LockPlayer { get; set; }
|
||||
|
||||
[JsonPropertyName("rental-time")]
|
||||
public int? RentalTime { get; set; }
|
||||
[JsonPropertyName("speed")]
|
||||
public float? Speed { get; set; }
|
||||
|
||||
[JsonPropertyName("associative-zone")]
|
||||
public string? AssociativeZone { get; set; }
|
||||
[JsonPropertyName("wait")]
|
||||
public float? Wait { get; set; }
|
||||
|
||||
[JsonPropertyName("display-name")]
|
||||
public string? DisplayName { get; set; }
|
||||
[JsonPropertyName("depart-sound")]
|
||||
public string? DepartSound { get; set; }
|
||||
|
||||
[JsonPropertyName("display-description")]
|
||||
public string? DisplayDescription { get; set; }
|
||||
|
||||
[JsonPropertyName("clone-limit")]
|
||||
public int? CloneLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("reputation-multiplier")]
|
||||
public float? ReputationMultiplier { get; set; }
|
||||
|
||||
[JsonPropertyName("time-unit")]
|
||||
public string? TimeUnit { get; set; }
|
||||
|
||||
[JsonPropertyName("achievement")]
|
||||
public string? Achievement { get; set; }
|
||||
|
||||
[JsonPropertyName("player-zone-point")]
|
||||
public Point3? PlayerZonePoint { get; set; }
|
||||
|
||||
[JsonPropertyName("max-build-height")]
|
||||
public float? MaxBuildHeight { get; set; }
|
||||
|
||||
// Spawner
|
||||
[JsonPropertyName("spawned-id")]
|
||||
public string? SpawnedId { get; set; }
|
||||
|
||||
[JsonPropertyName("respawn-time")]
|
||||
public float? RespawnTime { get; set; }
|
||||
|
||||
[JsonPropertyName("max-spawn-count")]
|
||||
public int? MaxSpawnCount { get; set; }
|
||||
|
||||
[JsonPropertyName("number-to-maintain")]
|
||||
public int? NumberToMaintain { get; set; }
|
||||
|
||||
[JsonPropertyName("spawner-object")]
|
||||
public string? SpawnerObject { get; set; }
|
||||
|
||||
[JsonPropertyName("activate-on-load")]
|
||||
public bool? ActivateOnLoad { get; set; }
|
||||
[JsonPropertyName("arrive-sound")]
|
||||
public string? ArriveSound { get; set; }
|
||||
}
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonPropertyName("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonPropertyName("behavior")]
|
||||
public string Behavior { get; set; }
|
||||
|
||||
[JsonPropertyName("waypoints")]
|
||||
public Waypoint[] Waypoints { get; set; }
|
||||
|
||||
// Moving platform
|
||||
[JsonPropertyName("next-path")]
|
||||
public string? NextPath { get; set; }
|
||||
|
||||
[JsonPropertyName("sound")]
|
||||
public string? Sound { get; set; }
|
||||
|
||||
[JsonPropertyName("time-based")]
|
||||
public bool? TimeBased { get; set; }
|
||||
|
||||
// Property
|
||||
[JsonPropertyName("price")]
|
||||
public int? Price { get; set; }
|
||||
|
||||
[JsonPropertyName("rental-time")]
|
||||
public int? RentalTime { get; set; }
|
||||
|
||||
[JsonPropertyName("associative-zone")]
|
||||
public string? AssociativeZone { get; set; }
|
||||
|
||||
[JsonPropertyName("display-name")]
|
||||
public string? DisplayName { get; set; }
|
||||
|
||||
[JsonPropertyName("display-description")]
|
||||
public string? DisplayDescription { get; set; }
|
||||
|
||||
[JsonPropertyName("clone-limit")]
|
||||
public int? CloneLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("reputation-multiplier")]
|
||||
public float? ReputationMultiplier { get; set; }
|
||||
|
||||
[JsonPropertyName("time-unit")]
|
||||
public string? TimeUnit { get; set; }
|
||||
|
||||
[JsonPropertyName("achievement")]
|
||||
public string? Achievement { get; set; }
|
||||
|
||||
[JsonPropertyName("player-zone-point")]
|
||||
public Point3? PlayerZonePoint { get; set; }
|
||||
|
||||
[JsonPropertyName("max-build-height")]
|
||||
public float? MaxBuildHeight { get; set; }
|
||||
|
||||
// Spawner
|
||||
[JsonPropertyName("spawned-id")]
|
||||
public string? SpawnedId { get; set; }
|
||||
|
||||
[JsonPropertyName("respawn-time")]
|
||||
public float? RespawnTime { get; set; }
|
||||
|
||||
[JsonPropertyName("max-spawn-count")]
|
||||
public int? MaxSpawnCount { get; set; }
|
||||
|
||||
[JsonPropertyName("number-to-maintain")]
|
||||
public int? NumberToMaintain { get; set; }
|
||||
|
||||
[JsonPropertyName("spawner-object")]
|
||||
public string? SpawnerObject { get; set; }
|
||||
|
||||
[JsonPropertyName("activate-on-load")]
|
||||
public bool? ActivateOnLoad { get; set; }
|
||||
}
|
||||
@@ -1,23 +1,22 @@
|
||||
using System.Numerics;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes;
|
||||
|
||||
public struct Point3
|
||||
{
|
||||
public struct Point3
|
||||
[JsonPropertyName("x")]
|
||||
public float X { get; set; }
|
||||
|
||||
[JsonPropertyName("y")]
|
||||
public float Y { get; set; }
|
||||
|
||||
[JsonPropertyName("z")]
|
||||
public float Z { get; set; }
|
||||
|
||||
// Implicit conversion from Point3 to Vector3
|
||||
public static implicit operator Vector3(Point3 point)
|
||||
{
|
||||
[JsonPropertyName("x")]
|
||||
public float X { get; set; }
|
||||
|
||||
[JsonPropertyName("y")]
|
||||
public float Y { get; set; }
|
||||
|
||||
[JsonPropertyName("z")]
|
||||
public float Z { get; set; }
|
||||
|
||||
// Implicit conversion from Point3 to Vector3
|
||||
public static implicit operator Vector3(Point3 point)
|
||||
{
|
||||
return new Vector3(point.X, point.Y, point.Z);
|
||||
}
|
||||
return new Vector3(point.X, point.Y, point.Z);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,25 @@
|
||||
using System.Numerics;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes;
|
||||
|
||||
public struct Point4
|
||||
{
|
||||
public struct Point4
|
||||
[JsonPropertyName("x")]
|
||||
public float X { get; set; }
|
||||
|
||||
[JsonPropertyName("y")]
|
||||
public float Y { get; set; }
|
||||
|
||||
[JsonPropertyName("z")]
|
||||
public float Z { get; set; }
|
||||
|
||||
[JsonPropertyName("w")]
|
||||
public float W { get; set; }
|
||||
|
||||
// Implicit conversion from Point4 to Quaternion
|
||||
public static implicit operator Quaternion(Point4 point)
|
||||
{
|
||||
[JsonPropertyName("x")]
|
||||
public float X { get; set; }
|
||||
|
||||
[JsonPropertyName("y")]
|
||||
public float Y { get; set; }
|
||||
|
||||
[JsonPropertyName("z")]
|
||||
public float Z { get; set; }
|
||||
|
||||
[JsonPropertyName("w")]
|
||||
public float W { get; set; }
|
||||
|
||||
// Implicit conversion from Point4 to Quaternion
|
||||
public static implicit operator Quaternion(Point4 point)
|
||||
{
|
||||
return new Quaternion(point.X, point.Y, point.Z, point.W);
|
||||
}
|
||||
return new Quaternion(point.X, point.Y, point.Z, point.W);
|
||||
}
|
||||
}
|
||||
@@ -1,77 +1,76 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using InfectedRose.Triggers;
|
||||
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes
|
||||
{
|
||||
public class Scene
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public int Id { get; set; }
|
||||
|
||||
[JsonPropertyName("layer")]
|
||||
public int Layer { get; set; }
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonPropertyName("skybox")]
|
||||
public string Skybox { get; set; }
|
||||
|
||||
[JsonPropertyName("blend-time")]
|
||||
public float BlendTime { get; set; }
|
||||
|
||||
[JsonPropertyName("ambient-color")]
|
||||
public Color3 AmbientColor { get; set; }
|
||||
|
||||
[JsonPropertyName("specular-color")]
|
||||
public Color3 SpecularColor { get; set; }
|
||||
|
||||
[JsonPropertyName("upper-hemi-color")]
|
||||
public Color3 UpperHemiColor { get; set; }
|
||||
|
||||
[JsonPropertyName("light-direction")]
|
||||
public Point3 LightDirection { get; set; }
|
||||
|
||||
[JsonPropertyName("fog-near-min")]
|
||||
public float FogNearMin { get; set; }
|
||||
|
||||
[JsonPropertyName("fog-far-min")]
|
||||
public float FogFarMin { get; set; }
|
||||
|
||||
[JsonPropertyName("post-fog-solid-min")]
|
||||
public float PostFogSolidMin { get; set; }
|
||||
|
||||
[JsonPropertyName("post-fog-fade-min")]
|
||||
public float PostFogFadeMin { get; set; }
|
||||
|
||||
[JsonPropertyName("fog-near-max")]
|
||||
public float FogNearMax { get; set; }
|
||||
|
||||
[JsonPropertyName("fog-far-max")]
|
||||
public float FogFarMax { get; set; }
|
||||
|
||||
[JsonPropertyName("post-fog-solid-max")]
|
||||
public float PostFogSolidMax { get; set; }
|
||||
|
||||
[JsonPropertyName("post-fog-fade-max")]
|
||||
public float PostFogFadeMax { get; set; }
|
||||
|
||||
[JsonPropertyName("fog-color")]
|
||||
public Color3 FogColor { get; set; }
|
||||
|
||||
[JsonPropertyName("directional-light-color")]
|
||||
public Color3 DirectionalLightColor { get; set; }
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes;
|
||||
|
||||
[JsonPropertyName("templates")]
|
||||
public LevelTemplate[] Templates { get; set; }
|
||||
public class Scene
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public int Id { get; set; }
|
||||
|
||||
[JsonPropertyName("particles")]
|
||||
public Particle[] Particles { get; set; }
|
||||
[JsonPropertyName("layer")]
|
||||
public int Layer { get; set; }
|
||||
|
||||
[JsonPropertyName("triggers")]
|
||||
public Trigger[] Triggers { get; set; }
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonPropertyName("scene-audio")]
|
||||
public SceneAudio SceneAudio { get; set; }
|
||||
}
|
||||
[JsonPropertyName("skybox")]
|
||||
public string Skybox { get; set; }
|
||||
|
||||
[JsonPropertyName("blend-time")]
|
||||
public float BlendTime { get; set; }
|
||||
|
||||
[JsonPropertyName("ambient-color")]
|
||||
public Color3 AmbientColor { get; set; }
|
||||
|
||||
[JsonPropertyName("specular-color")]
|
||||
public Color3 SpecularColor { get; set; }
|
||||
|
||||
[JsonPropertyName("upper-hemi-color")]
|
||||
public Color3 UpperHemiColor { get; set; }
|
||||
|
||||
[JsonPropertyName("light-direction")]
|
||||
public Point3 LightDirection { get; set; }
|
||||
|
||||
[JsonPropertyName("fog-near-min")]
|
||||
public float FogNearMin { get; set; }
|
||||
|
||||
[JsonPropertyName("fog-far-min")]
|
||||
public float FogFarMin { get; set; }
|
||||
|
||||
[JsonPropertyName("post-fog-solid-min")]
|
||||
public float PostFogSolidMin { get; set; }
|
||||
|
||||
[JsonPropertyName("post-fog-fade-min")]
|
||||
public float PostFogFadeMin { get; set; }
|
||||
|
||||
[JsonPropertyName("fog-near-max")]
|
||||
public float FogNearMax { get; set; }
|
||||
|
||||
[JsonPropertyName("fog-far-max")]
|
||||
public float FogFarMax { get; set; }
|
||||
|
||||
[JsonPropertyName("post-fog-solid-max")]
|
||||
public float PostFogSolidMax { get; set; }
|
||||
|
||||
[JsonPropertyName("post-fog-fade-max")]
|
||||
public float PostFogFadeMax { get; set; }
|
||||
|
||||
[JsonPropertyName("fog-color")]
|
||||
public Color3 FogColor { get; set; }
|
||||
|
||||
[JsonPropertyName("directional-light-color")]
|
||||
public Color3 DirectionalLightColor { get; set; }
|
||||
|
||||
[JsonPropertyName("templates")]
|
||||
public LevelTemplate[] Templates { get; set; }
|
||||
|
||||
[JsonPropertyName("particles")]
|
||||
public Particle[] Particles { get; set; }
|
||||
|
||||
[JsonPropertyName("triggers")]
|
||||
public Trigger[] Triggers { get; set; }
|
||||
|
||||
[JsonPropertyName("scene-audio")]
|
||||
public SceneAudio SceneAudio { get; set; }
|
||||
}
|
||||
@@ -1,41 +1,40 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes;
|
||||
|
||||
[XmlRoot("SceneAudioAttributes")]
|
||||
public class SceneAudio
|
||||
{
|
||||
[XmlRoot("SceneAudioAttributes")]
|
||||
public class SceneAudio
|
||||
{
|
||||
[JsonPropertyName("music-cue")]
|
||||
[XmlAttribute("musicCue")]
|
||||
public string MusicCue { get; set; }
|
||||
[JsonPropertyName("music-cue")]
|
||||
[XmlAttribute("musicCue")]
|
||||
public string MusicCue { get; set; }
|
||||
|
||||
[JsonPropertyName("music-param-name")]
|
||||
[XmlAttribute("musicParamName")]
|
||||
public string MusicParamName { get; set; }
|
||||
[JsonPropertyName("music-param-name")]
|
||||
[XmlAttribute("musicParamName")]
|
||||
public string MusicParamName { get; set; }
|
||||
|
||||
[JsonPropertyName("guid-2d")]
|
||||
[XmlAttribute("guid2D")]
|
||||
public string Guid2D { get; set; }
|
||||
[JsonPropertyName("guid-2d")]
|
||||
[XmlAttribute("guid2D")]
|
||||
public string Guid2D { get; set; }
|
||||
|
||||
[JsonPropertyName("guid-3d")]
|
||||
[XmlAttribute("guid3D")]
|
||||
public string Guid3D { get; set; }
|
||||
[JsonPropertyName("guid-3d")]
|
||||
[XmlAttribute("guid3D")]
|
||||
public string Guid3D { get; set; }
|
||||
|
||||
[JsonPropertyName("group-name")]
|
||||
[XmlAttribute("groupName")]
|
||||
public string GroupName { get; set; }
|
||||
[JsonPropertyName("group-name")]
|
||||
[XmlAttribute("groupName")]
|
||||
public string GroupName { get; set; }
|
||||
|
||||
[JsonPropertyName("program-name")]
|
||||
[XmlAttribute("programName")]
|
||||
public string ProgramName { get; set; }
|
||||
[JsonPropertyName("program-name")]
|
||||
[XmlAttribute("programName")]
|
||||
public string ProgramName { get; set; }
|
||||
|
||||
[JsonPropertyName("music-param-value")]
|
||||
[XmlAttribute("musicParamValue")]
|
||||
public string MusicParamValue { get; set; }
|
||||
[JsonPropertyName("music-param-value")]
|
||||
[XmlAttribute("musicParamValue")]
|
||||
public string MusicParamValue { get; set; }
|
||||
|
||||
[JsonPropertyName("boredom-time")]
|
||||
[XmlAttribute("boredomTime")]
|
||||
public string BoredomTime { get; set; }
|
||||
}
|
||||
[JsonPropertyName("boredom-time")]
|
||||
[XmlAttribute("boredomTime")]
|
||||
public string BoredomTime { get; set; }
|
||||
}
|
||||
@@ -1,22 +1,21 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes;
|
||||
|
||||
public class Transition
|
||||
{
|
||||
public class Transition
|
||||
public class Point
|
||||
{
|
||||
public class Point
|
||||
{
|
||||
[JsonPropertyName("scene")]
|
||||
public string Scene { get; set; }
|
||||
[JsonPropertyName("scene")]
|
||||
public string Scene { get; set; }
|
||||
|
||||
[JsonPropertyName("position")]
|
||||
public Point3 Position { get; set; }
|
||||
}
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonPropertyName("points")]
|
||||
public Point[] Points { get; set; }
|
||||
[JsonPropertyName("position")]
|
||||
public Point3 Position { get; set; }
|
||||
}
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonPropertyName("points")]
|
||||
public Point[] Points { get; set; }
|
||||
}
|
||||
@@ -1,25 +1,24 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes
|
||||
namespace InfectedRose.Interface.Templates.ValueTypes;
|
||||
|
||||
public class Zone
|
||||
{
|
||||
public class Zone
|
||||
{
|
||||
[JsonPropertyName("spawn-point")]
|
||||
public Point3 SpawnPoint { get; set; }
|
||||
[JsonPropertyName("spawn-point")]
|
||||
public Point3 SpawnPoint { get; set; }
|
||||
|
||||
[JsonPropertyName("spawn-rotation")]
|
||||
public Point4 SpawnRotation { get; set; }
|
||||
[JsonPropertyName("spawn-rotation")]
|
||||
public Point4 SpawnRotation { get; set; }
|
||||
|
||||
[JsonPropertyName("terrain-file")]
|
||||
public string TerrainFile { get; set; }
|
||||
[JsonPropertyName("terrain-file")]
|
||||
public string TerrainFile { get; set; }
|
||||
|
||||
[JsonPropertyName("scenes")]
|
||||
public Scene[] Scenes { get; set; }
|
||||
[JsonPropertyName("scenes")]
|
||||
public Scene[] Scenes { get; set; }
|
||||
|
||||
[JsonPropertyName("transitions")]
|
||||
public Transition[] Transitions { get; set; }
|
||||
[JsonPropertyName("transitions")]
|
||||
public Transition[] Transitions { get; set; }
|
||||
|
||||
[JsonPropertyName("paths")]
|
||||
public PathData[] Paths { get; set; }
|
||||
}
|
||||
[JsonPropertyName("paths")]
|
||||
public PathData[] Paths { get; set; }
|
||||
}
|
||||
251
InfectedRose.Interface/Templates/World/WorldInstances.cs
Normal file
251
InfectedRose.Interface/Templates/World/WorldInstances.cs
Normal file
@@ -0,0 +1,251 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using InfectedRose.Database.Generic;
|
||||
using InfectedRose.Luz;
|
||||
using InfectedRose.Lvl;
|
||||
using RakDotNet.IO;
|
||||
|
||||
namespace InfectedRose.Interface.Templates.World;
|
||||
|
||||
public class WorldInstance
|
||||
{
|
||||
public static Dictionary<string, WorldInstance> WorldInstances { get; } = new();
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public LuzFile Zone { get; set; }
|
||||
|
||||
public Dictionary<string, LvlFile> Scenes { get; set; }
|
||||
|
||||
public HashSet<ulong> ClaimedIds { get; }
|
||||
|
||||
public WorldInstance(string name, LuzFile zone, Dictionary<string, LvlFile> scenes, HashSet<ulong> claimedIds)
|
||||
{
|
||||
Name = name;
|
||||
Zone = zone;
|
||||
Scenes = scenes;
|
||||
ClaimedIds = claimedIds;
|
||||
}
|
||||
|
||||
public ulong ClaimId()
|
||||
{
|
||||
var lowest = 0x38B40AUL;
|
||||
|
||||
while (ClaimedIds.Contains(lowest))
|
||||
{
|
||||
lowest++;
|
||||
}
|
||||
|
||||
ClaimedIds.Add(lowest);
|
||||
|
||||
return lowest;
|
||||
}
|
||||
|
||||
public static void Await(string id, Action<WorldInstance> callback)
|
||||
{
|
||||
if (WorldInstances.TryGetValue(id, out var instance))
|
||||
{
|
||||
callback(instance);
|
||||
}
|
||||
|
||||
ModContext.AwaitId(id, zoneId =>
|
||||
{
|
||||
var zoneTable = ModContext.Database["ZoneTable"]!;
|
||||
|
||||
if (!zoneTable.Seek(zoneId, out var zoneEntry))
|
||||
{
|
||||
throw new Exception($"Zone {zoneId} not found");
|
||||
}
|
||||
|
||||
var zoneName = zoneEntry.Value<string>("zoneName").ToLower();
|
||||
|
||||
var path = Path.Combine(ModContext.Root, "../res/maps/", zoneName);
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
throw new Exception($"Zone file for {zoneName} not found: {path}");
|
||||
}
|
||||
|
||||
var zone = new LuzFile();
|
||||
|
||||
{
|
||||
using var zoneStream = File.OpenRead(path);
|
||||
using var zoneReader = new ByteReader(zoneStream);
|
||||
|
||||
zone.Deserialize(zoneReader);
|
||||
}
|
||||
|
||||
var scenes = new Dictionary<string, LvlFile>();
|
||||
|
||||
var claimedIds = new HashSet<ulong>();
|
||||
|
||||
var zoneRoot = Path.GetDirectoryName(path)!;
|
||||
|
||||
foreach (var scene in zone.Scenes)
|
||||
{
|
||||
var scenePath = Path.Combine(zoneRoot, scene.FileName.ToLower());
|
||||
|
||||
if (!File.Exists(scenePath))
|
||||
{
|
||||
throw new Exception($"Scene file for {scene.SceneName} not found: {scenePath}");
|
||||
}
|
||||
|
||||
var lvl = new LvlFile();
|
||||
|
||||
using var lvlStream = File.OpenRead(scenePath);
|
||||
using var lvlReader = new ByteReader(lvlStream);
|
||||
|
||||
lvl.Deserialize(lvlReader);
|
||||
|
||||
if (lvl.LevelObjects != null)
|
||||
{
|
||||
foreach (var template in lvl.LevelObjects.Templates)
|
||||
{
|
||||
claimedIds.Add(template.ObjectId);
|
||||
}
|
||||
}
|
||||
|
||||
scenes.Add(scene.FileName.ToLower(), lvl);
|
||||
}
|
||||
|
||||
instance = new WorldInstance(zoneName, zone, scenes, claimedIds);
|
||||
|
||||
WorldInstances.Add(id, instance);
|
||||
|
||||
callback(instance);
|
||||
});
|
||||
}
|
||||
|
||||
public static WorldInstance Get(string id)
|
||||
{
|
||||
if (!WorldInstances.TryGetValue(id, out var instance))
|
||||
{
|
||||
throw new Exception($"World instance {id} not found");
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static void AwaitZone(string id, Action<LuzFile> callback)
|
||||
{
|
||||
Await(id, instance => callback(instance.Zone));
|
||||
}
|
||||
|
||||
public static void AwaitScene(string id, string sceneName, Action<LvlFile> callback)
|
||||
{
|
||||
Await(id, instance =>
|
||||
{
|
||||
var sceneId = -1;
|
||||
var layerId = -1;
|
||||
|
||||
if (sceneName.Contains(":"))
|
||||
{
|
||||
var split = sceneName.Split(':');
|
||||
|
||||
if (split.Length != 3)
|
||||
{
|
||||
throw new Exception($"Invalid scene id {id}");
|
||||
}
|
||||
|
||||
sceneName = split[0];
|
||||
sceneId = int.Parse(split[1]);
|
||||
layerId = int.Parse(split[2]);
|
||||
}
|
||||
|
||||
foreach (var scene in instance.Zone.Scenes)
|
||||
{
|
||||
if (sceneId == -1 && layerId == -1 && sceneName == scene.SceneName)
|
||||
{
|
||||
callback(instance.Scenes[scene.FileName.ToLower()]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (sceneId != scene.SceneId || layerId != scene.LayerId || sceneName != scene.SceneName) continue;
|
||||
|
||||
callback(instance.Scenes[scene.FileName.ToLower()]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Exception($"Scene {sceneName} not found");
|
||||
});
|
||||
}
|
||||
|
||||
public static void SaveWorldInstances()
|
||||
{
|
||||
foreach (var (name, instance) in WorldInstances)
|
||||
{
|
||||
SaveWorldInstance(name, instance.Zone, instance.Scenes);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SaveWorldInstance(string name, LuzFile luzFile, Dictionary<string, LvlFile> scenes)
|
||||
{
|
||||
var zoneTable = ModContext.Database["ZoneTable"]!;
|
||||
|
||||
var zoneId = ModContext.AssertId(name);
|
||||
|
||||
if (!zoneTable.Seek(zoneId, out var zoneEntry))
|
||||
{
|
||||
throw new Exception($"Zone {name} not found");
|
||||
}
|
||||
|
||||
var zoneName = zoneEntry.Value<string>("zoneName").ToLower();
|
||||
|
||||
var root = Path.Combine(
|
||||
ModContext.Root,
|
||||
ModContext.Configuration.ResourceFolder,
|
||||
$"./compiled/{zoneId}/",
|
||||
Path.GetDirectoryName(zoneName)!
|
||||
);
|
||||
|
||||
if (!Directory.Exists(root))
|
||||
{
|
||||
Directory.CreateDirectory(root);
|
||||
}
|
||||
|
||||
var path = Path.Combine(root, Path.GetFileName(zoneName));
|
||||
|
||||
{
|
||||
using var zoneStream = File.Create(path);
|
||||
using var zoneWriter = new ByteWriter(zoneStream);
|
||||
|
||||
luzFile.Serialize(zoneWriter);
|
||||
}
|
||||
|
||||
foreach (var (fileName, scene) in scenes)
|
||||
{
|
||||
var scenePath = Path.Combine(root, fileName);
|
||||
|
||||
using var sceneStream = File.Create(scenePath);
|
||||
using var sceneWriter = new ByteWriter(sceneStream);
|
||||
|
||||
scene.Serialize(sceneWriter);
|
||||
}
|
||||
|
||||
var originalPath = Path.Combine(ModContext.Root, "../res/maps/", zoneName);
|
||||
|
||||
// Copy all ".raw", ".lutriggers", ".evc", and ".ast" files
|
||||
foreach (var file in Directory.GetFiles(Path.GetDirectoryName(originalPath)!))
|
||||
{
|
||||
var extension = Path.GetExtension(file);
|
||||
|
||||
if (extension == ".raw" || extension == ".lutriggers" || extension == ".evc" || extension == ".ast")
|
||||
{
|
||||
File.Copy(file, Path.Combine(root, Path.GetFileName(file)), true);
|
||||
|
||||
// Remove read-only flag
|
||||
var attributes = File.GetAttributes(Path.Combine(root, Path.GetFileName(file)));
|
||||
attributes &= ~FileAttributes.ReadOnly;
|
||||
File.SetAttributes(Path.Combine(root, Path.GetFileName(file)), attributes);
|
||||
}
|
||||
}
|
||||
|
||||
var link = new Uri(Path.Combine("../", ModContext.Configuration.ResourceFolder, $"./compiled/{zoneId}/", zoneName), UriKind.Relative);
|
||||
|
||||
zoneEntry["zoneName"].Value = link.ToString();
|
||||
}
|
||||
}
|
||||
144
InfectedRose.Interface/Templates/World/WorldObjectMod.cs
Normal file
144
InfectedRose.Interface/Templates/World/WorldObjectMod.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using InfectedRose.Interface.Templates.ValueTypes;
|
||||
using InfectedRose.Lvl;
|
||||
|
||||
namespace InfectedRose.Interface.Templates.World;
|
||||
|
||||
[ModType("world-object")]
|
||||
public class WorldObjectMod : ModType
|
||||
{
|
||||
public override void Apply(Mod mod)
|
||||
{
|
||||
var zoneId = mod.GetValue<string>("zone");
|
||||
var sceneId = mod.GetValue<string>("scene");
|
||||
|
||||
WorldInstance.AwaitScene(zoneId, sceneId, scene => ApplyToZone(mod, scene));
|
||||
}
|
||||
|
||||
private void ApplyToZone(Mod mod, LvlFile scene)
|
||||
{
|
||||
if (scene.LevelObjects == null)
|
||||
{
|
||||
scene.LevelObjects = new LevelObjects(scene.LvlVersion);
|
||||
}
|
||||
|
||||
var zoneId = mod.GetValue<string>("zone");
|
||||
|
||||
var instance = WorldInstance.Get(zoneId);
|
||||
|
||||
LevelObjectTemplate levelObjectTemplate;
|
||||
|
||||
switch (mod.Action)
|
||||
{
|
||||
case "add":
|
||||
{
|
||||
levelObjectTemplate = new LevelObjectTemplate(scene.LvlVersion);
|
||||
|
||||
levelObjectTemplate.ObjectId = instance.ClaimId();
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
throw new Exception($"Unknown action {mod.Action} for world-object");
|
||||
} break;
|
||||
}
|
||||
|
||||
var template = mod.GetValue<LevelTemplate>("template");
|
||||
|
||||
ModContext.AwaitId(template.Id, lot =>
|
||||
{
|
||||
levelObjectTemplate.Lot = lot;
|
||||
});
|
||||
|
||||
levelObjectTemplate.Position = template.Position;
|
||||
levelObjectTemplate.Rotation = template.Rotation;
|
||||
levelObjectTemplate.Scale = template.Scale ?? 1;
|
||||
levelObjectTemplate.AssetType = (uint) (template.Type ?? 1);
|
||||
levelObjectTemplate.GlomId = 1;
|
||||
|
||||
var dataString = new StringBuilder();
|
||||
|
||||
var ids = new List<string>();
|
||||
|
||||
foreach (var (_, dataValue) in template.Data)
|
||||
{
|
||||
var value = dataValue.ObjectValue ?? "";
|
||||
|
||||
if (dataValue.Type == FieldType.Object)
|
||||
{
|
||||
ids.Add(value.ToString()!);
|
||||
}
|
||||
}
|
||||
|
||||
ModContext.AwaitMultiple(ids.ToArray(), () =>
|
||||
{
|
||||
foreach (var (dataKey, dataValue) in template.Data)
|
||||
{
|
||||
var type = dataValue.TypeId;
|
||||
var value = dataValue.ObjectValue ?? "";
|
||||
|
||||
if (value is true) value = 1;
|
||||
if (value is false) value = 0;
|
||||
if (dataValue.Type == FieldType.Object)
|
||||
{
|
||||
value = ModContext.AssertId(value.ToString()!);
|
||||
type = 1;
|
||||
}
|
||||
|
||||
var strValue = value.ToString()!;
|
||||
|
||||
if (dataValue.Type == FieldType.Position)
|
||||
{
|
||||
if (dataValue.Value.TryGetValue(out string? _))
|
||||
{
|
||||
strValue = strValue.Replace("<", "").Replace(">", "").Replace(" ", "");
|
||||
var split = strValue.Split(',');
|
||||
strValue = $"{split[0]}\u001F{split[1]}\u001F{split[2]}";
|
||||
}
|
||||
else
|
||||
{
|
||||
var obj = dataValue.Value.ToDictionary();
|
||||
strValue = $"{obj["X"]}\u001F{obj["Y"]}\u001F{obj["Z"]}";
|
||||
}
|
||||
}
|
||||
else if (dataValue.Type == FieldType.Rotation)
|
||||
{
|
||||
if (dataValue.Value.TryGetValue(out string? _))
|
||||
{
|
||||
strValue = strValue.Replace("<", "").Replace(">", "").Replace(" ", "");
|
||||
var split = strValue.Split(',');
|
||||
strValue = $"{split[0]}\u001F{split[1]}\u001F{split[2]}\u001F{split[3]}";
|
||||
}
|
||||
else
|
||||
{
|
||||
var obj = dataValue.Value.ToDictionary();
|
||||
strValue = $"{obj["X"]}\u001F{obj["Y"]}\u001F{obj["Z"]}\u001F{obj["W"]}";
|
||||
}
|
||||
}
|
||||
|
||||
if (strValue == "True") strValue = "1";
|
||||
else if (strValue == "False") strValue = "0";
|
||||
|
||||
dataString.Append($"{dataKey}={type}:{strValue}\n");
|
||||
}
|
||||
|
||||
if (dataString.Length > 0)
|
||||
{
|
||||
dataString.Length -= 1;
|
||||
|
||||
levelObjectTemplate.LegoInfo = LegoDataDictionary.FromString(dataString.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
levelObjectTemplate.LegoInfo = new LegoDataDictionary();
|
||||
}
|
||||
|
||||
// Resize and add the object
|
||||
var levelObjectsTemplates = scene.LevelObjects.Templates;
|
||||
Array.Resize(ref levelObjectsTemplates, levelObjectsTemplates.Length + 1);
|
||||
levelObjectsTemplates[^1] = levelObjectTemplate;
|
||||
scene.LevelObjects.Templates = levelObjectsTemplates;
|
||||
});
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -172,8 +172,8 @@ namespace InfectedRose.Lvl
|
||||
var str = value switch
|
||||
{
|
||||
Vector2 vec2 => $"{vec2.X}{InfoSeparator}{vec2.Y}",
|
||||
Vector3 vec3 => $"{vec3.X}{InfoSeparator}{vec3.Z}{InfoSeparator}{vec3.Y}",
|
||||
Vector4 vec4 => $"{vec4.X}{InfoSeparator}{vec4.Z}{InfoSeparator}{vec4.Y}{InfoSeparator}{vec4.W}",
|
||||
Vector3 vec3 => $"{vec3.X}{InfoSeparator}{vec3.Y}{InfoSeparator}{vec3.Z}",
|
||||
Vector4 vec4 => $"{vec4.X}{InfoSeparator}{vec4.Y}{InfoSeparator}{vec4.Z}{InfoSeparator}{vec4.W}",
|
||||
LegoDataList list => list.ToString(),
|
||||
_ => value.ToString()
|
||||
};
|
||||
@@ -198,8 +198,8 @@ namespace InfectedRose.Lvl
|
||||
var val = v switch
|
||||
{
|
||||
Vector2 vec2 => $"{vec2.X}{InfoSeparator}{vec2.Y}",
|
||||
Vector3 vec3 => $"{vec3.X}{InfoSeparator}{vec3.Z}{InfoSeparator}{vec3.Y}",
|
||||
Vector4 vec4 => $"{vec4.X}{InfoSeparator}{vec4.Z}{InfoSeparator}{vec4.Y}{InfoSeparator}{vec4.W}",
|
||||
Vector3 vec3 => $"{vec3.X}{InfoSeparator}{vec3.Y}{InfoSeparator}{vec3.Z}",
|
||||
Vector4 vec4 => $"{vec4.X}{InfoSeparator}{vec4.Y}{InfoSeparator}{vec4.Z}{InfoSeparator}{vec4.W}",
|
||||
LegoDataList list => list.ToString(),
|
||||
false => "0",
|
||||
true => "1",
|
||||
|
||||
@@ -113,11 +113,11 @@ namespace InfectedRose.Lvl
|
||||
break;
|
||||
|
||||
case Vector3 vec3:
|
||||
val = $"{vec3.X}{InfoSeparator}{vec3.Z}{InfoSeparator}{vec3.Y}";
|
||||
val = $"{vec3.X}{InfoSeparator}{vec3.Y}{InfoSeparator}{vec3.Z}";
|
||||
break;
|
||||
|
||||
case Vector4 vec4:
|
||||
val = $"{vec4.X}{InfoSeparator}{vec4.Z}{InfoSeparator}{vec4.Y}{InfoSeparator}{vec4.W}";
|
||||
val = $"{vec4.X}{InfoSeparator}{vec4.Y}{InfoSeparator}{vec4.Z}{InfoSeparator}{vec4.W}";
|
||||
break;
|
||||
|
||||
case LegoDataList list:
|
||||
|
||||
@@ -40,6 +40,8 @@ namespace InfectedRose.Lvl
|
||||
{
|
||||
writer.Write<ushort>(0);
|
||||
}
|
||||
|
||||
writer.WriteNiString(Config, true);
|
||||
}
|
||||
|
||||
public void Deserialize(BitReader reader)
|
||||
@@ -59,6 +61,8 @@ namespace InfectedRose.Lvl
|
||||
{
|
||||
reader.Read<ushort>();
|
||||
}
|
||||
|
||||
Config = reader.ReadNiString(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,222 +4,220 @@ using InfectedRose.Luz;
|
||||
using InfectedRose.Lvl;
|
||||
using RakDotNet.IO;
|
||||
|
||||
namespace InfectedRose.Utilities
|
||||
namespace InfectedRose.Utilities;
|
||||
|
||||
public static class Checksum
|
||||
{
|
||||
public static class Checksum
|
||||
/// <summary>
|
||||
/// Calculate the checksum for a LEGO Universe zone
|
||||
/// </summary>
|
||||
/// <param name="zone">Path to zone file</param>
|
||||
/// <returns>Calculated checksum</returns>
|
||||
public static uint Generate(string zone)
|
||||
{
|
||||
/// <summary>
|
||||
/// Calculate the checksum for a LEGO Universe zone
|
||||
/// </summary>
|
||||
/// <param name="zone">Path to zone file</param>
|
||||
/// <returns>Calculated checksum</returns>
|
||||
public static uint Generate(string zone)
|
||||
{
|
||||
uint value = ushort.MaxValue; // For checksum calculations
|
||||
uint total = ushort.MaxValue; // Sum of all changes applied to value
|
||||
uint value = ushort.MaxValue; // For checksum calculations
|
||||
uint total = ushort.MaxValue; // Sum of all changes applied to value
|
||||
|
||||
//
|
||||
// Read zone file
|
||||
//
|
||||
//
|
||||
// Read zone file
|
||||
//
|
||||
|
||||
var luz = new LuzFile();
|
||||
var luz = new LuzFile();
|
||||
|
||||
using (var stream = File.OpenRead(zone))
|
||||
using (var stream = File.OpenRead(zone))
|
||||
{
|
||||
using var reader = new BitReader(stream);
|
||||
|
||||
luz.Deserialize(reader);
|
||||
}
|
||||
|
||||
//
|
||||
// Apply zone layer
|
||||
//
|
||||
|
||||
var zoneLayer = new ChecksumLayer
|
||||
{
|
||||
Id = uint.MaxValue,
|
||||
Layer = default,
|
||||
Revision = luz.RevisionNumber
|
||||
};
|
||||
|
||||
zoneLayer.Apply(ref value, ref total);
|
||||
|
||||
//
|
||||
// Get layers for scenes
|
||||
//
|
||||
|
||||
var root = Path.GetDirectoryName(zone);
|
||||
|
||||
var sceneLayers = new ChecksumLayer[luz.Scenes.Length];
|
||||
|
||||
for (var index = 0; index < luz.Scenes.Length; index++)
|
||||
{
|
||||
var scene = luz.Scenes[index];
|
||||
|
||||
//
|
||||
// Read scene (level) file
|
||||
//
|
||||
|
||||
var lvl = new LvlFile();
|
||||
|
||||
using (var stream = File.OpenRead(Path.Combine(root, scene.FileName)))
|
||||
{
|
||||
using var reader = new BitReader(stream);
|
||||
|
||||
luz.Deserialize(reader);
|
||||
lvl.Deserialize(reader);
|
||||
}
|
||||
|
||||
//
|
||||
// Apply zone layer
|
||||
// Get revision
|
||||
//
|
||||
|
||||
var zoneLayer = new ChecksumLayer
|
||||
|
||||
var revision = lvl.LevelInfo?.RevisionNumber ?? lvl.OldLevelHeader.Revision;
|
||||
|
||||
//
|
||||
// Get layer
|
||||
//
|
||||
|
||||
sceneLayers[index] = new ChecksumLayer
|
||||
{
|
||||
Id = uint.MaxValue,
|
||||
Layer = default,
|
||||
Revision = luz.RevisionNumber
|
||||
Id = scene.SceneId,
|
||||
Layer = scene.LayerId,
|
||||
Revision = revision
|
||||
};
|
||||
|
||||
zoneLayer.Apply(ref value, ref total);
|
||||
|
||||
//
|
||||
// Get layers for scenes
|
||||
//
|
||||
|
||||
var root = Path.GetDirectoryName(zone);
|
||||
|
||||
var sceneLayers = new ChecksumLayer[luz.Scenes.Length];
|
||||
|
||||
for (var index = 0; index < luz.Scenes.Length; index++)
|
||||
{
|
||||
var scene = luz.Scenes[index];
|
||||
|
||||
//
|
||||
// Read scene (level) file
|
||||
//
|
||||
|
||||
var lvl = new LvlFile();
|
||||
|
||||
using (var stream = File.OpenRead(Path.Combine(root, scene.FileName)))
|
||||
{
|
||||
using var reader = new BitReader(stream);
|
||||
|
||||
lvl.Deserialize(reader);
|
||||
}
|
||||
|
||||
//
|
||||
// Get revision
|
||||
//
|
||||
|
||||
var revision = lvl.LevelInfo?.RevisionNumber ?? lvl.OldLevelHeader.Revision;
|
||||
|
||||
//
|
||||
// Get layer
|
||||
//
|
||||
|
||||
sceneLayers[index] = new ChecksumLayer
|
||||
{
|
||||
Id = scene.SceneId,
|
||||
Layer = scene.LayerId,
|
||||
Revision = revision
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Apply scene layers
|
||||
//
|
||||
|
||||
foreach (var layer in sceneLayers)
|
||||
{
|
||||
layer.Apply(ref value, ref total);
|
||||
}
|
||||
|
||||
//
|
||||
// Get final checksum
|
||||
//
|
||||
|
||||
var lower = (ushort) ((value & ushort.MaxValue) + (value >> 16));
|
||||
var upper = (ushort) ((total & ushort.MaxValue) + (total >> 16));
|
||||
|
||||
//
|
||||
// The checksum has two parts, one for the 'total', and one for the 'value', these combine to form a 32bit value
|
||||
//
|
||||
|
||||
return (uint) (upper << 16 | lower);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the checksum for a LEGO Universe zone
|
||||
/// </summary>
|
||||
/// <param name="zone">Path to zone file</param>
|
||||
/// <returns>Calculated checksum</returns>
|
||||
public static async Task<uint> GenerateAsync(string zone)
|
||||
|
||||
//
|
||||
// Apply scene layers
|
||||
//
|
||||
|
||||
foreach (var layer in sceneLayers)
|
||||
{
|
||||
uint value = ushort.MaxValue; // For checksum calculations
|
||||
uint total = ushort.MaxValue; // Sum of all changes applied to value
|
||||
|
||||
//
|
||||
// Read zone file
|
||||
//
|
||||
|
||||
var luz = new LuzFile();
|
||||
|
||||
using (var stream = File.OpenRead(zone))
|
||||
{
|
||||
using var reader = new BitReader(stream);
|
||||
|
||||
luz.Deserialize(reader);
|
||||
}
|
||||
|
||||
//
|
||||
// Apply zone layer
|
||||
//
|
||||
|
||||
var zoneLayer = new ChecksumLayer
|
||||
{
|
||||
Id = uint.MaxValue,
|
||||
Layer = default,
|
||||
Revision = luz.RevisionNumber
|
||||
};
|
||||
|
||||
zoneLayer.Apply(ref value, ref total);
|
||||
|
||||
//
|
||||
// Get layers for scenes
|
||||
//
|
||||
|
||||
var root = Path.GetDirectoryName(zone);
|
||||
|
||||
var sceneLayers = new ChecksumLayer[luz.Scenes.Length];
|
||||
|
||||
var tasks = new Task[luz.Scenes.Length];
|
||||
|
||||
for (var index = 0; index < luz.Scenes.Length; index++)
|
||||
{
|
||||
var sceneIndex = index;
|
||||
|
||||
tasks[index] = Task.Run(() =>
|
||||
{
|
||||
var scene = luz.Scenes[sceneIndex];
|
||||
|
||||
//
|
||||
// Read scene (level) file
|
||||
//
|
||||
|
||||
var lvl = new LvlFile();
|
||||
|
||||
using (var stream = File.OpenRead(Path.Combine(root, scene.FileName)))
|
||||
{
|
||||
using var reader = new BitReader(stream);
|
||||
|
||||
lvl.Deserialize(reader);
|
||||
}
|
||||
|
||||
//
|
||||
// Get revision
|
||||
//
|
||||
|
||||
var revision = lvl.LevelInfo?.RevisionNumber ?? lvl.OldLevelHeader.Revision;
|
||||
|
||||
//
|
||||
// Get layer
|
||||
//
|
||||
|
||||
sceneLayers[sceneIndex] = new ChecksumLayer
|
||||
{
|
||||
Id = scene.SceneId,
|
||||
Layer = scene.LayerId,
|
||||
Revision = revision
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
//
|
||||
// Apply scene layers
|
||||
//
|
||||
|
||||
foreach (var layer in sceneLayers)
|
||||
{
|
||||
layer.Apply(ref value, ref total);
|
||||
}
|
||||
|
||||
//
|
||||
// Get final checksum
|
||||
//
|
||||
|
||||
var lower = (ushort) ((value & ushort.MaxValue) + (value >> 16));
|
||||
var upper = (ushort) ((total & ushort.MaxValue) + (total >> 16));
|
||||
|
||||
//
|
||||
// The checksum has two parts, one for the 'total', and one for the 'value', these combine to form a 32bit value
|
||||
//
|
||||
|
||||
return (uint) (upper << 16 | lower);
|
||||
layer.Apply(ref value, ref total);
|
||||
}
|
||||
|
||||
//
|
||||
// Get final checksum
|
||||
//
|
||||
|
||||
var lower = (ushort) ((value & ushort.MaxValue) + (value >> 16));
|
||||
var upper = (ushort) ((total & ushort.MaxValue) + (total >> 16));
|
||||
|
||||
//
|
||||
// The checksum has two parts, one for the 'total', and one for the 'value', these combine to form a 32bit value
|
||||
//
|
||||
|
||||
return (uint) (upper << 16 | lower);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the checksum for a LEGO Universe zone
|
||||
/// </summary>
|
||||
/// <param name="zone">Path to zone file</param>
|
||||
/// <returns>Calculated checksum</returns>
|
||||
public static async Task<uint> GenerateAsync(string zone)
|
||||
{
|
||||
uint value = ushort.MaxValue; // For checksum calculations
|
||||
uint total = ushort.MaxValue; // Sum of all changes applied to value
|
||||
|
||||
//
|
||||
// Read zone file
|
||||
//
|
||||
|
||||
var luz = new LuzFile();
|
||||
|
||||
using (var stream = File.OpenRead(zone))
|
||||
{
|
||||
using var reader = new BitReader(stream);
|
||||
|
||||
luz.Deserialize(reader);
|
||||
}
|
||||
|
||||
//
|
||||
// Apply zone layer
|
||||
//
|
||||
|
||||
var zoneLayer = new ChecksumLayer
|
||||
{
|
||||
Id = uint.MaxValue,
|
||||
Layer = default,
|
||||
Revision = luz.RevisionNumber
|
||||
};
|
||||
|
||||
zoneLayer.Apply(ref value, ref total);
|
||||
|
||||
//
|
||||
// Get layers for scenes
|
||||
//
|
||||
|
||||
var root = Path.GetDirectoryName(zone);
|
||||
|
||||
var sceneLayers = new ChecksumLayer[luz.Scenes.Length];
|
||||
|
||||
var tasks = new Task[luz.Scenes.Length];
|
||||
|
||||
for (var index = 0; index < luz.Scenes.Length; index++)
|
||||
{
|
||||
var sceneIndex = index;
|
||||
|
||||
tasks[index] = Task.Run(() =>
|
||||
{
|
||||
var scene = luz.Scenes[sceneIndex];
|
||||
|
||||
//
|
||||
// Read scene (level) file
|
||||
//
|
||||
|
||||
var lvl = new LvlFile();
|
||||
|
||||
using (var stream = File.OpenRead(Path.Combine(root, scene.FileName)))
|
||||
{
|
||||
using var reader = new BitReader(stream);
|
||||
|
||||
lvl.Deserialize(reader);
|
||||
}
|
||||
|
||||
//
|
||||
// Get revision
|
||||
//
|
||||
|
||||
var revision = lvl.LevelInfo?.RevisionNumber ?? lvl.OldLevelHeader.Revision;
|
||||
|
||||
//
|
||||
// Get layer
|
||||
//
|
||||
|
||||
sceneLayers[sceneIndex] = new ChecksumLayer
|
||||
{
|
||||
Id = scene.SceneId,
|
||||
Layer = scene.LayerId,
|
||||
Revision = revision
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
//
|
||||
// Apply scene layers
|
||||
//
|
||||
|
||||
foreach (var layer in sceneLayers)
|
||||
{
|
||||
layer.Apply(ref value, ref total);
|
||||
}
|
||||
|
||||
//
|
||||
// Get final checksum
|
||||
//
|
||||
|
||||
var lower = (ushort) ((value & ushort.MaxValue) + (value >> 16));
|
||||
var upper = (ushort) ((total & ushort.MaxValue) + (total >> 16));
|
||||
|
||||
//
|
||||
// The checksum has two parts, one for the 'total', and one for the 'value', these combine to form a 32bit value
|
||||
//
|
||||
|
||||
return (uint) (upper << 16 | lower);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,24 @@
|
||||
namespace InfectedRose.Utilities
|
||||
namespace InfectedRose.Utilities;
|
||||
|
||||
internal struct ChecksumLayer
|
||||
{
|
||||
internal struct ChecksumLayer
|
||||
internal uint Id { get; set; }
|
||||
|
||||
internal uint Layer { get; set; }
|
||||
|
||||
internal uint Revision { get; set; }
|
||||
|
||||
internal void Apply(ref uint value, ref uint total)
|
||||
{
|
||||
internal uint Id { get; set; }
|
||||
|
||||
internal uint Layer { get; set; }
|
||||
|
||||
internal uint Revision { get; set; }
|
||||
|
||||
internal void Apply(ref uint value, ref uint total)
|
||||
foreach (var reference in new[] {Id, Layer, Revision})
|
||||
{
|
||||
foreach (var reference in new[] {Id, Layer, Revision})
|
||||
{
|
||||
value += reference >> 16; // Apply reference
|
||||
value += reference >> 16; // Apply reference
|
||||
|
||||
total += value; // Add to total
|
||||
total += value; // Add to total
|
||||
|
||||
value += reference & ushort.MaxValue; // Make ushort
|
||||
value += reference & ushort.MaxValue; // Make ushort
|
||||
|
||||
total += value; // Add to total
|
||||
}
|
||||
total += value; // Add to total
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,66 +3,65 @@ using System.Collections.Generic;
|
||||
using InfectedRose.Luz;
|
||||
using InfectedRose.Lvl;
|
||||
|
||||
namespace InfectedRose.Utilities
|
||||
namespace InfectedRose.Utilities;
|
||||
|
||||
public static class LuzFileExtensions
|
||||
{
|
||||
public static class LuzFileExtensions
|
||||
public static uint GenerateChecksum(this LuzFile @this, List<LvlFile> scenes)
|
||||
{
|
||||
public static uint GenerateChecksum(this LuzFile @this, List<LvlFile> scenes)
|
||||
if (@this.Scenes.Length != scenes.Count)
|
||||
{
|
||||
if (@this.Scenes.Length != scenes.Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(scenes), "The count of scenes has to equal the count of scenes in this luz file.");
|
||||
}
|
||||
throw new ArgumentOutOfRangeException(nameof(scenes), "The count of scenes has to equal the count of scenes in this luz file.");
|
||||
}
|
||||
|
||||
uint value = ushort.MaxValue; // For checksum calculations
|
||||
uint total = ushort.MaxValue; // Sum of all changes applied to value
|
||||
uint value = ushort.MaxValue; // For checksum calculations
|
||||
uint total = ushort.MaxValue; // Sum of all changes applied to value
|
||||
|
||||
var zoneLayer = new ChecksumLayer
|
||||
var zoneLayer = new ChecksumLayer
|
||||
{
|
||||
Id = uint.MaxValue,
|
||||
Layer = default,
|
||||
Revision = @this.RevisionNumber
|
||||
};
|
||||
|
||||
zoneLayer.Apply(ref value, ref total);
|
||||
|
||||
for (var index = 0; index < scenes.Count; index++)
|
||||
{
|
||||
var scene = scenes[index];
|
||||
var lvl = @this.Scenes[index];
|
||||
|
||||
//
|
||||
// Get revision
|
||||
//
|
||||
|
||||
var revision = scene.LevelInfo?.RevisionNumber ?? scene.OldLevelHeader.Revision;
|
||||
|
||||
//
|
||||
// Get layer
|
||||
//
|
||||
|
||||
var sceneLayer = new ChecksumLayer
|
||||
{
|
||||
Id = uint.MaxValue,
|
||||
Layer = default,
|
||||
Revision = @this.RevisionNumber
|
||||
Id = lvl.SceneId,
|
||||
Layer = lvl.LayerId,
|
||||
Revision = revision
|
||||
};
|
||||
|
||||
zoneLayer.Apply(ref value, ref total);
|
||||
|
||||
for (var index = 0; index < scenes.Count; index++)
|
||||
{
|
||||
var scene = scenes[index];
|
||||
var lvl = @this.Scenes[index];
|
||||
|
||||
//
|
||||
// Get revision
|
||||
//
|
||||
|
||||
var revision = scene.LevelInfo?.RevisionNumber ?? scene.OldLevelHeader.Revision;
|
||||
|
||||
//
|
||||
// Get layer
|
||||
//
|
||||
|
||||
var sceneLayer = new ChecksumLayer
|
||||
{
|
||||
Id = lvl.SceneId,
|
||||
Layer = lvl.LayerId,
|
||||
Revision = revision
|
||||
};
|
||||
|
||||
sceneLayer.Apply(ref value, ref total);
|
||||
}
|
||||
|
||||
//
|
||||
// Get final checksum
|
||||
//
|
||||
|
||||
var lower = (ushort) ((value & ushort.MaxValue) + (value >> 16));
|
||||
var upper = (ushort) ((total & ushort.MaxValue) + (total >> 16));
|
||||
|
||||
//
|
||||
// The checksum has two parts, one for the 'total', and one for the 'value', these combine to form a 32bit value
|
||||
//
|
||||
|
||||
return (uint) (upper << 16 | lower);
|
||||
sceneLayer.Apply(ref value, ref total);
|
||||
}
|
||||
|
||||
//
|
||||
// Get final checksum
|
||||
//
|
||||
|
||||
var lower = (ushort) ((value & ushort.MaxValue) + (value >> 16));
|
||||
var upper = (ushort) ((total & ushort.MaxValue) + (total >> 16));
|
||||
|
||||
//
|
||||
// The checksum has two parts, one for the 'total', and one for the 'value', these combine to form a 32bit value
|
||||
//
|
||||
|
||||
return (uint) (upper << 16 | lower);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user