namespace change xd

This commit is contained in:
XtraCube committed 2024-08-19 17:19:43 -04:00
1 parent 4f01facd7c
commit 730b22f7ce
35 files changed
+1180 -1208

No files matched your search

+12 -13
View File
@@ -3,19 +3,18 @@ using MiraAPI.Roles;
using MiraAPI.Utilities.Assets;
using UnityEngine;
namespace MiraAPI.Example
namespace MiraAPI.Example;
[RegisterCustomRole]
public class CustomRole : ImpostorRole, ICustomRole
{
[RegisterCustomRole]
public class CustomRole : ImpostorRole, ICustomRole
{
public string RoleName => "fortnite killer";
public string RoleLongDescription => "ok so your objective is to eliminate everyone with your fortnite tactical shotgun, good luck";
public string RoleDescription => RoleLongDescription;
public Color RoleColor => Palette.Orange;
public ModdedRoleTeams Team => ModdedRoleTeams.Impostor;
public LoadableAsset<Sprite> OptionsScreenshot => MiraAssets.Banner;
public string RoleName => "fortnite killer";
public string RoleLongDescription => "ok so your objective is to eliminate everyone with your fortnite tactical shotgun, good luck";
public string RoleDescription => RoleLongDescription;
public Color RoleColor => Palette.Orange;
public ModdedRoleTeams Team => ModdedRoleTeams.Impostor;
public LoadableAsset<Sprite> OptionsScreenshot => MiraAssets.Banner;
[ModdedNumberOption("Testing level", min: 3, max: 9, roleType: typeof(CustomRole))] public float testingLevel { get; set; } = 4;
[ModdedNumberOption("Testing level", min: 3, max: 9, roleType: typeof(CustomRole))] public float testingLevel { get; set; } = 4;
}
}
}
+12 -13
View File
@@ -3,19 +3,18 @@ using MiraAPI.Roles;
using MiraAPI.Utilities.Assets;
using UnityEngine;
namespace MiraAPI.Example
namespace MiraAPI.Example;
[RegisterCustomRole]
public class CustomRole2 : CrewmateRole, ICustomRole
{
[RegisterCustomRole]
public class CustomRole2 : CrewmateRole, ICustomRole
{
public string RoleName => "fortnite defender";
public string RoleLongDescription => "ok so your objective is to save everyone from the fortnite killer";
public string RoleDescription => RoleLongDescription;
public Color RoleColor => Palette.AcceptedGreen;
public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate;
public LoadableAsset<Sprite> OptionsScreenshot => MiraAssets.Banner;
public string RoleName => "fortnite defender";
public string RoleLongDescription => "ok so your objective is to save everyone from the fortnite killer";
public string RoleDescription => RoleLongDescription;
public Color RoleColor => Palette.AcceptedGreen;
public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate;
public LoadableAsset<Sprite> OptionsScreenshot => MiraAssets.Banner;
[ModdedToggleOption("Teleportation ability", roleType: typeof(CustomRole2))] public bool teleport { get; set; } = true;
[ModdedToggleOption("Teleportation ability", roleType: typeof(CustomRole2))] public bool teleport { get; set; } = true;
}
}
}
+12 -13
View File
@@ -2,17 +2,16 @@
using MiraAPI.Utilities.Assets;
using UnityEngine;
namespace MiraAPI.Example
{
[RegisterCustomRole]
public class CustomRole3 : CrewmateRole, ICustomRole
{
public string RoleName => "fortnite helper";
public string RoleLongDescription => "ok so your objective is to help";
public string RoleDescription => RoleLongDescription;
public Color RoleColor => Palette.Brown;
public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate;
public LoadableAsset<Sprite> OptionsScreenshot => MiraAssets.Banner;
namespace MiraAPI.Example;
}
}
[RegisterCustomRole]
public class CustomRole3 : CrewmateRole, ICustomRole
{
public string RoleName => "fortnite helper";
public string RoleLongDescription => "ok so your objective is to help";
public string RoleDescription => RoleLongDescription;
public Color RoleColor => Palette.Brown;
public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate;
public LoadableAsset<Sprite> OptionsScreenshot => MiraAssets.Banner;
}
+22 -23
View File
@@ -2,33 +2,32 @@
using MiraAPI.GameOptions.Attributes;
using UnityEngine;
namespace MiraAPI.Example
namespace MiraAPI.Example;
public class ExampleOptions : IModdedOptionGroup
{
public class ExampleOptions : IModdedOptionGroup
{
public string GroupName => "General Group";
public Color GroupColor => Color.red;
public string GroupName => "General Group";
public Color GroupColor => Color.red;
[ModdedToggleOption("Use Thing")]
public bool useThing { get; set; } = false;
[ModdedToggleOption("Use Thing")]
public bool useThing { get; set; } = false;
[ModdedToggleOption("Use another thing")]
public bool useAnotherThing { get; set; } = true;
[ModdedToggleOption("Use another thing")]
public bool useAnotherThing { get; set; } = true;
[ModdedNumberOption("Sussy level", min: 0, max: 10)]
public float sussyLevel { get; set; } = 4f;
[ModdedNumberOption("Sussy level", min: 0, max: 10)]
public float sussyLevel { get; set; } = 4f;
[ModdedStringOption("Sus choices", ["hello", "hello 2", "hello 3"])]
public int susChoices { get; set; } = 2;
[ModdedStringOption("Sus choices", ["hello", "hello 2", "hello 3"])]
public int susChoices { get; set; } = 2;
[ModdedEnumOption("Enum test", typeof(TestEnum))]
public TestEnum enumTest { get; set; } = TestEnum.Bye;
}
public enum TestEnum
{
Hello,
Hi,
Bye
}
[ModdedEnumOption("Enum test", typeof(TestEnum))]
public TestEnum enumTest { get; set; } = TestEnum.Bye;
}
public enum TestEnum
{
Hello,
Hi,
Bye
}
+7 -8
View File
@@ -1,9 +1,8 @@
namespace MiraAPI.Example
{
public class ModifierExample
{
//name, role specific, etc
namespace MiraAPI.Example;
// mono behaviour stuff here (ModdedPlayerModifier inherits monobehaviour)
}
}
public class ModifierExample
{
//name, role specific, etc
// mono behaviour stuff here (ModdedPlayerModifier inherits monobehaviour)
}
+6 -7
View File
@@ -1,10 +1,9 @@
using MiraAPI.GameOptions.Attributes;
namespace MiraAPI.Example
namespace MiraAPI.Example;
public class SomeRandomNonGroupClass
{
public class SomeRandomNonGroupClass
{
[ModdedStringOption("Yeah, idk", ["Idk 1", "idk 2", "idk 3", "idk 4"])] public static int yeaIdk { get; set; } = 3;
[ModdedNumberOption("Aw man", min: 45, max: 95)] public float sussyLevel { get; set; } = 63;
}
}
[ModdedStringOption("Yeah, idk", ["Idk 1", "idk 2", "idk 3", "idk 4"])] public static int yeaIdk { get; set; } = 3;
[ModdedNumberOption("Aw man", min: 45, max: 95)] public float sussyLevel { get; set; } = 63;
}
@@ -2,32 +2,31 @@
using System;
using System.Reflection;
namespace MiraAPI.GameOptions.Attributes
namespace MiraAPI.GameOptions.Attributes;
public class ModdedEnumOptionAttribute : ModdedOptionAttribute
{
public class ModdedEnumOptionAttribute : ModdedOptionAttribute
public Type EnumType;
public ModdedEnumOptionAttribute(string title, Type enumType, Type roleType = null) : base(title, roleType)
{
public Type EnumType;
public ModdedEnumOptionAttribute(string title, Type enumType, Type roleType = null) : base(title, roleType)
{
EnumType = enumType;
}
public override IModdedOption CreateOption(object value, PropertyInfo property)
{
var opt = new ModdedEnumOption(Title, (int)value, EnumType, RoleType);
return opt;
}
public override void SetValue(object value)
{
ModdedEnumOption opt = HolderOption as ModdedEnumOption;
opt.SetValue((int)value);
}
public override object GetValue()
{
ModdedEnumOption opt = HolderOption as ModdedEnumOption;
return Enum.ToObject(EnumType.GetType(), opt.Value);
}
EnumType = enumType;
}
}
public override IModdedOption CreateOption(object value, PropertyInfo property)
{
var opt = new ModdedEnumOption(Title, (int)value, EnumType, RoleType);
return opt;
}
public override void SetValue(object value)
{
ModdedEnumOption opt = HolderOption as ModdedEnumOption;
opt.SetValue((int)value);
}
public override object GetValue()
{
ModdedEnumOption opt = HolderOption as ModdedEnumOption;
return Enum.ToObject(EnumType.GetType(), opt.Value);
}
}
@@ -2,41 +2,40 @@
using System;
using System.Reflection;
namespace MiraAPI.GameOptions.Attributes
namespace MiraAPI.GameOptions.Attributes;
public class ModdedNumberOptionAttribute : ModdedOptionAttribute
{
public class ModdedNumberOptionAttribute : ModdedOptionAttribute
public float Min { get; private set; }
public float Max { get; private set; }
public float Increment { get; private set; }
public NumberSuffixes SuffixType { get; private set; }
public bool ZeroInfinity { get; private set; }
public ModdedNumberOptionAttribute(string title, float min, float max, float increment = 1, NumberSuffixes suffixType = NumberSuffixes.None, bool zeroInfinity = false, Type roleType = null) : base(title, roleType)
{
public float Min { get; private set; }
public float Max { get; private set; }
public float Increment { get; private set; }
public NumberSuffixes SuffixType { get; private set; }
public bool ZeroInfinity { get; private set; }
public ModdedNumberOptionAttribute(string title, float min, float max, float increment = 1, NumberSuffixes suffixType = NumberSuffixes.None, bool zeroInfinity = false, Type roleType = null) : base(title, roleType)
{
Min = min;
Max = max;
Increment = increment;
SuffixType = suffixType;
ZeroInfinity = zeroInfinity;
}
public override IModdedOption CreateOption(object value, PropertyInfo property)
{
var toggleOpt = new ModdedNumberOption(Title, (float)value, Min, Max, Increment, SuffixType, ZeroInfinity, RoleType);
return toggleOpt;
}
public override void SetValue(object value)
{
ModdedNumberOption toggleOpt = HolderOption as ModdedNumberOption;
toggleOpt.SetValue((float)value);
}
public override object GetValue()
{
ModdedNumberOption toggleOpt = HolderOption as ModdedNumberOption;
return toggleOpt.Value;
}
Min = min;
Max = max;
Increment = increment;
SuffixType = suffixType;
ZeroInfinity = zeroInfinity;
}
}
public override IModdedOption CreateOption(object value, PropertyInfo property)
{
var toggleOpt = new ModdedNumberOption(Title, (float)value, Min, Max, Increment, SuffixType, ZeroInfinity, RoleType);
return toggleOpt;
}
public override void SetValue(object value)
{
ModdedNumberOption toggleOpt = HolderOption as ModdedNumberOption;
toggleOpt.SetValue((float)value);
}
public override object GetValue()
{
ModdedNumberOption toggleOpt = HolderOption as ModdedNumberOption;
return toggleOpt.Value;
}
}
@@ -1,22 +1,21 @@
using System;
using System.Reflection;
namespace MiraAPI.GameOptions.Attributes
{
[AttributeUsage(AttributeTargets.Property)]
public abstract class ModdedOptionAttribute : Attribute
{
public IModdedOption HolderOption { get; set; }
public string Title { get; private set; }
public Type RoleType { get; private set; }
public ModdedOptionAttribute(string title, Type roleType = null)
{
Title = title;
RoleType = roleType;
}
namespace MiraAPI.GameOptions.Attributes;
public abstract void SetValue(object val);
public abstract object GetValue();
public abstract IModdedOption CreateOption(object value, PropertyInfo property);
[AttributeUsage(AttributeTargets.Property)]
public abstract class ModdedOptionAttribute : Attribute
{
public IModdedOption HolderOption { get; set; }
public string Title { get; private set; }
public Type RoleType { get; private set; }
public ModdedOptionAttribute(string title, Type roleType = null)
{
Title = title;
RoleType = roleType;
}
}
public abstract void SetValue(object val);
public abstract object GetValue();
public abstract IModdedOption CreateOption(object value, PropertyInfo property);
}
@@ -2,32 +2,31 @@
using System;
using System.Reflection;
namespace MiraAPI.GameOptions.Attributes
namespace MiraAPI.GameOptions.Attributes;
public class ModdedStringOptionAttribute : ModdedOptionAttribute
{
public class ModdedStringOptionAttribute : ModdedOptionAttribute
public string[] Values;
public ModdedStringOptionAttribute(string title, string[] strings, Type roleType = null) : base(title, roleType)
{
public string[] Values;
public ModdedStringOptionAttribute(string title, string[] strings, Type roleType = null) : base(title, roleType)
{
Values = strings;
}
public override IModdedOption CreateOption(object value, PropertyInfo property)
{
var opt = new ModdedStringOption(Title, (int)value, Values, RoleType);
return opt;
}
public override void SetValue(object value)
{
ModdedStringOption opt = HolderOption as ModdedStringOption;
opt.SetValue((int)value);
}
public override object GetValue()
{
ModdedStringOption opt = HolderOption as ModdedStringOption;
return opt.Value;
}
Values = strings;
}
}
public override IModdedOption CreateOption(object value, PropertyInfo property)
{
var opt = new ModdedStringOption(Title, (int)value, Values, RoleType);
return opt;
}
public override void SetValue(object value)
{
ModdedStringOption opt = HolderOption as ModdedStringOption;
opt.SetValue((int)value);
}
public override object GetValue()
{
ModdedStringOption opt = HolderOption as ModdedStringOption;
return opt.Value;
}
}
@@ -2,30 +2,29 @@
using System;
using System.Reflection;
namespace MiraAPI.GameOptions.Attributes
namespace MiraAPI.GameOptions.Attributes;
public class ModdedToggleOptionAttribute : ModdedOptionAttribute
{
public class ModdedToggleOptionAttribute : ModdedOptionAttribute
public ModdedToggleOptionAttribute(string title, Type roleType = null) : base(title, roleType)
{
public ModdedToggleOptionAttribute(string title, Type roleType = null) : base(title, roleType)
{
}
public override IModdedOption CreateOption(object value, PropertyInfo property)
{
var toggleOpt = new ModdedToggleOption(Title, (bool)value, RoleType);
return toggleOpt;
}
public override void SetValue(object value)
{
ModdedToggleOption toggleOpt = HolderOption as ModdedToggleOption;
toggleOpt.SetValue((bool)value);
}
public override object GetValue()
{
ModdedToggleOption toggleOpt = HolderOption as ModdedToggleOption;
return toggleOpt.Value;
}
}
}
public override IModdedOption CreateOption(object value, PropertyInfo property)
{
var toggleOpt = new ModdedToggleOption(Title, (bool)value, RoleType);
return toggleOpt;
}
public override void SetValue(object value)
{
ModdedToggleOption toggleOpt = HolderOption as ModdedToggleOption;
toggleOpt.SetValue((bool)value);
}
public override object GetValue()
{
ModdedToggleOption toggleOpt = HolderOption as ModdedToggleOption;
return toggleOpt.Value;
}
}
+17 -18
View File
@@ -3,22 +3,21 @@ using System;
using MiraAPI.Networking;
using UnityEngine;
namespace MiraAPI.GameOptions
namespace MiraAPI.GameOptions;
public interface IModdedOption
{
public interface IModdedOption
{
public uint Id { get; }
public BaseGameSetting Data { get; }
public ModdedOptionGroup Group { get; set; }
public IMiraPlugin ParentMod { get; set; }
public Type AdvancedRole { get; }
public OptionBehaviour OptionBehaviour { get; protected set; }
public string Title { get; }
public StringNames StringName { get; }
public Func<bool> Visible { get; set; }
public void ValueChanged(OptionBehaviour optionBehaviour);
public OptionBehaviour CreateOption(ToggleOption toggleOpt, NumberOption numberOpt, StringOption stringOpt, Transform container);
public NetData GetNetData();
public void HandleNetData(byte[] data);
}
}
public uint Id { get; }
public BaseGameSetting Data { get; }
public ModdedOptionGroup Group { get; set; }
public IMiraPlugin ParentMod { get; set; }
public Type AdvancedRole { get; }
public OptionBehaviour OptionBehaviour { get; protected set; }
public string Title { get; }
public StringNames StringName { get; }
public Func<bool> Visible { get; set; }
public void ValueChanged(OptionBehaviour optionBehaviour);
public OptionBehaviour CreateOption(ToggleOption toggleOpt, NumberOption numberOpt, StringOption stringOpt, Transform container);
public NetData GetNetData();
public void HandleNetData(byte[] data);
}
+8 -9
View File
@@ -1,13 +1,12 @@
using System;
using UnityEngine;
namespace MiraAPI.GameOptions
namespace MiraAPI.GameOptions;
public interface IModdedOptionGroup
{
public interface IModdedOptionGroup
{
public string GroupName { get; }
public Func<bool> GroupVisible => () => true;
public Color GroupColor => Color.clear;
public Type AdvancedRole => null;
}
}
public string GroupName { get; }
public Func<bool> GroupVisible => () => true;
public Color GroupColor => Color.clear;
public Type AdvancedRole => null;
}
+12 -13
View File
@@ -1,20 +1,19 @@
using System;
using System.Linq;
namespace MiraAPI.GameOptions
{
public class ModdedGroupSingleton<T> where T : ModdedOptionGroup
{
private static T _instance;
namespace MiraAPI.GameOptions;
public static T Instance
public class ModdedGroupSingleton<T> where T : ModdedOptionGroup
{
private static T _instance;
public static T Instance
{
get => _instance ??= ModdedOptionsManager.Groups.OfType<T>().Single();
set
{
get => _instance ??= ModdedOptionsManager.Groups.OfType<T>().Single();
set
{
if (_instance != null) throw new InvalidOperationException($"Instance for {typeof(T)} is already set");
_instance = value;
}
if (_instance != null) throw new InvalidOperationException($"Instance for {typeof(T)} is already set");
_instance = value;
}
}
}
}
+10 -11
View File
@@ -2,15 +2,14 @@
using System;
using UnityEngine;
namespace MiraAPI.GameOptions
namespace MiraAPI.GameOptions;
public class ModdedOptionGroup
{
public class ModdedOptionGroup
{
public IMiraPlugin ParentMod;
public GameObject Header;
public string GroupName;
public Func<bool> GroupVisible;
public Color GroupColor;
public Type AdvancedRole;
}
}
public IMiraPlugin ParentMod;
public GameObject Header;
public string GroupName;
public Func<bool> GroupVisible;
public Color GroupColor;
public Type AdvancedRole;
}
+80 -81
View File
@@ -8,104 +8,103 @@ using System.Reflection;
using MiraAPI.Networking;
using Reactor.Networking.Rpc;
namespace MiraAPI.GameOptions
namespace MiraAPI.GameOptions;
public class ModdedOptionsManager
{
public class ModdedOptionsManager
public static readonly Dictionary<uint, IModdedOption> ModdedOptions = new();
public static readonly List<IModdedOption> Options = [];
public static readonly List<ModdedOptionGroup> Groups = [];
private static readonly Dictionary<PropertyInfo, ModdedOptionAttribute> OptionAttributes = new();
public static readonly Dictionary<Type, ModdedOptionGroup> OriginalTypes = new();
public static uint NextId = 1;
public static IModdedOption RegisterOption(Type type, ModdedOptionAttribute attribute, PropertyInfo property)
{
public static readonly Dictionary<uint, IModdedOption> ModdedOptions = new();
public static readonly List<IModdedOption> Options = [];
public static readonly List<ModdedOptionGroup> Groups = [];
private static readonly Dictionary<PropertyInfo, ModdedOptionAttribute> OptionAttributes = new();
public static readonly Dictionary<Type, ModdedOptionGroup> OriginalTypes = new();
public static uint NextId = 1;
if (OptionAttributes.ContainsKey(property)) return null;
object newObj = Activator.CreateInstance(type);
IModdedOption result = attribute.CreateOption(property.GetValue(newObj), property);
public static IModdedOption RegisterOption(Type type, ModdedOptionAttribute attribute, PropertyInfo property)
if (result != null)
{
if (OptionAttributes.ContainsKey(property)) return null;
object newObj = Activator.CreateInstance(type);
IModdedOption result = attribute.CreateOption(property.GetValue(newObj), property);
var setterOriginal = property.GetSetMethod();
var setterPatch = typeof(ModdedOptionsManager).GetMethod(nameof(PropertySetterPatch));
PluginSingleton<MiraApiPlugin>.Instance.Harmony.Patch(setterOriginal, postfix: new HarmonyMethod(setterPatch));
if (result != null)
{
var setterOriginal = property.GetSetMethod();
var setterPatch = typeof(ModdedOptionsManager).GetMethod(nameof(PropertySetterPatch));
PluginSingleton<MiraApiPlugin>.Instance.Harmony.Patch(setterOriginal, postfix: new HarmonyMethod(setterPatch));
var getterOriginal = property.GetGetMethod();
var getterPatch = typeof(ModdedOptionsManager).GetMethod(nameof(PropertyGetterPatch));
PluginSingleton<MiraApiPlugin>.Instance.Harmony.Patch(getterOriginal, prefix: new HarmonyMethod(getterPatch));
var getterOriginal = property.GetGetMethod();
var getterPatch = typeof(ModdedOptionsManager).GetMethod(nameof(PropertyGetterPatch));
PluginSingleton<MiraApiPlugin>.Instance.Harmony.Patch(getterOriginal, prefix: new HarmonyMethod(getterPatch));
attribute.HolderOption = result;
attribute.HolderOption = result;
OptionAttributes.Add(property, attribute);
OptionAttributes.Add(property, attribute);
if (OriginalTypes.ContainsKey(type))
{
Logger<MiraApiPlugin>.Error($"Grouping {attribute.Title} with {OriginalTypes[type].GroupName}");
result.Group = OriginalTypes[type];
}
if (OriginalTypes.ContainsKey(type))
{
Logger<MiraApiPlugin>.Error($"Grouping {attribute.Title} with {OriginalTypes[type].GroupName}");
result.Group = OriginalTypes[type];
}
return result;
}
public static void SyncAllOptions(int targetId=-1)
return result;
}
public static void SyncAllOptions(int targetId=-1)
{
List<NetData> data = [];
int count = 0;
foreach (var option in ModdedOptions.Values)
{
List<NetData> data = [];
int count = 0;
foreach (var option in ModdedOptions.Values)
{
var netData = option.GetNetData();
data.Add(netData);
count += netData.GetLength();
var netData = option.GetNetData();
data.Add(netData);
count += netData.GetLength();
if (count > 1000)
{
Rpc<SyncOptionsRpc>.Instance.SendTo(PlayerControl.LocalPlayer, targetId, data.ToArray());
data.Clear();
count = 0;
}
}
if (data.Count > 0)
if (count > 1000)
{
Rpc<SyncOptionsRpc>.Instance.SendTo(PlayerControl.LocalPlayer, targetId, data.ToArray());
data.Clear();
count = 0;
}
}
public static void HandleSyncOptions(NetData[] data)
if (data.Count > 0)
{
foreach (var netData in data)
{
if (ModdedOptions.TryGetValue(netData.Id, out var option))
{
Logger<MiraApiPlugin>.Error("Handling option " + option.Title);
option.HandleNetData(netData.Data);
}
}
}
public static void PropertySetterPatch(MethodBase __originalMethod, object value)
{
ModdedOptionAttribute attribute = OptionAttributes.First(pair => pair.Key.GetSetMethod().Equals(__originalMethod)).Value;
if (attribute != null)
{
attribute.SetValue(value);
}
}
public static bool PropertyGetterPatch(MethodBase __originalMethod, ref object __result)
{
ModdedOptionAttribute attribute = OptionAttributes.First(pair => pair.Key.GetGetMethod().Equals(__originalMethod)).Value;
if (attribute != null)
{
__result = attribute.GetValue();
return false;
}
return true;
Rpc<SyncOptionsRpc>.Instance.SendTo(PlayerControl.LocalPlayer, targetId, data.ToArray());
}
}
}
public static void HandleSyncOptions(NetData[] data)
{
foreach (var netData in data)
{
if (ModdedOptions.TryGetValue(netData.Id, out var option))
{
Logger<MiraApiPlugin>.Error("Handling option " + option.Title);
option.HandleNetData(netData.Data);
}
}
}
public static void PropertySetterPatch(MethodBase __originalMethod, object value)
{
ModdedOptionAttribute attribute = OptionAttributes.First(pair => pair.Key.GetSetMethod().Equals(__originalMethod)).Value;
if (attribute != null)
{
attribute.SetValue(value);
}
}
public static bool PropertyGetterPatch(MethodBase __originalMethod, ref object __result)
{
ModdedOptionAttribute attribute = OptionAttributes.First(pair => pair.Key.GetGetMethod().Equals(__originalMethod)).Value;
if (attribute != null)
{
__result = attribute.GetValue();
return false;
}
return true;
}
}
@@ -5,71 +5,70 @@ using MiraAPI.Networking;
using UnityEngine;
using Object = UnityEngine.Object;
namespace MiraAPI.GameOptions.OptionTypes
namespace MiraAPI.GameOptions.OptionTypes;
public class ModdedEnumOption : ModdedOption<int>
{
public class ModdedEnumOption : ModdedOption<int>
public ModdedEnumOption(string title, int defaultValue, Type enumType, Type roleType) : base(title, defaultValue, roleType)
{
public ModdedEnumOption(string title, int defaultValue, Type enumType, Type roleType) : base(title, defaultValue, roleType)
{
Values = Enum.GetNames(enumType);
Data = ScriptableObject.CreateInstance<StringGameSetting>();
var data = (StringGameSetting)Data;
Values = Enum.GetNames(enumType);
Data = ScriptableObject.CreateInstance<StringGameSetting>();
var data = (StringGameSetting)Data;
data.Title = StringName;
data.Type = global::OptionTypes.String;
data.Values = Values.Select(CustomStringName.CreateAndRegister).ToArray();
data.Index = Value;
}
data.Title = StringName;
data.Type = global::OptionTypes.String;
data.Values = Values.Select(CustomStringName.CreateAndRegister).ToArray();
data.Index = Value;
}
public string[] Values { get; set; }
public string[] Values { get; set; }
public override OptionBehaviour CreateOption(ToggleOption toggleOpt, NumberOption numberOpt, StringOption stringOpt, Transform container)
{
var stringOption = Object.Instantiate(stringOpt, container);
public override OptionBehaviour CreateOption(ToggleOption toggleOpt, NumberOption numberOpt, StringOption stringOpt, Transform container)
{
var stringOption = Object.Instantiate(stringOpt, container);
stringOption.SetUpFromData(Data, 20);
stringOption.OnValueChanged = (Il2CppSystem.Action<OptionBehaviour>)ValueChanged;
stringOption.SetUpFromData(Data, 20);
stringOption.OnValueChanged = (Il2CppSystem.Action<OptionBehaviour>)ValueChanged;
// SetUpFromData method doesnt work correctly so we must set the values manually
stringOption.Title = StringName;
stringOption.Values = ((StringGameSetting)Data).Values;
stringOption.Value = Value;
// SetUpFromData method doesnt work correctly so we must set the values manually
stringOption.Title = StringName;
stringOption.Values = ((StringGameSetting)Data).Values;
stringOption.Value = Value;
OptionBehaviour = stringOption;
OptionBehaviour = stringOption;
return stringOption;
}
return stringOption;
}
public override NetData GetNetData()
{
return new NetData(Id, BitConverter.GetBytes(Value));
}
public override NetData GetNetData()
{
return new NetData(Id, BitConverter.GetBytes(Value));
}
public override void HandleNetData(byte[] data)
{
SetValue(BitConverter.ToInt32(data));
}
public override void HandleNetData(byte[] data)
{
SetValue(BitConverter.ToInt32(data));
}
public override string GetHudStringText()
{
return Title + ": " + Values[Value];
}
public override string GetHudStringText()
{
return Title + ": " + Values[Value];
}
public override int GetValueFromOptionBehaviour(OptionBehaviour optionBehaviour)
{
return optionBehaviour.GetInt();
}
public override int GetValueFromOptionBehaviour(OptionBehaviour optionBehaviour)
{
return optionBehaviour.GetInt();
}
public override void OnValueChanged(int newValue)
{
DestroyableSingleton<HudManager>.Instance.Notifier.AddSettingsChangeMessage(StringName, Data.GetValueString(newValue), false);
if (OptionBehaviour is null) return;
public override void OnValueChanged(int newValue)
{
DestroyableSingleton<HudManager>.Instance.Notifier.AddSettingsChangeMessage(StringName, Data.GetValueString(newValue), false);
if (OptionBehaviour is null) return;
var opt = OptionBehaviour as StringOption;
if (opt)
{
opt.Value = newValue;
}
var opt = OptionBehaviour as StringOption;
if (opt)
{
opt.Value = newValue;
}
}
}
}
@@ -5,93 +5,92 @@ using MiraAPI.Utilities;
using UnityEngine;
using Object = UnityEngine.Object;
namespace MiraAPI.GameOptions.OptionTypes
namespace MiraAPI.GameOptions.OptionTypes;
public class ModdedNumberOption : ModdedOption<float>
{
public class ModdedNumberOption : ModdedOption<float>
public float Min { get; private set; }
public float Max { get; private set; }
public float Increment { get; private set; }
public NumberSuffixes SuffixType { get; private set; }
public bool ZeroInfinity { get; private set; }
public ModdedNumberOption(string title, float defaultValue, float min, float max, float increment, NumberSuffixes suffixType, bool zeroInfinity, Type roleType) : base(title, defaultValue, roleType)
{
public float Min { get; private set; }
public float Max { get; private set; }
public float Increment { get; private set; }
public NumberSuffixes SuffixType { get; private set; }
public bool ZeroInfinity { get; private set; }
public ModdedNumberOption(string title, float defaultValue, float min, float max, float increment, NumberSuffixes suffixType, bool zeroInfinity, Type roleType) : base(title, defaultValue, roleType)
{
Min = min;
Max = max;
Increment = increment;
SuffixType = suffixType;
ZeroInfinity = zeroInfinity;
Min = min;
Max = max;
Increment = increment;
SuffixType = suffixType;
ZeroInfinity = zeroInfinity;
Value = Mathf.Clamp(defaultValue, min, max);
Value = Mathf.Clamp(defaultValue, min, max);
Data = ScriptableObject.CreateInstance<FloatGameSetting>();
Data = ScriptableObject.CreateInstance<FloatGameSetting>();
var data = (FloatGameSetting)Data;
data.Type = global::OptionTypes.Float;
data.Title = StringName;
data.Value = Value;
data.Increment = Increment;
data.ValidRange = new FloatRange(Min, Max);
data.FormatString = "0";
data.ZeroIsInfinity = ZeroInfinity;
data.SuffixType = SuffixType;
data.OptionName = FloatOptionNames.Invalid;
}
var data = (FloatGameSetting)Data;
data.Type = global::OptionTypes.Float;
data.Title = StringName;
data.Value = Value;
data.Increment = Increment;
data.ValidRange = new FloatRange(Min, Max);
data.FormatString = "0";
data.ZeroIsInfinity = ZeroInfinity;
data.SuffixType = SuffixType;
data.OptionName = FloatOptionNames.Invalid;
}
public override OptionBehaviour CreateOption(ToggleOption toggleOpt, NumberOption numberOpt, StringOption stringOpt, Transform container)
{
var numberOption = Object.Instantiate(numberOpt, Vector3.zero, Quaternion.identity, container);
public override OptionBehaviour CreateOption(ToggleOption toggleOpt, NumberOption numberOpt, StringOption stringOpt, Transform container)
{
var numberOption = Object.Instantiate(numberOpt, Vector3.zero, Quaternion.identity, container);
numberOption.SetUpFromData(Data, 20);
numberOption.OnValueChanged = (Il2CppSystem.Action<OptionBehaviour>)ValueChanged;
numberOption.SetUpFromData(Data, 20);
numberOption.OnValueChanged = (Il2CppSystem.Action<OptionBehaviour>)ValueChanged;
numberOption.Title = StringName;
numberOption.Value = Value;
numberOption.Increment = Increment;
numberOption.ValidRange = new FloatRange(Min, Max);
numberOption.FormatString = "0";
numberOption.ZeroIsInfinity = ZeroInfinity;
numberOption.SuffixType = SuffixType;
numberOption.floatOptionName = FloatOptionNames.Invalid;
numberOption.Title = StringName;
numberOption.Value = Value;
numberOption.Increment = Increment;
numberOption.ValidRange = new FloatRange(Min, Max);
numberOption.FormatString = "0";
numberOption.ZeroIsInfinity = ZeroInfinity;
numberOption.SuffixType = SuffixType;
numberOption.floatOptionName = FloatOptionNames.Invalid;
OptionBehaviour = numberOption;
OptionBehaviour = numberOption;
return numberOption;
}
return numberOption;
}
public override NetData GetNetData()
public override NetData GetNetData()
{
return new NetData(Id, BitConverter.GetBytes(Value));
}
public override void HandleNetData(byte[] data)
{
SetValue(BitConverter.ToSingle(data));
}
public override string GetHudStringText()
{
return Title + ": " + Value + Helpers.GetSuffix(SuffixType);
}
public override float GetValueFromOptionBehaviour(OptionBehaviour optionBehaviour)
{
return Mathf.Clamp(optionBehaviour.GetFloat(), Min, Max);
}
public override void OnValueChanged(float newValue)
{
Value = Mathf.Clamp(newValue, Min, Max);
DestroyableSingleton<HudManager>.Instance.Notifier.AddSettingsChangeMessage(StringName, Data.GetValueString(Value), false);
if (OptionBehaviour is null) return;
var opt = OptionBehaviour as NumberOption;
if (opt)
{
return new NetData(Id, BitConverter.GetBytes(Value));
}
public override void HandleNetData(byte[] data)
{
SetValue(BitConverter.ToSingle(data));
}
public override string GetHudStringText()
{
return Title + ": " + Value + Helpers.GetSuffix(SuffixType);
}
public override float GetValueFromOptionBehaviour(OptionBehaviour optionBehaviour)
{
return Mathf.Clamp(optionBehaviour.GetFloat(), Min, Max);
}
public override void OnValueChanged(float newValue)
{
Value = Mathf.Clamp(newValue, Min, Max);
DestroyableSingleton<HudManager>.Instance.Notifier.AddSettingsChangeMessage(StringName, Data.GetValueString(Value), false);
if (OptionBehaviour is null) return;
var opt = OptionBehaviour as NumberOption;
if (opt)
{
opt.Value = newValue;
}
opt.Value = newValue;
}
}
}
}
+67 -68
View File
@@ -7,77 +7,76 @@ using Reactor.Networking.Rpc;
using Reactor.Utilities;
using UnityEngine;
namespace MiraAPI.GameOptions.OptionTypes
namespace MiraAPI.GameOptions.OptionTypes;
public abstract class ModdedOption<T> : IModdedOption
{
public abstract class ModdedOption<T> : IModdedOption
public uint Id { get; }
public BaseGameSetting Data { get; protected init; }
public T Value { get; protected set; }
public T DefaultValue { get; init; }
public Action<T> ChangedEvent { get; set; }
public string Title { get; }
public StringNames StringName { get; }
public Func<bool> Visible { get; set; }
public Type AdvancedRole { get; }
public OptionBehaviour OptionBehaviour { get; set; }
public ModdedOptionGroup Group { get; set; } = null;
public IMiraPlugin ParentMod { get; set; } = null;
public ModdedOption(string title, T defaultValue, Type roleType) : this()
{
public uint Id { get; }
public BaseGameSetting Data { get; protected init; }
public T Value { get; protected set; }
public T DefaultValue { get; init; }
public Action<T> ChangedEvent { get; set; }
public string Title { get; }
public StringNames StringName { get; }
public Func<bool> Visible { get; set; }
public Type AdvancedRole { get; }
public OptionBehaviour OptionBehaviour { get; set; }
public ModdedOptionGroup Group { get; set; } = null;
public IMiraPlugin ParentMod { get; set; } = null;
Title = title;
DefaultValue = defaultValue;
Value = defaultValue;
StringName = CustomStringName.CreateAndRegister(Title);
Visible = () => true;
public ModdedOption(string title, T defaultValue, Type roleType) : this()
if (roleType is not null && roleType.IsAssignableTo(typeof(ICustomRole)))
{
Title = title;
DefaultValue = defaultValue;
Value = defaultValue;
StringName = CustomStringName.CreateAndRegister(Title);
Visible = () => true;
if (roleType is not null && roleType.IsAssignableTo(typeof(ICustomRole)))
{
AdvancedRole = roleType;
}
AdvancedRole = roleType;
}
public ModdedOption()
{
Logger<MiraApiPlugin>.Error("created modded option");
Id = ModdedOptionsManager.NextId++;
ModdedOptionsManager.Options.Add(this);
ModdedOptionsManager.ModdedOptions.Add(Id, this);
}
public void ValueChanged(OptionBehaviour optionBehaviour)
{
SetValue(GetValueFromOptionBehaviour(optionBehaviour));
}
public void SetValue(T newValue)
{
var oldVal = Value;
Value = newValue;
if (!Value.Equals(oldVal) && ChangedEvent != null)
{
ChangedEvent.Invoke(Value);
}
if (AmongUsClient.Instance.AmHost)
{
Rpc<SyncOptionsRpc>.Instance.Send(PlayerControl.LocalPlayer, [GetNetData()], true);
}
OnValueChanged(newValue);
}
public abstract NetData GetNetData();
public abstract void HandleNetData(byte[] data);
public abstract void OnValueChanged(T newValue);
public abstract T GetValueFromOptionBehaviour(OptionBehaviour optionBehaviour);
public abstract OptionBehaviour CreateOption(ToggleOption toggleOpt, NumberOption numberOpt, StringOption stringOpt, Transform container);
public abstract string GetHudStringText();
}
}
public ModdedOption()
{
Logger<MiraApiPlugin>.Error("created modded option");
Id = ModdedOptionsManager.NextId++;
ModdedOptionsManager.Options.Add(this);
ModdedOptionsManager.ModdedOptions.Add(Id, this);
}
public void ValueChanged(OptionBehaviour optionBehaviour)
{
SetValue(GetValueFromOptionBehaviour(optionBehaviour));
}
public void SetValue(T newValue)
{
var oldVal = Value;
Value = newValue;
if (!Value.Equals(oldVal) && ChangedEvent != null)
{
ChangedEvent.Invoke(Value);
}
if (AmongUsClient.Instance.AmHost)
{
Rpc<SyncOptionsRpc>.Instance.Send(PlayerControl.LocalPlayer, [GetNetData()], true);
}
OnValueChanged(newValue);
}
public abstract NetData GetNetData();
public abstract void HandleNetData(byte[] data);
public abstract void OnValueChanged(T newValue);
public abstract T GetValueFromOptionBehaviour(OptionBehaviour optionBehaviour);
public abstract OptionBehaviour CreateOption(ToggleOption toggleOpt, NumberOption numberOpt, StringOption stringOpt, Transform container);
public abstract string GetHudStringText();
}
@@ -5,71 +5,70 @@ using MiraAPI.Networking;
using UnityEngine;
using Object = UnityEngine.Object;
namespace MiraAPI.GameOptions.OptionTypes
namespace MiraAPI.GameOptions.OptionTypes;
public class ModdedStringOption : ModdedOption<int>
{
public class ModdedStringOption : ModdedOption<int>
public ModdedStringOption(string title, int defaultValue, string[] values, Type roleType) : base(title, defaultValue, roleType)
{
public ModdedStringOption(string title, int defaultValue, string[] values, Type roleType) : base(title, defaultValue, roleType)
{
Values = values;
Data = ScriptableObject.CreateInstance<StringGameSetting>();
var data = (StringGameSetting)Data;
Values = values;
Data = ScriptableObject.CreateInstance<StringGameSetting>();
var data = (StringGameSetting)Data;
data.Title = StringName;
data.Type = global::OptionTypes.String;
data.Values = Values.Select(CustomStringName.CreateAndRegister).ToArray();
data.Index = Value;
}
data.Title = StringName;
data.Type = global::OptionTypes.String;
data.Values = Values.Select(CustomStringName.CreateAndRegister).ToArray();
data.Index = Value;
}
public string[] Values { get; set; }
public string[] Values { get; set; }
public override OptionBehaviour CreateOption(ToggleOption toggleOpt, NumberOption numberOpt, StringOption stringOpt, Transform container)
{
var stringOption = Object.Instantiate(stringOpt, container);
public override OptionBehaviour CreateOption(ToggleOption toggleOpt, NumberOption numberOpt, StringOption stringOpt, Transform container)
{
var stringOption = Object.Instantiate(stringOpt, container);
stringOption.SetUpFromData(Data, 20);
stringOption.OnValueChanged = (Il2CppSystem.Action<OptionBehaviour>)ValueChanged;
stringOption.SetUpFromData(Data, 20);
stringOption.OnValueChanged = (Il2CppSystem.Action<OptionBehaviour>)ValueChanged;
// SetUpFromData method doesnt work correctly so we must set the values manually
stringOption.Title = StringName;
stringOption.Values = ((StringGameSetting)Data).Values;
stringOption.Value = Value;
// SetUpFromData method doesnt work correctly so we must set the values manually
stringOption.Title = StringName;
stringOption.Values = ((StringGameSetting)Data).Values;
stringOption.Value = Value;
OptionBehaviour = stringOption;
OptionBehaviour = stringOption;
return stringOption;
}
return stringOption;
}
public override NetData GetNetData()
public override NetData GetNetData()
{
return new NetData(Id, BitConverter.GetBytes(Value));
}
public override void HandleNetData(byte[] data)
{
SetValue(BitConverter.ToInt32(data));
}
public override string GetHudStringText()
{
return Title + ": " + Values[Value];
}
public override int GetValueFromOptionBehaviour(OptionBehaviour optionBehaviour)
{
return optionBehaviour.GetInt();
}
public override void OnValueChanged(int newValue)
{
DestroyableSingleton<HudManager>.Instance.Notifier.AddSettingsChangeMessage(StringName, Data.GetValueString(newValue), false);
if (OptionBehaviour is null) return;
var opt = OptionBehaviour as StringOption;
if (opt)
{
return new NetData(Id, BitConverter.GetBytes(Value));
}
public override void HandleNetData(byte[] data)
{
SetValue(BitConverter.ToInt32(data));
}
public override string GetHudStringText()
{
return Title + ": " + Values[Value];
}
public override int GetValueFromOptionBehaviour(OptionBehaviour optionBehaviour)
{
return optionBehaviour.GetInt();
}
public override void OnValueChanged(int newValue)
{
DestroyableSingleton<HudManager>.Instance.Notifier.AddSettingsChangeMessage(StringName, Data.GetValueString(newValue), false);
if (OptionBehaviour is null) return;
var opt = OptionBehaviour as StringOption;
if (opt)
{
opt.Value = newValue;
}
opt.Value = newValue;
}
}
}
}
@@ -3,65 +3,64 @@ using MiraAPI.Networking;
using UnityEngine;
using Object = UnityEngine.Object;
namespace MiraAPI.GameOptions.OptionTypes
namespace MiraAPI.GameOptions.OptionTypes;
public class ModdedToggleOption : ModdedOption<bool>
{
public class ModdedToggleOption : ModdedOption<bool>
public ModdedToggleOption(string title, bool defaultValue, Type roleType) : base(title, defaultValue, roleType)
{
public ModdedToggleOption(string title, bool defaultValue, Type roleType) : base(title, defaultValue, roleType)
Data = ScriptableObject.CreateInstance<CheckboxGameSetting>();
var data = (CheckboxGameSetting)Data;
data.Title = StringName;
data.Type = global::OptionTypes.Checkbox;
}
public override OptionBehaviour CreateOption(ToggleOption toggleOpt, NumberOption numberOpt, StringOption stringOpt, Transform container)
{
var toggleOption = Object.Instantiate(toggleOpt, Vector3.zero, Quaternion.identity, container);
toggleOption.SetUpFromData(Data, 20);
toggleOption.Title = StringName;
toggleOption.TitleText.text = Title;
toggleOption.CheckMark.enabled = Value;
toggleOption.OnValueChanged = (Il2CppSystem.Action<OptionBehaviour>)ValueChanged;
OptionBehaviour = toggleOption;
return toggleOption;
}
public override NetData GetNetData()
{
return new NetData(Id, BitConverter.GetBytes(Value));
}
public override void HandleNetData(byte[] data)
{
SetValue(BitConverter.ToBoolean(data));
}
public override string GetHudStringText()
{
return Title + ": " + (Value ? "On" : "Off");
}
public override bool GetValueFromOptionBehaviour(OptionBehaviour optionBehaviour)
{
return optionBehaviour.GetBool();
}
public override void OnValueChanged(bool newValue)
{
DestroyableSingleton<HudManager>.Instance.Notifier.AddSettingsChangeMessage(StringName, newValue ? "On" : "Off", false);
if (OptionBehaviour is null) return;
var toggleOpt = OptionBehaviour as ToggleOption;
if (toggleOpt)
{
Data = ScriptableObject.CreateInstance<CheckboxGameSetting>();
var data = (CheckboxGameSetting)Data;
data.Title = StringName;
data.Type = global::OptionTypes.Checkbox;
}
public override OptionBehaviour CreateOption(ToggleOption toggleOpt, NumberOption numberOpt, StringOption stringOpt, Transform container)
{
var toggleOption = Object.Instantiate(toggleOpt, Vector3.zero, Quaternion.identity, container);
toggleOption.SetUpFromData(Data, 20);
toggleOption.Title = StringName;
toggleOption.TitleText.text = Title;
toggleOption.CheckMark.enabled = Value;
toggleOption.OnValueChanged = (Il2CppSystem.Action<OptionBehaviour>)ValueChanged;
OptionBehaviour = toggleOption;
return toggleOption;
}
public override NetData GetNetData()
{
return new NetData(Id, BitConverter.GetBytes(Value));
}
public override void HandleNetData(byte[] data)
{
SetValue(BitConverter.ToBoolean(data));
}
public override string GetHudStringText()
{
return Title + ": " + (Value ? "On" : "Off");
}
public override bool GetValueFromOptionBehaviour(OptionBehaviour optionBehaviour)
{
return optionBehaviour.GetBool();
}
public override void OnValueChanged(bool newValue)
{
DestroyableSingleton<HudManager>.Instance.Notifier.AddSettingsChangeMessage(StringName, newValue ? "On" : "Off", false);
if (OptionBehaviour is null) return;
var toggleOpt = OptionBehaviour as ToggleOption;
if (toggleOpt)
{
toggleOpt.CheckMark.enabled = newValue;
}
toggleOpt.CheckMark.enabled = newValue;
}
}
}
}
+6 -7
View File
@@ -1,8 +1,7 @@
namespace MiraAPI.Networking
namespace MiraAPI.Networking;
public enum MiraRpc : uint
{
public enum MiraRpc : uint
{
SyncGameOptions,
SyncRoleOptions
}
}
SyncGameOptions,
SyncRoleOptions
}
+96 -97
View File
@@ -5,127 +5,126 @@ using MiraAPI.Roles;
using Reactor.Utilities.Extensions;
using UnityEngine;
namespace MiraAPI.Patches
namespace MiraAPI.Patches;
[HarmonyPatch(typeof(HudManager))]
public static class HudManagerPatches
{
[HarmonyPatch(typeof(HudManager))]
public static class HudManagerPatches
/// Custom buttons parent
private static GameObject _bottomLeft;
/// Custom role tab
private static TaskPanelBehaviour _roleTab;
[HarmonyPostfix]
[HarmonyPatch(nameof(HudManager.Update))]
public static void UpdatePostfix(HudManager __instance)
{
/// Custom buttons parent
private static GameObject _bottomLeft;
var local = PlayerControl.LocalPlayer;
/// Custom role tab
private static TaskPanelBehaviour _roleTab;
[HarmonyPostfix]
[HarmonyPatch(nameof(HudManager.Update))]
public static void UpdatePostfix(HudManager __instance)
if (AmongUsClient.Instance.GameState != InnerNetClient.GameStates.Started && !ShipStatus.Instance)
{
var local = PlayerControl.LocalPlayer;
return;
}
if (AmongUsClient.Instance.GameState != InnerNetClient.GameStates.Started && !ShipStatus.Instance)
//CustomGameModeManager.ActiveMode.HudUpdate(__instance);
if (local is null || local.Data is null || local.Data.Role is null) return;
if (local.Data.Role is ICustomRole customRole)
{
customRole.HudUpdate(__instance);
if (customRole.SetTabText() != null)
{
return;
}
//CustomGameModeManager.ActiveMode.HudUpdate(__instance);
if (local is null || local.Data is null || local.Data.Role is null) return;
if (local.Data.Role is ICustomRole customRole)
{
customRole.HudUpdate(__instance);
if (customRole.SetTabText() != null)
if (_roleTab == null)
{
if (_roleTab == null)
{
_roleTab = CustomRoleManager.CreateRoleTab(customRole);
}
else
{
CustomRoleManager.UpdateRoleTab(_roleTab, customRole);
}
_roleTab = CustomRoleManager.CreateRoleTab(customRole);
}
else if (customRole.SetTabText() == null && _roleTab)
else
{
_roleTab.gameObject.Destroy();
CustomRoleManager.UpdateRoleTab(_roleTab, customRole);
}
}
else if (_roleTab)
else if (customRole.SetTabText() == null && _roleTab)
{
_roleTab.gameObject.Destroy();
}
}
/* /// <summary>
/// Trigger hudstart on current custom gamemode
/// </summary>
[HarmonyPostfix]
[HarmonyPatch("OnGameStart")]
public static void GameStartPatch(HudManager __instance)
{
CustomGameModeManager.ActiveMode.HudStart(__instance);
}*/
/// <summary>
/// Create custom buttons parent
/// </summary>
[HarmonyPostfix]
[HarmonyPatch(nameof(HudManager.Start))]
public static void StartPostfix(HudManager __instance)
else if (_roleTab)
{
if (!_bottomLeft)
_roleTab.gameObject.Destroy();
}
}
/* /// <summary>
/// Trigger hudstart on current custom gamemode
/// </summary>
[HarmonyPostfix]
[HarmonyPatch("OnGameStart")]
public static void GameStartPatch(HudManager __instance)
{
var buttons = __instance.transform.Find("Buttons");
_bottomLeft = Object.Instantiate(buttons.Find("BottomRight").gameObject, buttons);
}
CustomGameModeManager.ActiveMode.HudStart(__instance);
}*/
foreach (var t in _bottomLeft.GetComponentsInChildren<ActionButton>(true))
{
t.gameObject.Destroy();
}
var gridArrange = _bottomLeft.GetComponent<GridArrange>();
var aspectPosition = _bottomLeft.GetComponent<AspectPosition>();
_bottomLeft.name = "BottomLeft";
gridArrange.Alignment = GridArrange.StartAlign.Right;
aspectPosition.Alignment = AspectPosition.EdgeAlignments.LeftBottom;
foreach (var button in CustomButtonManager.CustomButtons)
{
button.CreateButton(_bottomLeft.transform);
}
gridArrange.Start();
gridArrange.ArrangeChilds();
aspectPosition.AdjustPosition();
/// <summary>
/// Create custom buttons parent
/// </summary>
[HarmonyPostfix]
[HarmonyPatch(nameof(HudManager.Start))]
public static void StartPostfix(HudManager __instance)
{
if (!_bottomLeft)
{
var buttons = __instance.transform.Find("Buttons");
_bottomLeft = Object.Instantiate(buttons.Find("BottomRight").gameObject, buttons);
}
/// <summary>
/// Make sure all launchpad hud elements are inactive/active when appropriate
/// </summary>
[HarmonyPostfix]
[HarmonyPatch(nameof(HudManager.SetHudActive), typeof(PlayerControl), typeof(RoleBehaviour), typeof(bool))]
public static void SetHudActivePostfix(HudManager __instance, [HarmonyArgument(0)] PlayerControl player, [HarmonyArgument(1)] RoleBehaviour roleBehaviour, [HarmonyArgument(2)] bool isActive)
foreach (var t in _bottomLeft.GetComponentsInChildren<ActionButton>(true))
{
if (player.Data == null)
{
return;
}
t.gameObject.Destroy();
}
if (_roleTab)
{
_roleTab.gameObject.SetActive(isActive);
}
var gridArrange = _bottomLeft.GetComponent<GridArrange>();
var aspectPosition = _bottomLeft.GetComponent<AspectPosition>();
foreach (var button in CustomButtonManager.CustomButtons)
button.SetActive(isActive, roleBehaviour);
_bottomLeft.name = "BottomLeft";
gridArrange.Alignment = GridArrange.StartAlign.Right;
aspectPosition.Alignment = AspectPosition.EdgeAlignments.LeftBottom;
if (roleBehaviour is ICustomRole role)
{
__instance.ImpostorVentButton.gameObject.SetActive(isActive && role.CanUseVent);
}
foreach (var button in CustomButtonManager.CustomButtons)
{
button.CreateButton(_bottomLeft.transform);
}
gridArrange.Start();
gridArrange.ArrangeChilds();
aspectPosition.AdjustPosition();
}
/// <summary>
/// Make sure all launchpad hud elements are inactive/active when appropriate
/// </summary>
[HarmonyPostfix]
[HarmonyPatch(nameof(HudManager.SetHudActive), typeof(PlayerControl), typeof(RoleBehaviour), typeof(bool))]
public static void SetHudActivePostfix(HudManager __instance, [HarmonyArgument(0)] PlayerControl player, [HarmonyArgument(1)] RoleBehaviour roleBehaviour, [HarmonyArgument(2)] bool isActive)
{
if (player.Data == null)
{
return;
}
if (_roleTab)
{
_roleTab.gameObject.SetActive(isActive);
}
foreach (var button in CustomButtonManager.CustomButtons)
button.SetActive(isActive, roleBehaviour);
if (roleBehaviour is ICustomRole role)
{
__instance.ImpostorVentButton.gameObject.SetActive(isActive && role.CanUseVent);
}
}
}
+45 -46
View File
@@ -2,61 +2,60 @@
using Il2CppSystem;
using MiraAPI.Utilities;
namespace MiraAPI.Patches.Options
namespace MiraAPI.Patches.Options;
[HarmonyPatch]
public static class OptionsPatches
{
[HarmonyPatch]
public static class OptionsPatches
[HarmonyPrefix]
[HarmonyPatch(typeof(ToggleOption), nameof(ToggleOption.Initialize))]
public static bool ToggleInit(ToggleOption __instance)
{
[HarmonyPrefix]
[HarmonyPatch(typeof(ToggleOption), nameof(ToggleOption.Initialize))]
public static bool ToggleInit(ToggleOption __instance)
{
if (!__instance.IsCustom()) return true;
__instance.TitleText.text = DestroyableSingleton<TranslationController>.Instance.GetString(__instance.Title, Array.Empty<Object>());
if (!__instance.IsCustom()) return true;
__instance.TitleText.text = DestroyableSingleton<TranslationController>.Instance.GetString(__instance.Title, Array.Empty<Object>());
return false;
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ToggleOption), nameof(ToggleOption.UpdateValue))]
public static bool ToggleUpdate(ToggleOption __instance)
{
return !__instance.IsCustom();
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ToggleOption), nameof(ToggleOption.UpdateValue))]
public static bool ToggleUpdate(ToggleOption __instance)
{
return !__instance.IsCustom();
}
[HarmonyPrefix]
[HarmonyPatch(typeof(NumberOption), nameof(NumberOption.Initialize))]
public static bool NumberInit(NumberOption __instance)
{
if (!__instance.IsCustom()) return true;
__instance.TitleText.text = DestroyableSingleton<TranslationController>.Instance.GetString(__instance.Title, Array.Empty<Object>());
[HarmonyPrefix]
[HarmonyPatch(typeof(NumberOption), nameof(NumberOption.Initialize))]
public static bool NumberInit(NumberOption __instance)
{
if (!__instance.IsCustom()) return true;
__instance.TitleText.text = DestroyableSingleton<TranslationController>.Instance.GetString(__instance.Title, Array.Empty<Object>());
return false;
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(NumberOption), nameof(NumberOption.UpdateValue))]
public static bool NumberUpdate(NumberOption __instance)
{
return !__instance.IsCustom();
}
[HarmonyPrefix]
[HarmonyPatch(typeof(NumberOption), nameof(NumberOption.UpdateValue))]
public static bool NumberUpdate(NumberOption __instance)
{
return !__instance.IsCustom();
}
[HarmonyPrefix]
[HarmonyPatch(typeof(StringOption), nameof(StringOption.Initialize))]
public static bool StringInit(StringOption __instance)
{
if (!__instance.IsCustom()) return true;
__instance.TitleText.text = DestroyableSingleton<TranslationController>.Instance.GetString(__instance.Title, Array.Empty<Object>());
__instance.ValueText.text = DestroyableSingleton<TranslationController>.Instance.GetString(__instance.Values[__instance.Value], Array.Empty<Object>());
[HarmonyPrefix]
[HarmonyPatch(typeof(StringOption), nameof(StringOption.Initialize))]
public static bool StringInit(StringOption __instance)
{
if (!__instance.IsCustom()) return true;
__instance.TitleText.text = DestroyableSingleton<TranslationController>.Instance.GetString(__instance.Title, Array.Empty<Object>());
__instance.ValueText.text = DestroyableSingleton<TranslationController>.Instance.GetString(__instance.Values[__instance.Value], Array.Empty<Object>());
return false;
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(StringOption), nameof(StringOption.UpdateValue))]
public static bool StringUpdate(StringOption __instance)
{
return !__instance.IsCustom();
}
[HarmonyPrefix]
[HarmonyPatch(typeof(StringOption), nameof(StringOption.UpdateValue))]
public static bool StringUpdate(StringOption __instance)
{
return !__instance.IsCustom();
}
}
+180 -181
View File
@@ -14,206 +14,205 @@ using UnityEngine.Events;
using static UnityEngine.UI.Button;
using Object = UnityEngine.Object;
namespace MiraAPI.Patches.Options
namespace MiraAPI.Patches.Options;
[HarmonyPatch(typeof(RolesSettingsMenu))]
public static class RoleSettingMenuPatches
{
[HarmonyPatch(typeof(RolesSettingsMenu))]
public static class RoleSettingMenuPatches
[HarmonyPrefix]
[HarmonyPatch(nameof(RolesSettingsMenu.SetQuotaTab))]
public static bool PatchStart(RolesSettingsMenu __instance)
{
[HarmonyPrefix]
[HarmonyPatch(nameof(RolesSettingsMenu.SetQuotaTab))]
public static bool PatchStart(RolesSettingsMenu __instance)
{
__instance.roleChances = new Il2CppSystem.Collections.Generic.List<RoleOptionSetting>();
__instance.advancedSettingChildren = new Il2CppSystem.Collections.Generic.List<OptionBehaviour>();
__instance.roleChances = new Il2CppSystem.Collections.Generic.List<RoleOptionSetting>();
__instance.advancedSettingChildren = new Il2CppSystem.Collections.Generic.List<OptionBehaviour>();
var maskBg = __instance.scrollBar.transform.FindChild("MaskBg");
var maskBg = __instance.scrollBar.transform.FindChild("MaskBg");
if (GameSettingMenuPatches.currentSelectedMod == 0)
{
__instance.AllButton.transform.parent.gameObject.SetActive(true);
__instance.AllButton.gameObject.SetActive(true);
__instance.scrollBar.transform.localPosition = new Vector3(-1.4957f, 0.657f, -4);
maskBg.localPosition = new Vector3(1.5353f, -.5734f, -.1f);
maskBg.localScale = new Vector3(6.6811f, 3.3563f, 0.5598f);
return true;
}
float num = 0.522f;
__instance.AllButton.transform.parent.gameObject.SetActive(false);
__instance.AllButton.gameObject.SetActive(false);
__instance.scrollBar.transform.localPosition = new Vector3(-1.4957f, 1.5261f, -4);
maskBg.localPosition = new Vector3(1.5353f, -1.0607f, -.1f);
maskBg.localScale = new Vector3(6.6811f, 4.1563f, 0.5598f);
CategoryHeaderEditRole categoryHeaderEditRole = Object.Instantiate(__instance.categoryHeaderEditRoleOrigin, Vector3.zero, Quaternion.identity, __instance.RoleChancesSettings.transform);
categoryHeaderEditRole.SetHeader(StringNames.CrewmateRolesHeader, 20);
categoryHeaderEditRole.transform.localPosition = new Vector3(4.986f, num, -2f);
num -= 0.522f;
int num3 = 0;
foreach (var role in GameSettingMenuPatches.selectedMod.CustomRoles.Values.OfType<ICustomRole>().Where(role => role.Team == ModdedRoleTeams.Crewmate))
{
CreateQuotaOption(__instance, role as RoleBehaviour, ref num, num3);
num3++;
}
num -= 0.4f;
CategoryHeaderEditRole categoryHeaderEditRole2 = Object.Instantiate(__instance.categoryHeaderEditRoleOrigin, Vector3.zero, Quaternion.identity, __instance.RoleChancesSettings.transform);
categoryHeaderEditRole2.SetHeader(StringNames.ImpostorRolesHeader, 20);
categoryHeaderEditRole2.transform.localPosition = new Vector3(4.986f, num, -2f);
num -= 0.522f;
foreach (var role in GameSettingMenuPatches.selectedMod.CustomRoles.Values.OfType<ICustomRole>().Where(role => role.Team == ModdedRoleTeams.Impostor))
{
CreateQuotaOption(__instance, role as RoleBehaviour, ref num, num3);
num3++;
}
num -= 0.8f;
CategoryHeaderEditRole categoryHeaderEditRole3 = Object.Instantiate(__instance.categoryHeaderEditRoleOrigin, Vector3.zero, Quaternion.identity, __instance.RoleChancesSettings.transform);
categoryHeaderEditRole3.SetHeader(StringNames.None, 20);
categoryHeaderEditRole3.Title.text = "Neutral Roles";
categoryHeaderEditRole3.transform.localPosition = new Vector3(4.986f, num, -2f);
num -= 0.522f;
foreach (var role in GameSettingMenuPatches.selectedMod.CustomRoles.Values.OfType<ICustomRole>().Where(role => role.Team == ModdedRoleTeams.Neutral))
{
CreateQuotaOption(__instance, role as RoleBehaviour, ref num, num3);
num3++;
}
return false;
if (GameSettingMenuPatches.currentSelectedMod == 0)
{
__instance.AllButton.transform.parent.gameObject.SetActive(true);
__instance.AllButton.gameObject.SetActive(true);
__instance.scrollBar.transform.localPosition = new Vector3(-1.4957f, 0.657f, -4);
maskBg.localPosition = new Vector3(1.5353f, -.5734f, -.1f);
maskBg.localScale = new Vector3(6.6811f, 3.3563f, 0.5598f);
return true;
}
[HarmonyPrefix]
[HarmonyPatch(nameof(RolesSettingsMenu.Update))]
public static bool UpdatePatch()
{
if (GameSettingMenuPatches.currentSelectedMod == 0)
{
return true;
}
float num = 0.522f;
return false;
__instance.AllButton.transform.parent.gameObject.SetActive(false);
__instance.AllButton.gameObject.SetActive(false);
__instance.scrollBar.transform.localPosition = new Vector3(-1.4957f, 1.5261f, -4);
maskBg.localPosition = new Vector3(1.5353f, -1.0607f, -.1f);
maskBg.localScale = new Vector3(6.6811f, 4.1563f, 0.5598f);
CategoryHeaderEditRole categoryHeaderEditRole = Object.Instantiate(__instance.categoryHeaderEditRoleOrigin, Vector3.zero, Quaternion.identity, __instance.RoleChancesSettings.transform);
categoryHeaderEditRole.SetHeader(StringNames.CrewmateRolesHeader, 20);
categoryHeaderEditRole.transform.localPosition = new Vector3(4.986f, num, -2f);
num -= 0.522f;
int num3 = 0;
foreach (var role in GameSettingMenuPatches.selectedMod.CustomRoles.Values.OfType<ICustomRole>().Where(role => role.Team == ModdedRoleTeams.Crewmate))
{
CreateQuotaOption(__instance, role as RoleBehaviour, ref num, num3);
num3++;
}
private static void ValueChanged(OptionBehaviour obj)
num -= 0.4f;
CategoryHeaderEditRole categoryHeaderEditRole2 = Object.Instantiate(__instance.categoryHeaderEditRoleOrigin, Vector3.zero, Quaternion.identity, __instance.RoleChancesSettings.transform);
categoryHeaderEditRole2.SetHeader(StringNames.ImpostorRolesHeader, 20);
categoryHeaderEditRole2.transform.localPosition = new Vector3(4.986f, num, -2f);
num -= 0.522f;
foreach (var role in GameSettingMenuPatches.selectedMod.CustomRoles.Values.OfType<ICustomRole>().Where(role => role.Team == ModdedRoleTeams.Impostor))
{
var roleSetting = obj.Cast<RoleOptionSetting>();
var role = roleSetting.Role as ICustomRole;
if (role is null or { HideSettings: true }) return;
PluginSingleton<MiraApiPlugin>.Instance.Config.TryGetEntry<int>(role.NumConfigDefinition, out var numEntry);
numEntry.Value = roleSetting.RoleMaxCount;
PluginSingleton<MiraApiPlugin>.Instance.Config.TryGetEntry<int>(role.ChanceConfigDefinition, out var chanceEntry);
chanceEntry.Value = roleSetting.RoleChance;
roleSetting.UpdateValuesAndText(GameOptionsManager.Instance.CurrentGameOptions.RoleOptions);
DestroyableSingleton<HudManager>.Instance.Notifier.AddRoleSettingsChangeMessage(roleSetting.Role.StringName, roleSetting.RoleMaxCount, roleSetting.RoleChance, roleSetting.Role.TeamType, false);
if (AmongUsClient.Instance.AmHost)
{
Rpc<SyncRoleOptionsRpc>.Instance.Send(PlayerControl.LocalPlayer, [role.GetNetData(roleSetting.Role)], true);
}
GameOptionsManager.Instance.GameHostOptions = GameOptionsManager.Instance.CurrentGameOptions;
CreateQuotaOption(__instance, role as RoleBehaviour, ref num, num3);
num3++;
}
private static void CreateAdvancedSettings(RolesSettingsMenu __instance, RoleBehaviour role)
num -= 0.8f;
CategoryHeaderEditRole categoryHeaderEditRole3 = Object.Instantiate(__instance.categoryHeaderEditRoleOrigin, Vector3.zero, Quaternion.identity, __instance.RoleChancesSettings.transform);
categoryHeaderEditRole3.SetHeader(StringNames.None, 20);
categoryHeaderEditRole3.Title.text = "Neutral Roles";
categoryHeaderEditRole3.transform.localPosition = new Vector3(4.986f, num, -2f);
num -= 0.522f;
foreach (var role in GameSettingMenuPatches.selectedMod.CustomRoles.Values.OfType<ICustomRole>().Where(role => role.Team == ModdedRoleTeams.Neutral))
{
foreach (var option in __instance.advancedSettingChildren)
{
Object.Destroy(option.gameObject);
}
__instance.advancedSettingChildren.Clear();
float num = -0.872f;
foreach (var option in GameSettingMenuPatches.selectedMod.Options.Where(option => option.AdvancedRole == role.GetType()))
{
OptionBehaviour newOpt = option.CreateOption(__instance.checkboxOrigin, __instance.numberOptionOrigin, __instance.stringOptionOrigin, __instance.AdvancedRolesSettings.transform);
newOpt.transform.localPosition = new Vector3(2.17f, num, -2f);
newOpt.SetClickMask(__instance.ButtonClickMask);
SpriteRenderer[] componentsInChildren = newOpt.GetComponentsInChildren<SpriteRenderer>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
componentsInChildren[i].material.SetInt(PlayerMaterial.MaskLayer, 20);
}
foreach (TextMeshPro textMeshPro in newOpt.GetComponentsInChildren<TextMeshPro>(true))
{
textMeshPro.fontMaterial.SetFloat(ShaderID._StencilComp, 3f);
textMeshPro.fontMaterial.SetFloat(ShaderID._Stencil, 20);
}
newOpt.LabelBackground.enabled = false;
__instance.advancedSettingChildren.Add(newOpt);
num += -0.45f;
newOpt.Initialize();
}
__instance.scrollBar.CalculateAndSetYBounds((float)(__instance.advancedSettingChildren.Count + 3), 1f, 6f, 0.45f);
}
private static void ChangeTab(RoleBehaviour role, RolesSettingsMenu __instance)
{
ICustomRole customRole = role as ICustomRole;
__instance.roleDescriptionText.text = customRole.RoleLongDescription;
__instance.roleTitleText.text = DestroyableSingleton<TranslationController>.Instance.GetString(role.StringName, Array.Empty<Il2CppSystem.Object>());
__instance.roleScreenshot.sprite = Sprite.Create(role.RoleScreenshot.texture, new Rect(0, 0, 370, 230), Vector2.one / 2, 100);
__instance.roleScreenshot.drawMode = SpriteDrawMode.Sliced;
__instance.roleHeaderSprite.color = customRole.RoleColor;
__instance.roleHeaderText.color = customRole.RoleColor.DarkenColor();
CreateAdvancedSettings(__instance, role);
foreach (var optionBehaviour in __instance.advancedSettingChildren)
{
optionBehaviour.OnValueChanged = new Action<OptionBehaviour>(__instance.ValueChanged);
if (AmongUsClient.Instance && !AmongUsClient.Instance.AmHost)
{
optionBehaviour.SetAsPlayer();
}
}
__instance.RoleChancesSettings.SetActive(false);
__instance.AdvancedRolesSettings.SetActive(true);
__instance.RefreshChildren();
CreateQuotaOption(__instance, role as RoleBehaviour, ref num, num3);
num3++;
}
public static void CreateQuotaOption(RolesSettingsMenu __instance, RoleBehaviour role, ref float yPos, int index)
return false;
}
[HarmonyPrefix]
[HarmonyPatch(nameof(RolesSettingsMenu.Update))]
public static bool UpdatePatch()
{
if (GameSettingMenuPatches.currentSelectedMod == 0)
{
ICustomRole customRole = role as ICustomRole;
RoleOptionSetting roleOptionSetting = Object.Instantiate(__instance.roleOptionSettingOrigin, Vector3.zero, Quaternion.identity, __instance.RoleChancesSettings.transform);
roleOptionSetting.transform.localPosition = new Vector3(-0.15f, yPos, -2f);
roleOptionSetting.SetRole(GameOptionsManager.Instance.CurrentGameOptions.RoleOptions, role, 20);
roleOptionSetting.labelSprite.color = customRole.RoleColor;
roleOptionSetting.titleText.color = customRole.RoleColor.DarkenColor();
roleOptionSetting.OnValueChanged = new Action<OptionBehaviour>(ValueChanged);
roleOptionSetting.titleText.horizontalAlignment = HorizontalAlignmentOptions.Left;
roleOptionSetting.SetClickMask(__instance.ButtonClickMask);
__instance.roleChances.Add(roleOptionSetting);
return true;
}
PassiveButton newButton = Object.Instantiate(roleOptionSetting.buttons[0], roleOptionSetting.transform);
newButton.name = "ConfigButton";
newButton.transform.localPosition = new Vector3(0.2419f, -0.2582f, -2f);
newButton.transform.FindChild("Plus_TMP").gameObject.DestroyImmediate();
newButton.transform.FindChild("InactiveSprite").GetComponent<SpriteRenderer>().sprite = MiraAssets.Cog.LoadAsset();
newButton.transform.FindChild("ActiveSprite").GetComponent<SpriteRenderer>().sprite = MiraAssets.CogActive.LoadAsset();
return false;
}
PassiveButton passiveButton = newButton.GetComponent<PassiveButton>();
passiveButton.OnClick = new ButtonClickedEvent();
passiveButton.OnClick.AddListener((UnityAction)(() =>
private static void ValueChanged(OptionBehaviour obj)
{
var roleSetting = obj.Cast<RoleOptionSetting>();
var role = roleSetting.Role as ICustomRole;
if (role is null or { HideSettings: true }) return;
PluginSingleton<MiraApiPlugin>.Instance.Config.TryGetEntry<int>(role.NumConfigDefinition, out var numEntry);
numEntry.Value = roleSetting.RoleMaxCount;
PluginSingleton<MiraApiPlugin>.Instance.Config.TryGetEntry<int>(role.ChanceConfigDefinition, out var chanceEntry);
chanceEntry.Value = roleSetting.RoleChance;
roleSetting.UpdateValuesAndText(GameOptionsManager.Instance.CurrentGameOptions.RoleOptions);
DestroyableSingleton<HudManager>.Instance.Notifier.AddRoleSettingsChangeMessage(roleSetting.Role.StringName, roleSetting.RoleMaxCount, roleSetting.RoleChance, roleSetting.Role.TeamType, false);
if (AmongUsClient.Instance.AmHost)
{
Rpc<SyncRoleOptionsRpc>.Instance.Send(PlayerControl.LocalPlayer, [role.GetNetData(roleSetting.Role)], true);
}
GameOptionsManager.Instance.GameHostOptions = GameOptionsManager.Instance.CurrentGameOptions;
}
private static void CreateAdvancedSettings(RolesSettingsMenu __instance, RoleBehaviour role)
{
foreach (var option in __instance.advancedSettingChildren)
{
Object.Destroy(option.gameObject);
}
__instance.advancedSettingChildren.Clear();
float num = -0.872f;
foreach (var option in GameSettingMenuPatches.selectedMod.Options.Where(option => option.AdvancedRole == role.GetType()))
{
OptionBehaviour newOpt = option.CreateOption(__instance.checkboxOrigin, __instance.numberOptionOrigin, __instance.stringOptionOrigin, __instance.AdvancedRolesSettings.transform);
newOpt.transform.localPosition = new Vector3(2.17f, num, -2f);
newOpt.SetClickMask(__instance.ButtonClickMask);
SpriteRenderer[] componentsInChildren = newOpt.GetComponentsInChildren<SpriteRenderer>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
ChangeTab(role, __instance);
}));
if (index < GameSettingMenuPatches.selectedMod.CustomRoles.Count - 1)
{
yPos += -0.43f;
componentsInChildren[i].material.SetInt(PlayerMaterial.MaskLayer, 20);
}
foreach (TextMeshPro textMeshPro in newOpt.GetComponentsInChildren<TextMeshPro>(true))
{
textMeshPro.fontMaterial.SetFloat(ShaderID._StencilComp, 3f);
textMeshPro.fontMaterial.SetFloat(ShaderID._Stencil, 20);
}
newOpt.LabelBackground.enabled = false;
__instance.advancedSettingChildren.Add(newOpt);
num += -0.45f;
newOpt.Initialize();
}
__instance.scrollBar.CalculateAndSetYBounds((float)(__instance.advancedSettingChildren.Count + 3), 1f, 6f, 0.45f);
}
private static void ChangeTab(RoleBehaviour role, RolesSettingsMenu __instance)
{
ICustomRole customRole = role as ICustomRole;
__instance.roleDescriptionText.text = customRole.RoleLongDescription;
__instance.roleTitleText.text = DestroyableSingleton<TranslationController>.Instance.GetString(role.StringName, Array.Empty<Il2CppSystem.Object>());
__instance.roleScreenshot.sprite = Sprite.Create(role.RoleScreenshot.texture, new Rect(0, 0, 370, 230), Vector2.one / 2, 100);
__instance.roleScreenshot.drawMode = SpriteDrawMode.Sliced;
__instance.roleHeaderSprite.color = customRole.RoleColor;
__instance.roleHeaderText.color = customRole.RoleColor.DarkenColor();
CreateAdvancedSettings(__instance, role);
foreach (var optionBehaviour in __instance.advancedSettingChildren)
{
optionBehaviour.OnValueChanged = new Action<OptionBehaviour>(__instance.ValueChanged);
if (AmongUsClient.Instance && !AmongUsClient.Instance.AmHost)
{
optionBehaviour.SetAsPlayer();
}
}
__instance.RoleChancesSettings.SetActive(false);
__instance.AdvancedRolesSettings.SetActive(true);
__instance.RefreshChildren();
}
public static void CreateQuotaOption(RolesSettingsMenu __instance, RoleBehaviour role, ref float yPos, int index)
{
ICustomRole customRole = role as ICustomRole;
RoleOptionSetting roleOptionSetting = Object.Instantiate(__instance.roleOptionSettingOrigin, Vector3.zero, Quaternion.identity, __instance.RoleChancesSettings.transform);
roleOptionSetting.transform.localPosition = new Vector3(-0.15f, yPos, -2f);
roleOptionSetting.SetRole(GameOptionsManager.Instance.CurrentGameOptions.RoleOptions, role, 20);
roleOptionSetting.labelSprite.color = customRole.RoleColor;
roleOptionSetting.titleText.color = customRole.RoleColor.DarkenColor();
roleOptionSetting.OnValueChanged = new Action<OptionBehaviour>(ValueChanged);
roleOptionSetting.titleText.horizontalAlignment = HorizontalAlignmentOptions.Left;
roleOptionSetting.SetClickMask(__instance.ButtonClickMask);
__instance.roleChances.Add(roleOptionSetting);
PassiveButton newButton = Object.Instantiate(roleOptionSetting.buttons[0], roleOptionSetting.transform);
newButton.name = "ConfigButton";
newButton.transform.localPosition = new Vector3(0.2419f, -0.2582f, -2f);
newButton.transform.FindChild("Plus_TMP").gameObject.DestroyImmediate();
newButton.transform.FindChild("InactiveSprite").GetComponent<SpriteRenderer>().sprite = MiraAssets.Cog.LoadAsset();
newButton.transform.FindChild("ActiveSprite").GetComponent<SpriteRenderer>().sprite = MiraAssets.CogActive.LoadAsset();
PassiveButton passiveButton = newButton.GetComponent<PassiveButton>();
passiveButton.OnClick = new ButtonClickedEvent();
passiveButton.OnClick.AddListener((UnityAction)(() =>
{
ChangeTab(role, __instance);
}));
if (index < GameSettingMenuPatches.selectedMod.CustomRoles.Count - 1)
{
yPos += -0.43f;
}
}
}
}
+5 -6
View File
@@ -1,9 +1,8 @@
using BepInEx.Configuration;
namespace MiraAPI.PluginLoading
namespace MiraAPI.PluginLoading;
public interface IMiraPlugin
{
public interface IMiraPlugin
{
public ConfigFile GetConfigFile();
}
}
public ConfigFile GetConfigFile();
}
+1
View File
@@ -22,6 +22,7 @@ public interface ICustomRole
Color RoleColor { get; }
ModdedRoleTeams Team { get; }
LoadableAsset<Sprite> OptionsScreenshot { get; }
LoadableAsset<Sprite> Icon => MiraAssets.Empty;
+7 -8
View File
@@ -1,9 +1,8 @@
namespace MiraAPI.Roles
namespace MiraAPI.Roles;
public enum ModdedRoleTeams
{
public enum ModdedRoleTeams
{
Crewmate,
Impostor,
Neutral
}
}
Crewmate,
Impostor,
Neutral
}
+17 -18
View File
@@ -1,22 +1,21 @@
namespace MiraAPI.Utilities.Assets
namespace MiraAPI.Utilities.Assets;
/// <summary>
/// An abstract class that provides a simple pattern for loading assets.
/// Mira uses the <see cref="LoadableAsset{T}"/> pattern in various locations.
/// You can create your own implementation of this class to load assets in different ways.
/// </summary>
/// <typeparam name="T">The type of the asset to be loaded</typeparam>
public abstract class LoadableAsset<T> where T : UnityEngine.Object
{
/// <summary>
/// An abstract class that provides a simple pattern for loading assets.
/// Mira uses the <see cref="LoadableAsset{T}"/> pattern in various locations.
/// You can create your own implementation of this class to load assets in different ways.
/// A reference to the loaded asset. Intended to be used for caching purposes.
/// </summary>
/// <typeparam name="T">The type of the asset to be loaded</typeparam>
public abstract class LoadableAsset<T> where T : UnityEngine.Object
{
/// <summary>
/// A reference to the loaded asset. Intended to be used for caching purposes.
/// </summary>
protected T LoadedAsset;
protected T LoadedAsset;
/// <summary>
/// The method that loads the asset.
/// </summary>
/// <returns>The loaded asset</returns>
public abstract T LoadAsset();
}
}
/// <summary>
/// The method that loads the asset.
/// </summary>
/// <returns>The loaded asset</returns>
public abstract T LoadAsset();
}
+24 -25
View File
@@ -2,36 +2,35 @@
using Reactor.Utilities.Extensions;
using UnityEngine;
namespace MiraAPI.Utilities.Assets
namespace MiraAPI.Utilities.Assets;
/// <summary>
/// A utility class for loading assets from an asset bundle.
/// </summary>
/// <param name="name">The name of the asset</param>
/// <param name="bundle">The AssetBundle that contains the asset</param>
/// <typeparam name="T">The type of the asset to be loaded</typeparam>
public class LoadableBundleAsset<T>(string name, AssetBundle bundle) : LoadableAsset<T> where T : UnityEngine.Object
{
/// <summary>
/// A utility class for loading assets from an asset bundle.
/// Loads the asset from the asset bundle.
/// </summary>
/// <param name="name">The name of the asset</param>
/// <param name="bundle">The AssetBundle that contains the asset</param>
/// <typeparam name="T">The type of the asset to be loaded</typeparam>
public class LoadableBundleAsset<T>(string name, AssetBundle bundle) : LoadableAsset<T> where T : UnityEngine.Object
/// <returns>The asset</returns>
/// <exception cref="Exception">The asset did not load properly.</exception>
public override T LoadAsset()
{
/// <summary>
/// Loads the asset from the asset bundle.
/// </summary>
/// <returns>The asset</returns>
/// <exception cref="Exception">The asset did not load properly.</exception>
public override T LoadAsset()
if (LoadedAsset)
{
if (LoadedAsset)
{
return LoadedAsset;
}
LoadedAsset = bundle.LoadAsset<T>(name);
if (!LoadedAsset)
{
throw new Exception($"INVALID ASSET: {name}");
}
return LoadedAsset;
}
LoadedAsset = bundle.LoadAsset<T>(name);
if (!LoadedAsset)
{
throw new Exception($"INVALID ASSET: {name}");
}
return LoadedAsset;
}
}
}
@@ -1,25 +1,24 @@
using UnityEngine;
namespace MiraAPI.Utilities.Assets
{
public class LoadableResourceAsset(string path) : LoadableAsset<Sprite>
{
public override Sprite LoadAsset()
{
if (LoadedAsset != null)
{
return LoadedAsset;
}
namespace MiraAPI.Utilities.Assets;
try
{
return LoadedAsset = SpriteTools.LoadSpriteFromPath(path);
}
catch
{
Debug.LogError($"Not loading, invalid asset: {path}");
return null;
}
public class LoadableResourceAsset(string path) : LoadableAsset<Sprite>
{
public override Sprite LoadAsset()
{
if (LoadedAsset != null)
{
return LoadedAsset;
}
try
{
return LoadedAsset = SpriteTools.LoadSpriteFromPath(path);
}
catch
{
Debug.LogError($"Not loading, invalid asset: {path}");
return null;
}
}
}
}
+11 -12
View File
@@ -1,13 +1,12 @@
namespace MiraAPI.Utilities.Assets
{
public static class MiraAssets
{
public static readonly LoadableResourceAsset Empty = new("");
namespace MiraAPI.Utilities.Assets;
public static readonly LoadableResourceAsset NextButton = new("MiraAPI.Resources.NextButton.png");
public static readonly LoadableResourceAsset NextButtonActive = new("MiraAPI.Resources.NextButtonActive.png");
public static readonly LoadableResourceAsset Cog = new("MiraAPI.Resources.Cog.png");
public static readonly LoadableResourceAsset CogActive = new("MiraAPI.Resources.CogActive.png");
public static readonly LoadableResourceAsset Banner = new("MiraAPI.Resources.FortniteBanner.jpeg");
}
}
public static class MiraAssets
{
public static readonly LoadableResourceAsset Empty = new("");
public static readonly LoadableResourceAsset NextButton = new("MiraAPI.Resources.NextButton.png");
public static readonly LoadableResourceAsset NextButtonActive = new("MiraAPI.Resources.NextButtonActive.png");
public static readonly LoadableResourceAsset Cog = new("MiraAPI.Resources.Cog.png");
public static readonly LoadableResourceAsset CogActive = new("MiraAPI.Resources.CogActive.png");
public static readonly LoadableResourceAsset Banner = new("MiraAPI.Resources.FortniteBanner.jpeg");
}
+39 -40
View File
@@ -6,48 +6,47 @@ using System.Reflection;
using Reactor.Utilities;
using UnityEngine;
namespace MiraAPI.Utilities.Assets
namespace MiraAPI.Utilities.Assets;
/// <summary>
/// A utility class for various sprite-related operations.
/// </summary>
public static class SpriteTools
{
/// <summary>
/// A utility class for various sprite-related operations.
/// </summary>
public static class SpriteTools
private delegate bool DLoadImage(IntPtr tex, IntPtr data, bool markNonReadable);
private static DLoadImage _iCallLoadImage;
private static bool LoadImage(Texture2D tex, byte[] data, bool markNonReadable)
{
private delegate bool DLoadImage(IntPtr tex, IntPtr data, bool markNonReadable);
_iCallLoadImage ??= IL2CPP.ResolveICall<DLoadImage>("UnityEngine.ImageConversion::LoadImage");
private static DLoadImage _iCallLoadImage;
var il2CPPArray = (Il2CppStructArray<byte>)data;
private static bool LoadImage(Texture2D tex, byte[] data, bool markNonReadable)
{
_iCallLoadImage ??= IL2CPP.ResolveICall<DLoadImage>("UnityEngine.ImageConversion::LoadImage");
var il2CPPArray = (Il2CppStructArray<byte>)data;
return _iCallLoadImage.Invoke(tex.Pointer, il2CPPArray.Pointer, markNonReadable);
}
/// <summary>
/// Load a sprite from a resource path.
/// </summary>
/// <param name="resourcePath">The path to the resource.</param>
/// <returns>A sprite made from the resource</returns>
/// <exception cref="Exception">The resource cannot be found.</exception>
public static Sprite LoadSpriteFromPath(string resourcePath)
{
var tex = new Texture2D(1, 1, TextureFormat.ARGB32, false);
var assembly = Assembly.GetExecutingAssembly();
var myStream = assembly.GetManifestResourceStream(resourcePath);
if (myStream != null)
{
var buttonTexture = myStream.ReadFully();
LoadImage(tex, buttonTexture, false);
}
else
{
Logger<MiraApiPlugin>.Error($"Resource not found: {resourcePath}\nReturning empty sprite!");
}
return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
}
return _iCallLoadImage.Invoke(tex.Pointer, il2CPPArray.Pointer, markNonReadable);
}
}
/// <summary>
/// Load a sprite from a resource path.
/// </summary>
/// <param name="resourcePath">The path to the resource.</param>
/// <returns>A sprite made from the resource</returns>
/// <exception cref="Exception">The resource cannot be found.</exception>
public static Sprite LoadSpriteFromPath(string resourcePath)
{
var tex = new Texture2D(1, 1, TextureFormat.ARGB32, false);
var assembly = Assembly.GetExecutingAssembly();
var myStream = assembly.GetManifestResourceStream(resourcePath);
if (myStream != null)
{
var buttonTexture = myStream.ReadFully();
LoadImage(tex, buttonTexture, false);
}
else
{
Logger<MiraApiPlugin>.Error($"Resource not found: {resourcePath}\nReturning empty sprite!");
}
return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
}
}
+75 -76
View File
@@ -4,93 +4,92 @@ using Reactor.Utilities.Extensions;
using System.Linq;
using UnityEngine;
namespace MiraAPI.Utilities
namespace MiraAPI.Utilities;
public static class Extensions
{
public static class Extensions
public static bool IsCustom(this OptionBehaviour optionBehaviour)
{
public static bool IsCustom(this OptionBehaviour optionBehaviour)
return ModdedOptionsManager.Options.Any(opt => opt.OptionBehaviour && opt.OptionBehaviour.Equals(optionBehaviour));
}
public static Color DarkenColor(this Color color)
{
return new Color(color.r - 0.3f, color.g - 0.3f, color.b - 0.3f);
}
public static void UpdateBodies(this PlayerControl playerControl, Color outlineColor, ref DeadBody target)
{
foreach (var body in Object.FindObjectsOfType<DeadBody>())
{
return ModdedOptionsManager.Options.Any(opt => opt.OptionBehaviour && opt.OptionBehaviour.Equals(optionBehaviour));
}
public static Color DarkenColor(this Color color)
{
return new Color(color.r - 0.3f, color.g - 0.3f, color.b - 0.3f);
}
public static void UpdateBodies(this PlayerControl playerControl, Color outlineColor, ref DeadBody target)
{
foreach (var body in Object.FindObjectsOfType<DeadBody>())
foreach (var bodyRenderer in body.bodyRenderers)
{
foreach (var bodyRenderer in body.bodyRenderers)
{
bodyRenderer.SetOutline(null);
}
}
if (playerControl.Data.Role is not ICustomRole { TargetsBodies: true })
{
return;
}
target = playerControl.NearestDeadBody();
if (!target)
{
return;
}
foreach (var renderer in target.bodyRenderers)
{
renderer.SetOutline(outlineColor);
bodyRenderer.SetOutline(null);
}
}
public static DeadBody NearestDeadBody(this PlayerControl playerControl)
if (playerControl.Data.Role is not ICustomRole { TargetsBodies: true })
{
var results = new Il2CppSystem.Collections.Generic.List<Collider2D>();
Physics2D.OverlapCircle(playerControl.GetTruePosition(), playerControl.MaxReportDistance / 4f, Helpers.Filter, results);
return results.ToArray()
.Where(collider2D => collider2D.CompareTag("DeadBody"))
.Select(collider2D => collider2D.GetComponent<DeadBody>())
.FirstOrDefault(component => component && !component.Reported);
return;
}
public static PlayerControl GetClosestPlayer(this PlayerControl playerControl, bool includeImpostors, float distance)
target = playerControl.NearestDeadBody();
if (!target)
{
PlayerControl result = null;
if (!ShipStatus.Instance)
{
return null;
}
return;
}
var truePosition = playerControl.GetTruePosition();
foreach (var playerInfo in GameData.Instance.AllPlayers)
{
if (playerInfo.Disconnected || playerInfo.PlayerId == playerControl.PlayerId ||
playerInfo.IsDead || !includeImpostors && playerInfo.Role.IsImpostor)
{
continue;
}
var @object = playerInfo.Object;
if (!@object)
{
continue;
}
var vector = @object.GetTruePosition() - truePosition;
var magnitude = vector.magnitude;
if (!(magnitude <= distance) || PhysicsHelpers.AnyNonTriggersBetween(truePosition,
vector.normalized,
magnitude, LayerMask.GetMask("Ship", "Objects")))
{
continue;
}
result = @object;
distance = magnitude;
}
return result;
foreach (var renderer in target.bodyRenderers)
{
renderer.SetOutline(outlineColor);
}
}
}
public static DeadBody NearestDeadBody(this PlayerControl playerControl)
{
var results = new Il2CppSystem.Collections.Generic.List<Collider2D>();
Physics2D.OverlapCircle(playerControl.GetTruePosition(), playerControl.MaxReportDistance / 4f, Helpers.Filter, results);
return results.ToArray()
.Where(collider2D => collider2D.CompareTag("DeadBody"))
.Select(collider2D => collider2D.GetComponent<DeadBody>())
.FirstOrDefault(component => component && !component.Reported);
}
public static PlayerControl GetClosestPlayer(this PlayerControl playerControl, bool includeImpostors, float distance)
{
PlayerControl result = null;
if (!ShipStatus.Instance)
{
return null;
}
var truePosition = playerControl.GetTruePosition();
foreach (var playerInfo in GameData.Instance.AllPlayers)
{
if (playerInfo.Disconnected || playerInfo.PlayerId == playerControl.PlayerId ||
playerInfo.IsDead || !includeImpostors && playerInfo.Role.IsImpostor)
{
continue;
}
var @object = playerInfo.Object;
if (!@object)
{
continue;
}
var vector = @object.GetTruePosition() - truePosition;
var magnitude = vector.magnitude;
if (!(magnitude <= distance) || PhysicsHelpers.AnyNonTriggersBetween(truePosition,
vector.normalized,
magnitude, LayerMask.GetMask("Ship", "Objects")))
{
continue;
}
result = @object;
distance = magnitude;
}
return result;
}
}
+33 -29
View File
@@ -3,35 +3,39 @@ using System.Linq;
using System.Text;
using UnityEngine;
namespace MiraAPI.Utilities
namespace MiraAPI.Utilities;
public static class Helpers
{
public static class Helpers
public static readonly ContactFilter2D Filter = ContactFilter2D.CreateLegacyFilter(Constants.NotShipMask, float.MinValue, float.MaxValue);
public static PlainShipRoom GetRoom(Vector3 pos)
{
public static readonly ContactFilter2D Filter = ContactFilter2D.CreateLegacyFilter(Constants.NotShipMask, float.MinValue, float.MaxValue);
public static PlainShipRoom GetRoom(Vector3 pos)
{
return ShipStatus.Instance.AllRooms.ToList().Find(room => room.roomArea.OverlapPoint(pos));
}
public static string GetSuffix(NumberSuffixes suffix)
{
return suffix switch
{
NumberSuffixes.None => string.Empty,
NumberSuffixes.Multiplier => "x",
NumberSuffixes.Seconds => "s",
_ => string.Empty
};
}
public static StringBuilder CreateForRole(ICustomRole role)
{
var taskStringBuilder = new StringBuilder();
taskStringBuilder.AppendLine($"{role.RoleColor.ToTextColor()}You are a <b>{role.RoleName}.</b></color>");
taskStringBuilder.Append("<size=70%>");
taskStringBuilder.AppendLine($"{role.RoleLongDescription}");
return taskStringBuilder;
}
return ShipStatus.Instance.AllRooms.ToList().Find(room => room.roomArea.OverlapPoint(pos));
}
}
public static DeadBody GetBodyById(byte id)
{
return Object.FindObjectsOfType<DeadBody>().FirstOrDefault(body => body.ParentId == id);
}
public static string GetSuffix(NumberSuffixes suffix)
{
return suffix switch
{
NumberSuffixes.None => string.Empty,
NumberSuffixes.Multiplier => "x",
NumberSuffixes.Seconds => "s",
_ => string.Empty
};
}
public static StringBuilder CreateForRole(ICustomRole role)
{
var taskStringBuilder = new StringBuilder();
taskStringBuilder.AppendLine($"{role.RoleColor.ToTextColor()}You are a <b>{role.RoleName}.</b></color>");
taskStringBuilder.Append("<size=70%>");
taskStringBuilder.AppendLine($"{role.RoleLongDescription}");
return taskStringBuilder;
}
}