mirror of
https://github.com/All-Of-Us-Mods/MiraAPI.git
synced 2026-10-20 01:46:15 +00:00
WIP Targeted meeting abilities API
This commit is contained in:
1 parent
f96f75cea1
commit
e381de033e
11 files changed
+376
-3
No files matched your search
@@ -9,5 +9,6 @@ public static class ExampleAssets
|
|||||||
|
|
||||||
// Credit to EpicHorrors for the teleport button asset.
|
// Credit to EpicHorrors for the teleport button asset.
|
||||||
public static LoadableResourceAsset TeleportButton { get; } = new("MiraAPI.Example.Resources.TeleportButton.png");
|
public static LoadableResourceAsset TeleportButton { get; } = new("MiraAPI.Example.Resources.TeleportButton.png");
|
||||||
|
public static LoadableResourceAsset SharpshootButton { get; } = new("MiraAPI.Example.Resources.SharpshootButton.png");
|
||||||
public static LoadableResourceAsset Banner { get; } = new("MiraAPI.Example.Resources.FortniteBanner.jpeg");
|
public static LoadableResourceAsset Banner { get; } = new("MiraAPI.Example.Resources.FortniteBanner.jpeg");
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using MiraAPI.MeetingAbilities;
|
||||||
|
using MiraAPI.Utilities.Assets;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace MiraAPI.Example.MeetingAbilities;
|
||||||
|
|
||||||
|
public class ShootButton : TargetedMeetingButton
|
||||||
|
{
|
||||||
|
public override string Name => "Shooooooot";
|
||||||
|
|
||||||
|
public override int MaxUses => 0;
|
||||||
|
|
||||||
|
public override float Cooldown => 10;
|
||||||
|
|
||||||
|
public override LoadableAsset<Sprite> Sprite => ExampleAssets.SharpshootButton;
|
||||||
|
|
||||||
|
public override MeetingButtonUsesMode ButtonUsesMode => MeetingButtonUsesMode.PerGame;
|
||||||
|
|
||||||
|
public override bool Enabled(RoleBehaviour r)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnClick(PlayerVoteArea playerVoteArea)
|
||||||
|
{
|
||||||
|
playerVoteArea.SetDisabled();
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 5.7 KiB |
@@ -0,0 +1,77 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using Reactor.Utilities.Attributes;
|
||||||
|
using Reactor.Utilities.Extensions;
|
||||||
|
using TMPro;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace MiraAPI.MeetingAbilities;
|
||||||
|
|
||||||
|
[RegisterInIl2Cpp]
|
||||||
|
public class MeetingAbilityBehaviour(IntPtr cppPtr) : MonoBehaviour(cppPtr)
|
||||||
|
{
|
||||||
|
private bool _init = false;
|
||||||
|
private TargetedMeetingButton _button = null!;
|
||||||
|
public PassiveButton Button;
|
||||||
|
public PlayerVoteArea VoteArea;
|
||||||
|
public SpriteRenderer Renderer;
|
||||||
|
public TextMeshPro CooldownText;
|
||||||
|
public TextMeshPro UsesText;
|
||||||
|
public void Initialize(TargetedMeetingButton button, PlayerVoteArea voteArea)
|
||||||
|
{
|
||||||
|
if (_init) return;
|
||||||
|
VoteArea = voteArea;
|
||||||
|
_button = button;
|
||||||
|
Renderer = GetComponent<SpriteRenderer>();
|
||||||
|
SetFillUp(1, 1);
|
||||||
|
if (!TryGetComponent(out Button))
|
||||||
|
{
|
||||||
|
Error($"Could not initialize MeetingButtonBehaviour for {Button.GetType().Name}, Destroying...");
|
||||||
|
Destroy(this);
|
||||||
|
}
|
||||||
|
_init = true;
|
||||||
|
CooldownText = Instantiate(HudManager.Instance.KillButton.cooldownTimerText, transform);
|
||||||
|
CooldownText.GetComponent<TextTranslatorTMP>().Destroy();
|
||||||
|
CooldownText.transform.localPosition = new Vector3(0, 0, -10);
|
||||||
|
CooldownText.m_maxFontSize = 3f;
|
||||||
|
CooldownText.color = new Color(1, 1, 1, 0.7f);
|
||||||
|
UsesText = Instantiate(CooldownText, transform);
|
||||||
|
UsesText.transform.localPosition = new Vector3(0.25f, 0.25f, -10);
|
||||||
|
UsesText.transform.localScale = Vector3.one * 0.7f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
if (!_init) return;
|
||||||
|
Button.enabled = true;
|
||||||
|
Renderer.enabled = true;
|
||||||
|
if (_button.Enabled(PlayerControl.LocalPlayer.Data.Role) && _button.IsTargetValid(VoteArea)) return;
|
||||||
|
Button.enabled = false;
|
||||||
|
Renderer.enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (!_init) return;
|
||||||
|
if (_button.Timer < 0)
|
||||||
|
{
|
||||||
|
Renderer.material.SetFloat("_Desat", 0.0f);
|
||||||
|
CooldownText.text = string.Empty;
|
||||||
|
UsesText.text = _button.LimitedUses ? _button.UsesRemaining.ToString(CultureInfo.InvariantCulture) : string.Empty;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Renderer.material.SetFloat("_Desat", 0.5f);
|
||||||
|
CooldownText.text = _button.Timer.ToString(_button.CooldownTimerFormatString, NumberFormatInfo.InvariantInfo);
|
||||||
|
UsesText.text = string.Empty;
|
||||||
|
}
|
||||||
|
SetFillUp(_button.Timer, _button.Cooldown);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetFillUp(float timer, float maxTimer)
|
||||||
|
{
|
||||||
|
float percentCool = Mathf.Clamp(timer / maxTimer, 0.001f, 1f);
|
||||||
|
if (percentCool <= 0) percentCool = 1f;
|
||||||
|
Renderer.material.SetFloat("_Percent", percentCool);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace MiraAPI.MeetingAbilities;
|
||||||
|
|
||||||
|
public enum MeetingButtonUsesMode
|
||||||
|
{
|
||||||
|
PerGame,
|
||||||
|
PerMeeting
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using MiraAPI.Modifiers;
|
||||||
|
using MiraAPI.Modifiers.Types;
|
||||||
|
using MiraAPI.PluginLoading;
|
||||||
|
using MiraAPI.Utilities.Assets;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace MiraAPI.MeetingAbilities;
|
||||||
|
|
||||||
|
public static class TargetedMeetingAbilityManager
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a list if==of all registered <see cref="TargetedMeetingButton"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static List<TargetedMeetingButton> Buttons { get; internal set; } = new();
|
||||||
|
|
||||||
|
internal static bool RegisterMeetingAbility(Type type, MiraPluginInfo info)
|
||||||
|
{
|
||||||
|
if (!typeof(TargetedMeetingButton).IsAssignableFrom(type))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var button = Activator.CreateInstance(type) as TargetedMeetingButton;
|
||||||
|
info.InternalMeetingAbilities.Add(button);
|
||||||
|
Buttons.Add(button);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using MiraAPI.Utilities.Assets;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace MiraAPI.MeetingAbilities;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Abstract class for creating custom meeting abilities.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class TargetedMeetingButton
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the <see cref="TargetedMeetingButton"/>.
|
||||||
|
/// </summary>
|
||||||
|
public abstract string Name { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Max Uses of the button.
|
||||||
|
/// Set it to 0 for Infinite uses.
|
||||||
|
/// </summary>
|
||||||
|
public abstract int MaxUses { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the amount of uses left for this button.
|
||||||
|
/// </summary>
|
||||||
|
public int UsesRemaining { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the <see cref="TargetedMeetingButton"/> has limited uses.
|
||||||
|
/// </summary>
|
||||||
|
public bool LimitedUses => MaxUses != 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the cooldown time for this button.
|
||||||
|
/// </summary>
|
||||||
|
public abstract float Cooldown { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the current cooldown timer for this button.
|
||||||
|
/// </summary>
|
||||||
|
public float Timer { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the cooldown time for this button.
|
||||||
|
/// </summary>
|
||||||
|
public virtual string CooldownTimerFormatString => "0";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the sprite used for this button.
|
||||||
|
/// </summary>
|
||||||
|
public abstract LoadableAsset<Sprite> Sprite { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="MeetingButtonUsesMode"/> for this button.
|
||||||
|
/// </summary>
|
||||||
|
public virtual MeetingButtonUsesMode ButtonUsesMode { get; } = MeetingButtonUsesMode.PerGame;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if the button is enabled.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="r">The local player's <see cref="RoleBehaviour"/>.</param>
|
||||||
|
/// <returns>Whether the button is enabled or not.</returns>
|
||||||
|
public abstract bool Enabled(RoleBehaviour r);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback method for when the button is clicked.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="playerVoteArea">The target <see cref="PlayerVoteArea"/>.</param>
|
||||||
|
protected abstract void OnClick(PlayerVoteArea playerVoteArea);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the button creation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="playerVoteArea">The target <see cref="PlayerVoteArea"/>.</param>
|
||||||
|
/// <returns>The <see cref="MeetingAbilityBehaviour"/> instance.</returns>
|
||||||
|
public virtual MeetingAbilityBehaviour CreateButton(PlayerVoteArea playerVoteArea)
|
||||||
|
{
|
||||||
|
if (MeetingHud.Instance == null) return null!;
|
||||||
|
|
||||||
|
var btn = Object.Instantiate(MeetingHud.Instance.PlayerButtonPrefab.ConfirmButton).GetComponent<PassiveButton>();
|
||||||
|
btn.gameObject.name = Name + "Button";
|
||||||
|
|
||||||
|
var spriteRenderer = btn.GetComponent<SpriteRenderer>();
|
||||||
|
spriteRenderer.sprite = Sprite.LoadAsset();
|
||||||
|
spriteRenderer.material = new Material(HudManager.Instance.KillButton.graphic.material);
|
||||||
|
spriteRenderer.SetCooldownNormalizedUvs();
|
||||||
|
btn.gameObject.SetActive(true);
|
||||||
|
|
||||||
|
btn.OnClick = new Button.ButtonClickedEvent();
|
||||||
|
btn.OnClick.AddListener(new System.Action(() => ClickHandler(playerVoteArea)));
|
||||||
|
var abilityBehaviour = btn.gameObject.AddComponent<MeetingAbilityBehaviour>();
|
||||||
|
abilityBehaviour.Initialize(this, playerVoteArea);
|
||||||
|
Timer = Cooldown;
|
||||||
|
return abilityBehaviour;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called every <see cref="MeetingHud.Update"/>.
|
||||||
|
/// Handles the timer logic.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void UpdateHandler()
|
||||||
|
{
|
||||||
|
Timer -= Time.deltaTime;
|
||||||
|
Timer = Mathf.Clamp(Timer, 0, int.MaxValue);
|
||||||
|
FixedUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback method for handling logic every frame.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void FixedUpdate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the button is clicked
|
||||||
|
/// Handles increasing cooldown and decreasing uses remaining.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="playerVoteArea">The target <see cref="PlayerVoteArea"/>.</param>
|
||||||
|
public virtual void ClickHandler(PlayerVoteArea playerVoteArea)
|
||||||
|
{
|
||||||
|
if (UsesRemaining <= 0 && LimitedUses) return;
|
||||||
|
if (Timer > 0) return;
|
||||||
|
Timer = Cooldown;
|
||||||
|
UsesRemaining--;
|
||||||
|
playerVoteArea.Cancel();
|
||||||
|
OnClick(playerVoteArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the target is valid.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="playerVoteArea">The target <see cref="PlayerVoteArea"/>.</param>
|
||||||
|
/// <returns>Whether the target is valid or not.</returns>
|
||||||
|
public virtual bool IsTargetValid(PlayerVoteArea playerVoteArea)
|
||||||
|
{
|
||||||
|
return playerVoteArea != null && playerVoteArea.PlayerId.Value != PlayerControl.LocalPlayer.Data.PlayerId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
using System.Reflection;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using Il2CppInterop.Runtime.InteropTypes;
|
using Il2CppInterop.Runtime.InteropTypes;
|
||||||
using MiraAPI.Events;
|
using MiraAPI.Events;
|
||||||
using MiraAPI.Events.Vanilla.Gameplay;
|
using MiraAPI.Events.Vanilla.Gameplay;
|
||||||
|
using MiraAPI.MeetingAbilities;
|
||||||
using MiraAPI.Roles;
|
using MiraAPI.Roles;
|
||||||
using MiraAPI.Utilities;
|
using MiraAPI.Utilities;
|
||||||
|
|
||||||
@@ -128,6 +130,11 @@ public static class IntroCutscenePatches
|
|||||||
var @event = new BeforeRoundStartEvent(true);
|
var @event = new BeforeRoundStartEvent(true);
|
||||||
MiraEventManager.InvokeEvent(@event);
|
MiraEventManager.InvokeEvent(@event);
|
||||||
|
|
||||||
|
foreach (var ability in TargetedMeetingAbilityManager.Buttons.Where(x => x.ButtonUsesMode == MeetingButtonUsesMode.PerGame))
|
||||||
|
{
|
||||||
|
ability.UsesRemaining = ability.MaxUses;
|
||||||
|
}
|
||||||
|
|
||||||
if (@event.IsCancelled) return;
|
if (@event.IsCancelled) return;
|
||||||
MiraEventManager.InvokeEvent(new RoundStartEvent(true));
|
MiraEventManager.InvokeEvent(new RoundStartEvent(true));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||||
using MiraAPI.Events;
|
using MiraAPI.Events;
|
||||||
using MiraAPI.Events.Vanilla.Meeting;
|
using MiraAPI.Events.Vanilla.Meeting;
|
||||||
using MiraAPI.Events.Vanilla.Meeting.Voting;
|
using MiraAPI.Events.Vanilla.Meeting.Voting;
|
||||||
|
using MiraAPI.MeetingAbilities;
|
||||||
using MiraAPI.Modifiers;
|
using MiraAPI.Modifiers;
|
||||||
using MiraAPI.Utilities;
|
using MiraAPI.Utilities;
|
||||||
using MiraAPI.Voting;
|
using MiraAPI.Voting;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace MiraAPI.Patches.Voting;
|
namespace MiraAPI.Patches.Voting;
|
||||||
|
|
||||||
@@ -33,6 +37,54 @@ internal static class MeetingHudPatches
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
[HarmonyPatch(typeof(PlayerVoteArea), nameof(PlayerVoteArea.Start))]
|
||||||
|
public static void VoteAreaStartPostfix(PlayerVoteArea __instance)
|
||||||
|
{
|
||||||
|
foreach (var targetedMeetingAbility in TargetedMeetingAbilityManager.Buttons)
|
||||||
|
{
|
||||||
|
var btn = targetedMeetingAbility.CreateButton(__instance);
|
||||||
|
btn.transform.SetParent(__instance.Buttons.transform);
|
||||||
|
btn.gameObject.SetActive(targetedMeetingAbility.Enabled(PlayerControl.LocalPlayer.Data.Role) && targetedMeetingAbility.IsTargetValid(__instance));
|
||||||
|
}
|
||||||
|
__instance.CancelButton.transform.SetAsFirstSibling();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
[HarmonyPatch(typeof(PlayerVoteArea), nameof(PlayerVoteArea.Select))]
|
||||||
|
public static bool VoteAreaSelectPatch(PlayerVoteArea __instance)
|
||||||
|
{
|
||||||
|
if (PlayerControl.LocalPlayer.Data.IsDead || __instance.AmDead || !(bool) (UnityEngine.Object) __instance.Parent)
|
||||||
|
return false;
|
||||||
|
JudgeRole? judgeRole = PlayerControl.LocalPlayer.Data.Role.TryCast<JudgeRole>();
|
||||||
|
bool flag = judgeRole && PlayerControl.LocalPlayer.PlayerId != __instance.PlayerId;
|
||||||
|
__instance.JudgeOverruleButton.gameObject.SetActive(flag);
|
||||||
|
if (__instance.VoteComplete || !__instance.Parent.Select((byte) __instance.PlayerId))
|
||||||
|
return false;
|
||||||
|
__instance.Buttons.SetActive(true);
|
||||||
|
|
||||||
|
float startPos = __instance.AnimateButtonsFromLeft ? 0.2f : 1.95f;
|
||||||
|
|
||||||
|
Il2CppSystem.Collections.Generic.List<UiElement> selectableElements = new Il2CppSystem.Collections.Generic.List<UiElement>();
|
||||||
|
foreach (var btn in __instance.Buttons.GetComponentsInChildren<PassiveButton>())
|
||||||
|
{
|
||||||
|
selectableElements.Add(btn);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < selectableElements.Count; i++)
|
||||||
|
{
|
||||||
|
var button = selectableElements[i];
|
||||||
|
float endPos = 1.3f - 0.65f * i;
|
||||||
|
float duration = 0.25f + 0.1f * i;
|
||||||
|
__instance.StartCoroutine(Effects.All(Effects.Lerp(duration, (Action<float>) (t =>
|
||||||
|
button.transform.localPosition = Vector2.Lerp(Vector2.right * startPos, Vector2.right * endPos, Effects.ExpOut(t))))));
|
||||||
|
}
|
||||||
|
|
||||||
|
ControllerManager.Instance.OpenOverlayMenu(__instance.name, __instance.CancelButton, selectableElements[1], selectableElements);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(nameof(MeetingHud.Start))]
|
[HarmonyPatch(nameof(MeetingHud.Start))]
|
||||||
public static void MeetingHudStartPatch(MeetingHud __instance)
|
public static void MeetingHudStartPatch(MeetingHud __instance)
|
||||||
@@ -54,6 +106,10 @@ internal static class MeetingHudPatches
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var ability in TargetedMeetingAbilityManager.Buttons.Where(x => x.ButtonUsesMode == MeetingButtonUsesMode.PerMeeting))
|
||||||
|
{
|
||||||
|
ability.UsesRemaining = ability.MaxUses;
|
||||||
|
}
|
||||||
var @event = new StartMeetingEvent(__instance);
|
var @event = new StartMeetingEvent(__instance);
|
||||||
MiraEventManager.InvokeEvent(@event);
|
MiraEventManager.InvokeEvent(@event);
|
||||||
}
|
}
|
||||||
@@ -77,6 +133,11 @@ internal static class MeetingHudPatches
|
|||||||
[HarmonyPatch(nameof(MeetingHud.Update))]
|
[HarmonyPatch(nameof(MeetingHud.Update))]
|
||||||
public static void ForceSkipPatch(MeetingHud __instance)
|
public static void ForceSkipPatch(MeetingHud __instance)
|
||||||
{
|
{
|
||||||
|
foreach (var targetedMeetingAbility in TargetedMeetingAbilityManager.Buttons)
|
||||||
|
{
|
||||||
|
targetedMeetingAbility.UpdateHandler();
|
||||||
|
}
|
||||||
|
|
||||||
if (__instance.state is not (MeetingHud.MeetingStates.NotVoted or MeetingHud.MeetingStates.Voted))
|
if (__instance.state is not (MeetingHud.MeetingStates.NotVoted or MeetingHud.MeetingStates.Voted))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -105,7 +166,7 @@ internal static class MeetingHudPatches
|
|||||||
|
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
[HarmonyPatch(nameof(MeetingHud.Select))]
|
[HarmonyPatch(nameof(MeetingHud.Select))]
|
||||||
public static bool SelectPatch(MeetingHud __instance, int suspectStateIdx)
|
public static bool MeetingHudSelectPatch(MeetingHud __instance, int suspectStateIdx)
|
||||||
{
|
{
|
||||||
var voteData = PlayerControl.LocalPlayer.GetVoteData();
|
var voteData = PlayerControl.LocalPlayer.GetVoteData();
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using BepInEx.Configuration;
|
|||||||
using MiraAPI.GameModes;
|
using MiraAPI.GameModes;
|
||||||
using MiraAPI.GameOptions;
|
using MiraAPI.GameOptions;
|
||||||
using MiraAPI.Hud;
|
using MiraAPI.Hud;
|
||||||
|
using MiraAPI.MeetingAbilities;
|
||||||
using MiraAPI.Modifiers;
|
using MiraAPI.Modifiers;
|
||||||
using MiraAPI.Presets;
|
using MiraAPI.Presets;
|
||||||
|
|
||||||
@@ -78,6 +79,8 @@ public class MiraPluginInfo
|
|||||||
|
|
||||||
internal List<CustomActionButton> InternalButtons { get; } = [];
|
internal List<CustomActionButton> InternalButtons { get; } = [];
|
||||||
|
|
||||||
|
internal List<TargetedMeetingButton?> InternalMeetingAbilities { get; } = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin's ID, as defined in the plugin's BepInEx metadata.
|
/// Gets the plugin's ID, as defined in the plugin's BepInEx metadata.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ using MiraAPI.Hud;
|
|||||||
using MiraAPI.Keybinds;
|
using MiraAPI.Keybinds;
|
||||||
using MiraAPI.LocalSettings;
|
using MiraAPI.LocalSettings;
|
||||||
using MiraAPI.LocalSettings.Attributes;
|
using MiraAPI.LocalSettings.Attributes;
|
||||||
|
using MiraAPI.MeetingAbilities;
|
||||||
using MiraAPI.Modifiers;
|
using MiraAPI.Modifiers;
|
||||||
using MiraAPI.Patches.Options;
|
using MiraAPI.Patches.Options;
|
||||||
using MiraAPI.Presets;
|
using MiraAPI.Presets;
|
||||||
@@ -117,6 +118,11 @@ public sealed class MiraPluginManager
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (RegisterMeetingAbility(type, info))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
RegisterColorClasses(type);
|
RegisterColorClasses(type);
|
||||||
RegisterKeybinds(type, plugin);
|
RegisterKeybinds(type, plugin);
|
||||||
@@ -443,4 +449,17 @@ public sealed class MiraPluginManager
|
|||||||
Error($"Failed to register keybind class {type.Name}: {e}");
|
Error($"Failed to register keybind class {type.Name}: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool RegisterMeetingAbility(Type type, MiraPluginInfo info)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return TargetedMeetingAbilityManager.RegisterMeetingAbility(type, info);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Error($"Failed to register meeting ability {type.Name}: {e}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user