mirror of
https://github.com/All-Of-Us-Mods/MiraAPI.git
synced 2026-10-20 01:46:15 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19c7e38690 | ||
|
|
f1639a784d | ||
|
|
5f1996b457 | ||
|
|
33d389e107 | ||
|
|
176d472cd7 | ||
|
|
7a3406e0ae | ||
|
|
9f92af8958 | ||
|
|
8d167596d2 | ||
|
|
a98a37bea7 | ||
|
|
4963c80395 | ||
|
|
4bef2f838d | ||
|
|
763017b6e2 | ||
|
|
16fd8e02aa | ||
|
|
f187a15f2e | ||
|
|
e211c4c49c | ||
|
|
7f532cd82f | ||
|
|
7a0396fe5c | ||
|
|
d4955b5183 | ||
|
|
0a5c59d9cd | ||
|
|
774e1a7a2b | ||
|
|
8e6f75cfbd | ||
|
|
b36b434a99 | ||
|
|
858e518a57 | ||
|
|
b9734f5a1c | ||
|
|
1cb11be9b0 | ||
|
|
6bc6ab7143 | ||
|
|
05fdf5313d |
No files matched your search
@@ -1,29 +0,0 @@
|
||||
using MiraAPI.Example.Modifiers;
|
||||
using MiraAPI.Hud;
|
||||
using MiraAPI.Utilities;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using Reactor.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.Buttons;
|
||||
|
||||
[RegisterButton]
|
||||
public class ExampleButton : CustomActionButton
|
||||
{
|
||||
public override string Name => "Example Button";
|
||||
public override float Cooldown => 5f;
|
||||
public override float EffectDuration => 0f;
|
||||
public override int MaxUses => 5;
|
||||
public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton;
|
||||
public override ButtonLocation Location => ButtonLocation.BottomRight;
|
||||
|
||||
protected override void OnClick()
|
||||
{
|
||||
Logger<ExamplePlugin>.Info("Example button clicked!");
|
||||
}
|
||||
|
||||
public override bool Enabled(RoleBehaviour role)
|
||||
{
|
||||
return PlayerControl.LocalPlayer.HasModifier<GameModifierExample>();
|
||||
}
|
||||
}
|
||||
+13
-9
@@ -1,20 +1,24 @@
|
||||
using MiraAPI.Hud;
|
||||
using MiraAPI.Example.Modifiers.Freezer;
|
||||
using MiraAPI.Example.Roles;
|
||||
using MiraAPI.Hud;
|
||||
using MiraAPI.Utilities;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.Buttons;
|
||||
namespace MiraAPI.Example.Buttons.Freezer;
|
||||
|
||||
public class ExampleTargetButton : CustomActionButton<PlayerControl>
|
||||
[RegisterButton]
|
||||
public class FreezeButton : CustomActionButton<PlayerControl>
|
||||
{
|
||||
public override string Name => "Shoot";
|
||||
public override float Cooldown => 0f;
|
||||
public override string Name => "Freeze";
|
||||
public override float Cooldown => 5f;
|
||||
public override float EffectDuration => 0f;
|
||||
public override int MaxUses => 0;
|
||||
public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton;
|
||||
|
||||
protected override void OnClick()
|
||||
{
|
||||
PlayerControl.LocalPlayer.CmdCheckMurder(Target);
|
||||
Target.AddModifier<FreezeModifier>();
|
||||
}
|
||||
|
||||
public override PlayerControl GetTarget()
|
||||
@@ -24,17 +28,17 @@ public class ExampleTargetButton : CustomActionButton<PlayerControl>
|
||||
|
||||
public override void SetOutline(bool active)
|
||||
{
|
||||
Target?.cosmetics.SetOutline(active, new Il2CppSystem.Nullable<Color>(Color.red));
|
||||
Target?.cosmetics.SetOutline(active, new Il2CppSystem.Nullable<Color>(Palette.Blue));
|
||||
}
|
||||
|
||||
public override bool IsTargetValid(PlayerControl target)
|
||||
{
|
||||
return PlayerControl.LocalPlayer.Data.Role.IsValidTarget(target.Data);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool Enabled(RoleBehaviour role)
|
||||
{
|
||||
return role.IsImpostor;
|
||||
return role is FreezerRole;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using MiraAPI.Example;
|
||||
using MiraAPI.Example.Modifiers;
|
||||
using MiraAPI.Hud;
|
||||
using MiraAPI.Utilities;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using UnityEngine;
|
||||
|
||||
[RegisterButton]
|
||||
public class MeetingButton : CustomActionButton
|
||||
{
|
||||
public override string Name => "Call Meeting";
|
||||
|
||||
public override float Cooldown => 15;
|
||||
|
||||
public override float EffectDuration => 0;
|
||||
|
||||
public override int MaxUses => 3;
|
||||
|
||||
public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton;
|
||||
|
||||
public override bool Enabled(RoleBehaviour role)
|
||||
{
|
||||
return PlayerControl.LocalPlayer.HasModifier<CaptainModifier>();
|
||||
}
|
||||
|
||||
protected override void OnClick()
|
||||
{
|
||||
var bt = ShipStatus.Instance.EmergencyButton;
|
||||
|
||||
PlayerControl.LocalPlayer.NetTransform.Halt();
|
||||
var minigame = Object.Instantiate(bt.MinigamePrefab, Camera.main!.transform, false);
|
||||
|
||||
var taskAdderGame = minigame as TaskAdderGame;
|
||||
if (taskAdderGame != null)
|
||||
{
|
||||
taskAdderGame.SafePositionWorld = bt.SafePositionLocal + (Vector2)bt.transform.position;
|
||||
}
|
||||
|
||||
minigame.transform.localPosition = new Vector3(0f, 0f, -50f);
|
||||
minigame.Begin(null);
|
||||
|
||||
if (UsesLeft == 0 && PlayerControl.LocalPlayer.HasModifier<CaptainModifier>())
|
||||
{
|
||||
PlayerControl.LocalPlayer.RemoveModifier<CaptainModifier>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
using MiraAPI.Example.Options.Roles;
|
||||
using MiraAPI.Example.Roles;
|
||||
using MiraAPI.GameOptions;
|
||||
using MiraAPI.Hud;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using Reactor.Utilities;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.Buttons.Teleporter;
|
||||
[RegisterButton]
|
||||
public class TeleportButton : CustomActionButton
|
||||
{
|
||||
public override string Name => "Teleport";
|
||||
|
||||
public override float Cooldown => OptionGroupSingleton<TeleporterOptions>.Instance.TeleportCooldown;
|
||||
|
||||
public override float EffectDuration => OptionGroupSingleton<TeleporterOptions>.Instance.TeleportDuration;
|
||||
|
||||
public override int MaxUses => 0;
|
||||
|
||||
public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton;
|
||||
public static bool IsZoom { get; private set; }
|
||||
|
||||
public override bool Enabled(RoleBehaviour role)
|
||||
{
|
||||
return role is TeleporterRole;
|
||||
}
|
||||
protected override void OnClick()
|
||||
{
|
||||
Coroutines.Start(ZoomOutCoroutine());
|
||||
}
|
||||
|
||||
public override void OnEffectEnd()
|
||||
{
|
||||
Coroutines.Start(ZoomInCoroutine());
|
||||
}
|
||||
|
||||
protected override void FixedUpdate(PlayerControl playerControl)
|
||||
{
|
||||
base.FixedUpdate(playerControl);
|
||||
|
||||
if (!EffectActive) return;
|
||||
|
||||
if (Input.GetKey(KeyCode.Mouse0))
|
||||
{
|
||||
playerControl.NetTransform.RpcSnapTo(Camera.main.ScreenToWorldPoint(Input.mousePosition));
|
||||
ResetCooldownAndOrEffect();
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerator ZoomOutCoroutine()
|
||||
{
|
||||
HudManager.Instance.ShadowQuad.gameObject.SetActive(false);
|
||||
IsZoom = true;
|
||||
var zoomDistance = OptionGroupSingleton<TeleporterOptions>.Instance.ZoomDistance;
|
||||
for (var ft = Camera.main!.orthographicSize; ft < zoomDistance; ft += 0.3f)
|
||||
{
|
||||
Camera.main.orthographicSize = MeetingHud.Instance ? 3f : ft;
|
||||
ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height, Screen.width, Screen.height, Screen.fullScreen);
|
||||
foreach (var cam in Camera.allCameras) cam.orthographicSize = Camera.main.orthographicSize;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
foreach (var cam in Camera.allCameras) cam.orthographicSize = zoomDistance;
|
||||
ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height, Screen.width, Screen.height, Screen.fullScreen);
|
||||
}
|
||||
|
||||
private static IEnumerator ZoomInCoroutine()
|
||||
{
|
||||
for (var ft = Camera.main!.orthographicSize; ft > 3f; ft -= 0.3f)
|
||||
{
|
||||
Camera.main.orthographicSize = MeetingHud.Instance ? 3f : ft;
|
||||
ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height, Screen.width, Screen.height, Screen.fullScreen);
|
||||
foreach (var cam in Camera.allCameras) cam.orthographicSize = Camera.main.orthographicSize;
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
foreach (var cam in Camera.allCameras) cam.orthographicSize = 3f;
|
||||
HudManager.Instance.ShadowQuad.gameObject.SetActive(true);
|
||||
IsZoom = false;
|
||||
|
||||
ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height, Screen.width, Screen.height, Screen.fullScreen);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
using MiraAPI.Utilities;
|
||||
using MiraAPI.Example.Modifiers;
|
||||
using MiraAPI.Utilities;
|
||||
using Reactor.Utilities.Attributes;
|
||||
using Reactor.Utilities.ImGui;
|
||||
using System;
|
||||
using MiraAPI.Example.Modifiers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example;
|
||||
@@ -13,11 +13,11 @@ public class MiraDebugWindow(IntPtr ptr) : MonoBehaviour(ptr)
|
||||
{
|
||||
if (GUILayout.Button("Test modifier"))
|
||||
{
|
||||
PlayerControl.LocalPlayer.AddModifier<ModifierTimerExample>();
|
||||
//PlayerControl.LocalPlayer.AddModifier<ModifierTimerExample>();
|
||||
}
|
||||
if (GUILayout.Button("Remove modifier"))
|
||||
{
|
||||
PlayerControl.LocalPlayer.RemoveModifier<ModifierTimerExample>();
|
||||
//PlayerControl.LocalPlayer.RemoveModifier<ModifierTimerExample>();
|
||||
}
|
||||
})
|
||||
{
|
||||
|
||||
+2
-8
@@ -4,15 +4,9 @@ using MiraAPI.Modifiers.Types;
|
||||
namespace MiraAPI.Example.Modifiers;
|
||||
|
||||
[RegisterModifier]
|
||||
public class GameModifierExample : GameModifier
|
||||
public class CaptainModifier : GameModifier
|
||||
{
|
||||
public override string ModifierName => "Example Game Modifier";
|
||||
|
||||
public override bool CanVent()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ModifierName => "Captain";
|
||||
public override int GetAmountPerGame()
|
||||
{
|
||||
return 1;
|
||||
@@ -0,0 +1,30 @@
|
||||
using MiraAPI.Modifiers;
|
||||
using MiraAPI.Modifiers.Types;
|
||||
|
||||
namespace MiraAPI.Example.Modifiers.Freezer;
|
||||
|
||||
[RegisterModifier]
|
||||
public class FreezeModifier : TimedModifier
|
||||
{
|
||||
public override string ModifierName => "Freezed";
|
||||
public override bool HideOnUi => false;
|
||||
public override float Duration => 15f;
|
||||
public override bool AutoStart => true;
|
||||
public override bool RemoveOnComplete => true;
|
||||
|
||||
public override void OnActivate()
|
||||
{
|
||||
if (Player.AmOwner)
|
||||
{
|
||||
Player.moveable = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnTimerComplete()
|
||||
{
|
||||
if (Player.AmOwner)
|
||||
{
|
||||
Player.moveable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using MiraAPI.Modifiers;
|
||||
using MiraAPI.Modifiers.Types;
|
||||
|
||||
namespace MiraAPI.Example.Modifiers;
|
||||
|
||||
[RegisterModifier]
|
||||
public class ModifierTimerExample : TimedModifier
|
||||
{
|
||||
public override string ModifierName => "Color Changer";
|
||||
public override bool HideOnUi => true;
|
||||
public override float Duration => 10f;
|
||||
public override bool AutoStart => true;
|
||||
|
||||
private readonly System.Random _rand = new();
|
||||
|
||||
public override void OnTimerComplete()
|
||||
{
|
||||
Player.SetColor((byte)_rand.Next(0, Palette.PlayerColors.Count));
|
||||
StartTimer();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using MiraAPI.GameOptions;
|
||||
using MiraAPI.GameOptions.Attributes;
|
||||
using MiraAPI.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Example.Options;
|
||||
@@ -15,7 +16,7 @@ public class ExampleOptions : AbstractOptionGroup
|
||||
[ModdedToggleOption("Toggle Opt 2")]
|
||||
public bool ToggleOpt2 { get; set; } = true;
|
||||
|
||||
[ModdedNumberOption("Number Opt", min: 0, max: 10)]
|
||||
[ModdedNumberOption("Number Opt", min: 0, max: 10, suffixType: MiraNumberSuffixes.Percent)]
|
||||
public float NumberOpt { get; set; } = 4f;
|
||||
|
||||
[ModdedStringOption("String Opt", ["Hello", "Hey", "Bye"])]
|
||||
|
||||
@@ -9,7 +9,7 @@ public class CustomRole2Settings : AbstractOptionGroup
|
||||
{
|
||||
public override string GroupName => "Custom Role";
|
||||
|
||||
public override Type AdvancedRole => typeof(CustomRole2);
|
||||
public override Type AdvancedRole => typeof(FreezerRole);
|
||||
|
||||
[ModdedToggleOption("Teleportation ability")] public bool Teleport { get; set; } = true;
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
using MiraAPI.Example.Roles;
|
||||
using MiraAPI.GameOptions;
|
||||
using MiraAPI.GameOptions.Attributes;
|
||||
using System;
|
||||
|
||||
namespace MiraAPI.Example.Options.Roles;
|
||||
|
||||
public class CustomRoleSettings : AbstractOptionGroup
|
||||
{
|
||||
public override string GroupName => "Custom Role";
|
||||
|
||||
public override Type AdvancedRole => typeof(CustomRole);
|
||||
|
||||
[ModdedNumberOption("Number Opt", min: 3, max: 9)] public float NumberOpt { get; set; } = 4;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using MiraAPI.Example.Roles;
|
||||
using MiraAPI.GameOptions;
|
||||
using MiraAPI.GameOptions.Attributes;
|
||||
using MiraAPI.Utilities;
|
||||
using System;
|
||||
|
||||
namespace MiraAPI.Example.Options.Roles;
|
||||
|
||||
public class TeleporterOptions : AbstractOptionGroup
|
||||
{
|
||||
public override string GroupName => "Teleporter";
|
||||
|
||||
public override Type AdvancedRole => typeof(TeleporterRole);
|
||||
|
||||
[ModdedNumberOption("Teleport Cooldown", 5, 60, 2.5f, MiraNumberSuffixes.Seconds)]
|
||||
public float TeleportCooldown { get; set; } = 5;
|
||||
|
||||
[ModdedNumberOption("Teleport Duration", 5, 25, 1, MiraNumberSuffixes.Seconds)]
|
||||
public float TeleportDuration { get; set; } = 10;
|
||||
|
||||
[ModdedNumberOption("Zoom Distance", 4, 15)]
|
||||
public float ZoomDistance { get; set; } = 6;
|
||||
}
|
||||
@@ -5,12 +5,12 @@ using UnityEngine;
|
||||
namespace MiraAPI.Example.Roles;
|
||||
|
||||
[RegisterCustomRole]
|
||||
public class CustomRole : ImpostorRole, ICustomRole
|
||||
public class FreezerRole : ImpostorRole, ICustomRole
|
||||
{
|
||||
public string RoleName => "Custom Role";
|
||||
public string RoleLongDescription => "Eliminate everyone with your special ability!";
|
||||
public string RoleName => "Freezer";
|
||||
public string RoleLongDescription => "Freeze another player for a duration of time.";
|
||||
public string RoleDescription => RoleLongDescription;
|
||||
public Color RoleColor => Palette.Black;
|
||||
public Color RoleColor => Palette.Blue;
|
||||
public ModdedRoleTeams Team => ModdedRoleTeams.Impostor;
|
||||
public LoadableAsset<Sprite> OptionsScreenshot => ExampleAssets.Banner;
|
||||
|
||||
@@ -5,12 +5,12 @@ using UnityEngine;
|
||||
namespace MiraAPI.Example.Roles;
|
||||
|
||||
[RegisterCustomRole]
|
||||
public class CustomRole2 : CrewmateRole, ICustomRole
|
||||
public class TeleporterRole : CrewmateRole, ICustomRole
|
||||
{
|
||||
public string RoleName => "Custom Role 2";
|
||||
public string RoleLongDescription => "Save everyone from dying!";
|
||||
public string RoleName => "Teleporter";
|
||||
public string RoleLongDescription => "Zoom out and teleport across the map!";
|
||||
public string RoleDescription => RoleLongDescription;
|
||||
public Color RoleColor => Palette.AcceptedGreen;
|
||||
public Color RoleColor => new Color32(221, 176, 152, 255);
|
||||
public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate;
|
||||
public LoadableAsset<Sprite> OptionsScreenshot => ExampleAssets.Banner;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using MiraAPI.GameOptions.OptionTypes;
|
||||
using MiraAPI.Utilities;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
@@ -9,7 +10,7 @@ public class ModdedNumberOptionAttribute(
|
||||
float min,
|
||||
float max,
|
||||
float increment = 1,
|
||||
NumberSuffixes suffixType = NumberSuffixes.None,
|
||||
MiraNumberSuffixes suffixType = MiraNumberSuffixes.None,
|
||||
bool zeroInfinity = false,
|
||||
Type roleType = null)
|
||||
: ModdedOptionAttribute(title, roleType)
|
||||
|
||||
@@ -129,6 +129,11 @@ public static class ModdedOptionsManager
|
||||
|
||||
option.HandleNetData(netData.Data);
|
||||
}
|
||||
|
||||
if (LobbyInfoPane.Instance)
|
||||
{
|
||||
LobbyInfoPane.Instance.RefreshPane();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using AmongUs.GameOptions;
|
||||
using AmongUs.GameOptions;
|
||||
using MiraAPI.Networking;
|
||||
using MiraAPI.Utilities;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
@@ -9,17 +9,17 @@ namespace MiraAPI.GameOptions.OptionTypes;
|
||||
|
||||
public class ModdedNumberOption : ModdedOption<float>
|
||||
{
|
||||
public float Min { get;}
|
||||
|
||||
public float Min { get; }
|
||||
|
||||
public float Max { get; }
|
||||
|
||||
|
||||
public float Increment { get; }
|
||||
|
||||
public NumberSuffixes SuffixType { get; }
|
||||
|
||||
|
||||
public MiraNumberSuffixes SuffixType { get; }
|
||||
|
||||
public bool ZeroInfinity { get; }
|
||||
|
||||
public ModdedNumberOption(string title, float defaultValue, float min, float max, float increment, NumberSuffixes suffixType, bool zeroInfinity=false, Type roleType=null) : base(title, defaultValue, roleType)
|
||||
|
||||
public ModdedNumberOption(string title, float defaultValue, float min, float max, float increment, MiraNumberSuffixes suffixType, bool zeroInfinity = false, Type roleType = null) : base(title, defaultValue, roleType)
|
||||
{
|
||||
Min = min;
|
||||
Max = max;
|
||||
@@ -28,18 +28,18 @@ public class ModdedNumberOption : ModdedOption<float>
|
||||
ZeroInfinity = zeroInfinity;
|
||||
|
||||
Value = Mathf.Clamp(defaultValue, min, max);
|
||||
|
||||
|
||||
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 = Increment % 1 == 0 && Value % 1 == 0 && Min % 1 == 0 && Max % 1 == 0 ? "0" : "0.0";
|
||||
data.FormatString = Increment % 1 == 0 && Value % 1 == 0 && Min % 1 == 0 && Max % 1 == 0 ? "0" : "0.0";
|
||||
data.ZeroIsInfinity = ZeroInfinity;
|
||||
data.SuffixType = SuffixType;
|
||||
data.SuffixType = (NumberSuffixes)SuffixType;
|
||||
data.OptionName = FloatOptionNames.Invalid;
|
||||
}
|
||||
|
||||
@@ -49,17 +49,17 @@ public class ModdedNumberOption : ModdedOption<float>
|
||||
|
||||
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 = ((FloatGameSetting)Data).FormatString;
|
||||
numberOption.ZeroIsInfinity = ZeroInfinity;
|
||||
numberOption.SuffixType = SuffixType;
|
||||
numberOption.SuffixType = (NumberSuffixes)SuffixType;
|
||||
numberOption.floatOptionName = FloatOptionNames.Invalid;
|
||||
|
||||
|
||||
|
||||
|
||||
OptionBehaviour = numberOption;
|
||||
|
||||
return numberOption;
|
||||
|
||||
@@ -3,6 +3,7 @@ using MiraAPI.Utilities;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace MiraAPI.Hud;
|
||||
|
||||
@@ -70,7 +71,7 @@ public abstract class CustomActionButton
|
||||
/// The button object in game. This is created by Mira API automatically.
|
||||
/// </summary>
|
||||
protected ActionButton? Button { get; private set; }
|
||||
|
||||
|
||||
internal void CreateButton(Transform parent)
|
||||
{
|
||||
if (Button)
|
||||
@@ -95,24 +96,24 @@ public abstract class CustomActionButton
|
||||
}
|
||||
|
||||
var pb = Button.GetComponent<PassiveButton>();
|
||||
pb.OnClick.RemoveAllListeners();
|
||||
pb.OnClick = new Button.ButtonClickedEvent();
|
||||
pb.OnClick.AddListener((UnityAction)ClickHandler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A utility function to reset the cooldown of the button.
|
||||
/// A utility function to reset the cooldown and/or effect of the button.
|
||||
/// </summary>
|
||||
public void ResetCooldown()
|
||||
public void ResetCooldownAndOrEffect()
|
||||
{
|
||||
Timer = Cooldown;
|
||||
if (EffectActive)
|
||||
{
|
||||
OnEffectEnd();
|
||||
}
|
||||
|
||||
|
||||
EffectActive = false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A utility function to override the sprite of the button.
|
||||
/// </summary>
|
||||
@@ -135,13 +136,13 @@ public abstract class CustomActionButton
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A utility function that runs with the local PlayerControl's FixedUpdate.
|
||||
/// A utility function that runs with the local PlayerControl's FixedUpdate if the button is enabled.
|
||||
/// </summary>
|
||||
/// <param name="playerControl">the local PlayerControl</param>
|
||||
protected virtual void FixedUpdate(PlayerControl playerControl) { }
|
||||
|
||||
/// <summary>
|
||||
/// Runs when the button is clicked.
|
||||
/// Callback method for the button click event.
|
||||
/// </summary>
|
||||
protected abstract void OnClick();
|
||||
|
||||
@@ -153,7 +154,8 @@ public abstract class CustomActionButton
|
||||
public abstract bool Enabled(RoleBehaviour? role);
|
||||
|
||||
/// <summary>
|
||||
/// Given that there is an effect, this method that runs when the effect ends.
|
||||
/// Given that there is an effect, this method runs when the effect ends.
|
||||
/// <br /> <br /> THIS IS A CALLBACK METHOD! Use <see cref="ResetCooldownAndOrEffect" /> if you want to end the effect.
|
||||
/// </summary>
|
||||
public virtual void OnEffectEnd() { }
|
||||
|
||||
@@ -238,7 +240,7 @@ public abstract class CustomActionButton
|
||||
{
|
||||
Button?.SetDisabled();
|
||||
}
|
||||
|
||||
|
||||
Button?.SetCoolDown(Timer, EffectActive ? EffectDuration : Cooldown);
|
||||
|
||||
FixedUpdate(playerControl);
|
||||
@@ -255,12 +257,12 @@ public abstract class CustomActionButton<T> : CustomActionButton where T : MonoB
|
||||
/// The target object of the button.
|
||||
/// </summary>
|
||||
public T? Target { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The distance the player must be from the target object to use the button.
|
||||
/// </summary>
|
||||
public virtual float Distance => PlayerControl.LocalPlayer.Data.Role.GetAbilityDistance();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// An optional collider tag to filter the target object by.
|
||||
/// </summary>
|
||||
@@ -269,26 +271,23 @@ public abstract class CustomActionButton<T> : CustomActionButton where T : MonoB
|
||||
/// <summary>
|
||||
/// Determines if the target object is valid.
|
||||
/// </summary>
|
||||
public virtual bool IsTargetValid(T target)
|
||||
public virtual bool IsTargetValid(T? target)
|
||||
{
|
||||
return target;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The method used to get the target object.
|
||||
/// </summary>
|
||||
public virtual T? GetTarget()
|
||||
{
|
||||
return PlayerControl.LocalPlayer.GetNearestObjectOfType<T>(Distance, ColliderTag, IsTargetValid);
|
||||
}
|
||||
public abstract T? GetTarget();
|
||||
|
||||
/// <summary>
|
||||
/// Sets the outline of the target object.
|
||||
/// </summary>
|
||||
/// <param name="active">Should the outline be active</param>
|
||||
public abstract void SetOutline(bool active);
|
||||
|
||||
|
||||
|
||||
|
||||
public override bool CanUse()
|
||||
{
|
||||
var newTarget = GetTarget();
|
||||
@@ -297,9 +296,9 @@ public abstract class CustomActionButton<T> : CustomActionButton where T : MonoB
|
||||
SetOutline(false);
|
||||
}
|
||||
|
||||
Target = newTarget;
|
||||
Target = IsTargetValid(newTarget) ? newTarget : null;
|
||||
SetOutline(true);
|
||||
|
||||
|
||||
return base.CanUse() && Target;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
<LangVersion>latest</LangVersion>
|
||||
<DebugType>embedded</DebugType>
|
||||
<PackageId>AllOfUs.MiraAPI</PackageId>
|
||||
<Version>0.1.0</Version>
|
||||
<Version>0.1.2</Version>
|
||||
<Description>Simple and easy to use Among Us modding API.</Description>
|
||||
<Authors>Angxl, XtraCube</Authors>
|
||||
<Company>All Of Us</Company>
|
||||
|
||||
@@ -26,7 +26,7 @@ public partial class MiraApiPlugin : BasePlugin
|
||||
{
|
||||
Harmony.PatchAll();
|
||||
|
||||
ReactorCredits.Register("Mira API", Version.Truncate(11, "") ?? Version, true, ReactorCredits.AlwaysShow);
|
||||
ReactorCredits.Register("Mira API", Version, true, ReactorCredits.AlwaysShow);
|
||||
|
||||
PluginManager = new MiraPluginManager();
|
||||
PluginManager.Initialize();
|
||||
|
||||
@@ -84,7 +84,7 @@ public class ModifierComponent(IntPtr ptr) : MonoBehaviour(ptr)
|
||||
|
||||
var modifierComponent = target.GetModifierComponent();
|
||||
|
||||
var modifier = modifierComponent.ActiveModifiers.Find(x => x.GetType() == type);
|
||||
var modifier = modifierComponent?.ActiveModifiers.Find(x => x.GetType() == type);
|
||||
|
||||
if (modifier is null)
|
||||
{
|
||||
|
||||
@@ -6,6 +6,8 @@ using Reactor.Networking.Rpc;
|
||||
using Reactor.Utilities.Extensions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Reactor.Utilities;
|
||||
using Random = System.Random;
|
||||
|
||||
namespace MiraAPI.Modifiers;
|
||||
@@ -40,12 +42,27 @@ public static class ModifierManager
|
||||
|
||||
List<uint> filteredModifiers = [];
|
||||
|
||||
foreach (var modifier in IdToTypeModifiers)
|
||||
foreach (var modifier in IdToTypeModifiers.Where(pair => pair.Value.IsAssignableTo(typeof(GameModifier))))
|
||||
{
|
||||
var mod = (GameModifier)Activator.CreateInstance(modifier.Value);
|
||||
var num = mod.GetAmountPerGame();
|
||||
var chance = mod.GetAssignmentChance();
|
||||
|
||||
if (mod is null)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Failed to create instance of {modifier.Value.Name}");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!plrs.Any(x=>IsGameModifierValid(x, mod, modifier.Key)))
|
||||
{
|
||||
Logger<MiraApiPlugin>.Warning("No players are valid for modifier: " + mod.ModifierName);
|
||||
continue;
|
||||
}
|
||||
|
||||
var maxCount = plrs.Count(x=>IsGameModifierValid(x, mod, modifier.Key));
|
||||
|
||||
var num = Math.Clamp(mod.GetAmountPerGame(), 0, maxCount);
|
||||
var chance = mod.GetAssignmentChance();
|
||||
|
||||
for (var i = 0; i < num; i++)
|
||||
{
|
||||
var randomNum = rand.Next(100);
|
||||
@@ -62,23 +79,28 @@ public static class ModifierManager
|
||||
{
|
||||
shuffledModifiers = shuffledModifiers.GetRange(0, plrs.Count);
|
||||
}
|
||||
|
||||
|
||||
while (shuffledModifiers.Count > 0)
|
||||
{
|
||||
var id = shuffledModifiers[0];
|
||||
|
||||
var mod = (GameModifier)Activator.CreateInstance(IdToTypeModifiers[id]);
|
||||
|
||||
if (mod is null)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Failed to create instance of {IdToTypeModifiers[id].Name}");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!plrs.Any(x=>IsGameModifierValid(x, mod, id)))
|
||||
{
|
||||
shuffledModifiers.RemoveAt(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
var plr = plrs.Random();
|
||||
|
||||
if (plr.Data.Role is ICustomRole modRole)
|
||||
{
|
||||
if (!modRole.IsModifierApplicable(mod))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (plr.HasModifier(id) || mod.IsModifierValidOn(plr.Data.Role))
|
||||
if (!IsGameModifierValid(plr, mod, id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -88,26 +110,23 @@ public static class ModifierManager
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsGameModifierValid(PlayerControl player, GameModifier modifier, uint modifierId)
|
||||
{
|
||||
return (player.Data.Role is not ICustomRole role || role.IsModifierApplicable(modifier)) &&
|
||||
modifier.IsModifierValidOn(player.Data.Role) &&
|
||||
!player.HasModifier(modifierId);
|
||||
}
|
||||
|
||||
internal static void SyncAllModifiers(int targetId = -1)
|
||||
{
|
||||
var data = new List<NetData>();
|
||||
|
||||
if (targetId == -1)
|
||||
foreach (var player in GameData.Instance.AllPlayers)
|
||||
{
|
||||
foreach (var player in GameData.Instance.AllPlayers)
|
||||
{
|
||||
data.Add(GetPlayerModifiers(player.Object));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var player = GameData.Instance.GetPlayerById((byte)targetId).Object;
|
||||
|
||||
data.Add(GetPlayerModifiers(player));
|
||||
data.Add(GetPlayerModifiers(player.Object));
|
||||
}
|
||||
|
||||
|
||||
Rpc<SyncModifiersRpc>.Instance.Send(PlayerControl.LocalPlayer, data.ToArray(), true);
|
||||
Rpc<SyncModifiersRpc>.Instance.SendTo(PlayerControl.LocalPlayer, targetId, data.ToArray());
|
||||
}
|
||||
|
||||
internal static void HandleSyncModifiers(NetData[] data)
|
||||
|
||||
@@ -6,6 +6,7 @@ public abstract class TimedModifier : BaseModifier
|
||||
{
|
||||
public abstract float Duration { get; }
|
||||
public virtual bool AutoStart => false;
|
||||
public virtual bool RemoveOnComplete => true;
|
||||
public abstract void OnTimerComplete();
|
||||
|
||||
public bool TimerActive { get; protected set; }
|
||||
@@ -28,6 +29,11 @@ public abstract class TimedModifier : BaseModifier
|
||||
TimerActive = false;
|
||||
TimeRemaining = Duration;
|
||||
OnTimerComplete();
|
||||
|
||||
if (RemoveOnComplete)
|
||||
{
|
||||
ModifierComponent.RpcRemoveModifier(Player, ModifierId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ public static class MeetingHudPatches
|
||||
{
|
||||
foreach (var customActionButton in CustomButtonManager.CustomButtons)
|
||||
{
|
||||
customActionButton.ResetCooldown();
|
||||
customActionButton.ResetCooldownAndOrEffect();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ using MiraAPI.Utilities;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using Reactor.Localization.Utilities;
|
||||
using Reactor.Utilities.Extensions;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
@@ -102,7 +101,7 @@ public static class GameOptionsMenuPatch
|
||||
|
||||
var options = group.Options.Select(opt => opt.CreateOption(__instance.checkboxOrigin,
|
||||
__instance.numberOptionOrigin, __instance.stringOptionOrigin, __instance.settingsContainer));
|
||||
|
||||
|
||||
foreach (var newOpt in options)
|
||||
{
|
||||
newOpt.SetClickMask(__instance.ButtonClickMask);
|
||||
@@ -137,10 +136,10 @@ public static class GameOptionsMenuPatch
|
||||
if (newOpt is ToggleOption toggle)
|
||||
{
|
||||
toggle.CheckMark.sprite = MiraAssets.Checkmark.LoadAsset();
|
||||
|
||||
toggle.CheckMark.color = group.GroupColor != Color.clear ? group.GroupColor : MiraAssets.AcceptedTeal;
|
||||
var rend = toggle.CheckMark.transform.parent.FindChild("ActiveSprite").GetComponent<SpriteRenderer>();
|
||||
rend.sprite = MiraAssets.CheckmarkBox.LoadAsset();
|
||||
rend.color = group.GroupColor;
|
||||
rend.color = group.GroupColor != Color.clear ? group.GroupColor : MiraAssets.AcceptedTeal;
|
||||
}
|
||||
|
||||
__instance.Children.Add(newOpt);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using HarmonyLib;
|
||||
#nullable enable
|
||||
using HarmonyLib;
|
||||
using MiraAPI.PluginLoading;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using Reactor.Utilities.Extensions;
|
||||
@@ -17,9 +18,9 @@ public static class GameSettingMenuPatches
|
||||
{
|
||||
public static int CurrentSelectedMod { get; private set; }
|
||||
|
||||
public static MiraPluginInfo SelectedMod { get; private set; }
|
||||
public static MiraPluginInfo? SelectedMod { get; private set; }
|
||||
|
||||
private static TextMeshPro _text;
|
||||
private static TextMeshPro? _text;
|
||||
|
||||
private static Vector3 _roleBtnOgPos;
|
||||
|
||||
@@ -80,12 +81,12 @@ public static class GameSettingMenuPatches
|
||||
|
||||
private static void UpdateText(GameSettingMenu menu, GameOptionsMenu settings, RolesSettingsMenu roles)
|
||||
{
|
||||
if (CurrentSelectedMod == 0)
|
||||
if (_text is not null && CurrentSelectedMod == 0)
|
||||
{
|
||||
_text.text = "Default";
|
||||
_text.fontSizeMax = 3.2f;
|
||||
}
|
||||
else
|
||||
else if (_text is not null)
|
||||
{
|
||||
_text.fontSizeMax = 2.3f;
|
||||
SelectedMod = MiraPluginManager.Instance.RegisteredPlugins.ElementAt(CurrentSelectedMod - 1).Value;
|
||||
@@ -153,7 +154,7 @@ public static class GameSettingMenuPatches
|
||||
roles.scrollBar.ScrollToTop();
|
||||
}
|
||||
|
||||
if (settings?.Children != null && SelectedMod?.OptionGroups.Count != 0)
|
||||
if (settings.Children != null && SelectedMod?.OptionGroups.Count != 0)
|
||||
{
|
||||
foreach (var child in settings.Children)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
using HarmonyLib;
|
||||
using Il2CppSystem;
|
||||
using MiraAPI.Roles;
|
||||
using System.Linq;
|
||||
|
||||
namespace MiraAPI.Patches.Options;
|
||||
|
||||
[HarmonyPatch(typeof(NotificationPopper))]
|
||||
public class NotificationPopperPatch
|
||||
{
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(NotificationPopper.AddRoleSettingsChangeMessage))]
|
||||
public static bool RoleChangeMsgPatch(NotificationPopper __instance,
|
||||
[HarmonyArgument(0)] StringNames key, [HarmonyArgument(1)] int roleCount, [HarmonyArgument(2)] int roleChance, [HarmonyArgument(3)] RoleTeamTypes teamType,
|
||||
[HarmonyArgument(4)] bool playSound)
|
||||
{
|
||||
if (CustomRoleManager.CustomRoles.Values.Any(role => role.StringName == key))
|
||||
{
|
||||
string item = string.Empty;
|
||||
string text = (teamType == RoleTeamTypes.Crewmate) ? Palette.CrewmateSettingChangeText.ToTextColor() : Palette.ImpostorRed.ToTextColor();
|
||||
item = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.LobbyChangeSettingNotificationRole, new Object[]
|
||||
{
|
||||
string.Concat(
|
||||
[
|
||||
"<font=\"Barlow-Black SDF\" material=\"Barlow-Black Outline\">",
|
||||
text,
|
||||
DestroyableSingleton<TranslationController>.Instance.GetString(key, Array.Empty<Object>()),
|
||||
"</color></font>"
|
||||
]),
|
||||
"<font=\"Barlow-Black SDF\" material=\"Barlow-Black Outline\">" + roleCount.ToString() + "</font>",
|
||||
"<font=\"Barlow-Black SDF\" material=\"Barlow-Black Outline\">" + roleChance.ToString() + "%"
|
||||
});
|
||||
__instance.SettingsChangeMessageLogic(key, item, playSound);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -224,11 +224,20 @@ public static class RoleSettingMenuPatches
|
||||
__instance.roleScreenshot.drawMode = SpriteDrawMode.Sliced;
|
||||
__instance.roleHeaderSprite.color = customRole.RoleColor;
|
||||
__instance.roleHeaderText.color = customRole.RoleColor.GetAlternateColor();
|
||||
|
||||
var bg = __instance.AdvancedRolesSettings.transform.Find("Background");
|
||||
bg.localPosition = new Vector3(1.4041f, -7.08f, 0);
|
||||
bg.GetComponent<SpriteRenderer>().size = new Vector2(89.4628f, 100);
|
||||
|
||||
CreateAdvancedSettings(__instance, role);
|
||||
|
||||
foreach (var optionBehaviour in __instance.advancedSettingChildren)
|
||||
{
|
||||
if (optionBehaviour.IsCustom())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
optionBehaviour.OnValueChanged = new Action<OptionBehaviour>(__instance.ValueChanged);
|
||||
if (AmongUsClient.Instance && !AmongUsClient.Instance.AmHost)
|
||||
{
|
||||
@@ -254,27 +263,28 @@ public static class RoleSettingMenuPatches
|
||||
roleOptionSetting.titleText.transform.localPosition = new Vector3(-0.5376f, -0.2923f, 0f);
|
||||
roleOptionSetting.titleText.color = customRole.RoleColor.GetAlternateColor();
|
||||
roleOptionSetting.titleText.horizontalAlignment = HorizontalAlignmentOptions.Left;
|
||||
|
||||
var newButton = Object.Instantiate(roleOptionSetting.buttons[0], roleOptionSetting.transform);
|
||||
newButton.name = "ConfigButton";
|
||||
newButton.transform.localPosition = new Vector3(0.4473f, -0.3f, -2f);
|
||||
newButton.transform.FindChild("Text_TMP").gameObject.DestroyImmediate();
|
||||
newButton.activeSprites.Destroy();
|
||||
|
||||
var btnRend = newButton.transform.FindChild("ButtonSprite").GetComponent<SpriteRenderer>();
|
||||
btnRend.sprite = MiraAssets.Cog.LoadAsset();
|
||||
|
||||
var passiveButton = newButton.GetComponent<GameOptionButton>();
|
||||
passiveButton.OnClick = new ButtonClickedEvent();
|
||||
passiveButton.interactableColor = btnRend.color = customRole.RoleColor.GetAlternateColor();
|
||||
passiveButton.interactableHoveredColor = Color.white;
|
||||
|
||||
passiveButton.OnClick.AddListener((UnityAction)(() =>
|
||||
|
||||
if (GameSettingMenuPatches.SelectedMod is null ||
|
||||
GameSettingMenuPatches.SelectedMod.Options.Any(x => x.AdvancedRole != null && x.AdvancedRole.IsInstanceOfType(role)))
|
||||
{
|
||||
ChangeTab(role, __instance);
|
||||
}));
|
||||
var newButton = Object.Instantiate(roleOptionSetting.buttons[0], roleOptionSetting.transform);
|
||||
newButton.name = "ConfigButton";
|
||||
newButton.transform.localPosition = new Vector3(0.4473f, -0.3f, -2f);
|
||||
newButton.transform.FindChild("Text_TMP").gameObject.DestroyImmediate();
|
||||
newButton.activeSprites.Destroy();
|
||||
|
||||
if (index < GameSettingMenuPatches.SelectedMod.CustomRoles.Count - 1)
|
||||
var btnRend = newButton.transform.FindChild("ButtonSprite").GetComponent<SpriteRenderer>();
|
||||
btnRend.sprite = MiraAssets.Cog.LoadAsset();
|
||||
|
||||
var passiveButton = newButton.GetComponent<GameOptionButton>();
|
||||
passiveButton.OnClick = new ButtonClickedEvent();
|
||||
passiveButton.interactableColor = btnRend.color = customRole.RoleColor.GetAlternateColor();
|
||||
passiveButton.interactableHoveredColor = Color.white;
|
||||
|
||||
passiveButton.OnClick.AddListener((UnityAction)(() => { ChangeTab(role, __instance); }));
|
||||
}
|
||||
|
||||
if (index < GameSettingMenuPatches.SelectedMod?.CustomRoles.Count - 1)
|
||||
{
|
||||
yPos += -0.43f;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
using HarmonyLib;
|
||||
using MiraAPI.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Patches.Options;
|
||||
[HarmonyPatch]
|
||||
public class SettingPatches
|
||||
{
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(FloatGameSetting), nameof(FloatGameSetting.GetValueString))]
|
||||
public static bool ValueStringPatch(FloatGameSetting __instance, ref string __result, [HarmonyArgument(0)] float value)
|
||||
{
|
||||
string result = string.Empty;
|
||||
MiraNumberSuffixes suffix = (MiraNumberSuffixes)__instance.SuffixType;
|
||||
|
||||
if (__instance.ZeroIsInfinity && Mathf.Abs(value) < 0.0001f)
|
||||
{
|
||||
result = "<b>∞</b>";
|
||||
}
|
||||
else if (suffix == MiraNumberSuffixes.None)
|
||||
{
|
||||
result = value.ToString(__instance.FormatString);
|
||||
}
|
||||
else if (suffix == MiraNumberSuffixes.Multiplier)
|
||||
{
|
||||
result = value.ToString(__instance.FormatString) + "x";
|
||||
}
|
||||
else if (suffix == MiraNumberSuffixes.Percent)
|
||||
{
|
||||
result = value.ToString(__instance.FormatString) + "%";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GameSecondsAbbrev, (Il2CppSystem.Object[])(
|
||||
[
|
||||
value.ToString(__instance.FormatString)
|
||||
]));
|
||||
}
|
||||
__result = result;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -37,9 +37,9 @@ public static class PlayerControlPatches
|
||||
|
||||
foreach (var button in CustomButtonManager.CustomButtons)
|
||||
{
|
||||
if (__instance.Data?.Role != null)
|
||||
if (__instance.Data?.Role == null)
|
||||
{
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!button.Enabled(__instance.Data?.Role))
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 370 B After Width: | Height: | Size: 1.0 KiB |
@@ -205,5 +205,10 @@ public static class CustomRoleManager
|
||||
Logger<MiraApiPlugin>.Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (LobbyInfoPane.Instance)
|
||||
{
|
||||
LobbyInfoPane.Instance.RefreshPane();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace MiraAPI.Utilities.Assets;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Utilities.Assets;
|
||||
|
||||
public static class MiraAssets
|
||||
{
|
||||
@@ -9,4 +11,7 @@ public static class MiraAssets
|
||||
public static readonly LoadableResourceAsset Cog = new("MiraAPI.Resources.Cog.png");
|
||||
public static readonly LoadableResourceAsset Checkmark = new("MiraAPI.Resources.Checkmark.png");
|
||||
public static readonly LoadableResourceAsset CheckmarkBox = new("MiraAPI.Resources.CheckMarkBox.png");
|
||||
|
||||
|
||||
public static readonly Color32 AcceptedTeal = new Color32(43, 233, 198, 255);
|
||||
}
|
||||
@@ -46,13 +46,14 @@ TextAlignmentOptions textAlignment = TextAlignmentOptions.Center)
|
||||
return Object.FindObjectsOfType<DeadBody>().FirstOrDefault(body => body.ParentId == id);
|
||||
}
|
||||
|
||||
public static string GetSuffix(NumberSuffixes suffix)
|
||||
public static string GetSuffix(MiraNumberSuffixes suffix)
|
||||
{
|
||||
return suffix switch
|
||||
{
|
||||
NumberSuffixes.None => string.Empty,
|
||||
NumberSuffixes.Multiplier => "x",
|
||||
NumberSuffixes.Seconds => "s",
|
||||
MiraNumberSuffixes.None => string.Empty,
|
||||
MiraNumberSuffixes.Multiplier => "x",
|
||||
MiraNumberSuffixes.Seconds => "s",
|
||||
MiraNumberSuffixes.Percent => "%",
|
||||
_ => string.Empty
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace MiraAPI.Utilities;
|
||||
public enum MiraNumberSuffixes
|
||||
{
|
||||
None,
|
||||
Multiplier,
|
||||
Seconds,
|
||||
Percent
|
||||
}
|
||||
@@ -57,6 +57,8 @@ Roles are very simple in Mira API. There are 3 things you need to do to create a
|
||||
2. Implement the `ICustomRole` interface from Mira API.
|
||||
3. Add the `[RegisterCustomRole]` attribute to the class.
|
||||
|
||||
**Disclaimer: Make sure your plugin class has the following attribute `[ReactorModFlags(ModFlags.RequireOnAllClients)]` or else your roles will not register correctly.**
|
||||
|
||||
Note: For step 1, if you are making neutral roles, choose either `CrewmateRole` or `ImpostorRole` as the base depending on if it can kill or not!
|
||||
|
||||
Mira API handles everything else, from adding the proper options to the settings menu, to managing the role assignment at the start of the game. There are no extra steps on the developer's part.
|
||||
|
||||
Reference in new issue
Block a user