New events & extensions

This commit is contained in:
ang-xd committed 2025-02-09 16:42:09 -05:00
1 parent 4fe301511d
commit 7042c6e646
29 files changed
+305 -176

No files matched your search

+16 -10
View File
@@ -1,7 +1,8 @@
using MiraAPI.Events;
using MiraAPI.Events.Mira;
using MiraAPI.Events.Vanilla;
using MiraAPI.Events.Vanilla.Usables;
using MiraAPI.Events.Vanilla.Gameplay;
using MiraAPI.Events.Vanilla.Map;
using MiraAPI.Events.Vanilla.Player;
using MiraAPI.Example.Buttons.Freezer;
using Reactor.Utilities;
@@ -15,16 +16,21 @@ public static class ExampleEventHandlers
MiraEventManager.RegisterEventHandler<MiraButtonClickEvent<FreezeButton>>(FreezeButtonClickHandler, 1);
MiraEventManager.RegisterEventHandler<MiraButtonCancelledEvent<FreezeButton>>(FreezeButtonCancelledHandler);
MiraEventManager.RegisterEventHandler<UpdateSystemEvent>(UpdateSystemEventHandler);
MiraEventManager.RegisterEventHandler<PlayerCanUseEvent>(PlayerControlCanUse);
MiraEventManager.RegisterEventHandler<PlayerUseEvent>(PlayerControlUse);
}
public static void PlayerControlCanUse(PlayerCanUseEvent @event)
{
}
MiraEventManager.RegisterEventHandler<BeforeMurderEvent>(@event =>
{
Logger<ExamplePlugin>.Info($"{@event.Source.Data.PlayerName} is about to kill {@event.Target.Data.PlayerName}");
});
public static void PlayerControlUse(PlayerUseEvent @event)
{
MiraEventManager.RegisterEventHandler<AfterMurderEvent>(@event =>
{
Logger<ExamplePlugin>.Info($"{@event.Source.Data.PlayerName} has killed {@event.Target.Data.PlayerName}");
});
MiraEventManager.RegisterEventHandler<CompleteTaskEvent>(@event =>
{
Logger<ExamplePlugin>.Info($"{@event.Player.Data.PlayerName} completed {@event.Task.TaskType.ToString()}");
});
}
public static void UpdateSystemEventHandler(UpdateSystemEvent @event)
@@ -1,24 +0,0 @@
using System;
namespace MiraAPI.Events.Vanilla;
/// <summary>
/// Button click event for <see cref="AdminButton"/> from Vanilla Among Us.
/// </summary>
[Obsolete("This class is deprecated. Use PlayerUseEvent instead.")]
public class AdminButtonClickEvent : MiraCancelableEvent
{
/// <summary>
/// Gets the instance of <see cref="AdminButton"/> that was clicked.
/// </summary>
public AdminButton Button { get; }
/// <summary>
/// Initializes a new instance of the <see cref="AdminButtonClickEvent"/> class.
/// </summary>
/// <param name="button">The AdminButton.</param>
public AdminButtonClickEvent(AdminButton button)
{
Button = button;
}
}
@@ -1,4 +1,4 @@
namespace MiraAPI.Events.Vanilla;
namespace MiraAPI.Events.Vanilla.Gameplay;
/// <summary>
/// Event that is invoked after a player is murdered. Only called after a successful murder. This event is not cancelable.
@@ -1,4 +1,4 @@
namespace MiraAPI.Events.Vanilla;
namespace MiraAPI.Events.Vanilla.Gameplay;
/// <summary>
/// Event that is invoked before a player is murdered. This event is cancelable.
@@ -0,0 +1,21 @@
namespace MiraAPI.Events.Vanilla.Gameplay;
/// <summary>
/// The event that is invoked when the end game screen is shown. Non cancelable.
/// </summary>
public class GameEndEvent : MiraEvent
{
/// <summary>
/// Gets the instance of the EndGameManager.
/// </summary>
public EndGameManager EndGameManager { get; }
/// <summary>
/// Initializes a new instance of the <see cref="GameEndEvent"/> class.
/// </summary>
/// <param name="manager">The instance of the EndGameManager.</param>
public GameEndEvent(EndGameManager manager)
{
EndGameManager = manager;
}
}
@@ -1,7 +1,7 @@
namespace MiraAPI.Events.Vanilla.Meeting;
namespace MiraAPI.Events.Vanilla.Gameplay;
/// <summary>
/// The event that is invoked when the intro cutscene is shown. Non cancellable.
/// The event that is invoked when the intro cutscene is shown. Non cancelable.
/// </summary>
public class IntroBeginEvent : MiraEvent
{
@@ -13,7 +13,7 @@ public class IntroBeginEvent : MiraEvent
/// <summary>
/// Initializes a new instance of the <see cref="IntroBeginEvent"/> class.
/// </summary>
/// <param name="controller">The exile controller.</param>
/// <param name="introCutscene">The intro cutscene.</param>
public IntroBeginEvent(IntroCutscene introCutscene)
{
IntroCutscene = introCutscene;
@@ -1,4 +1,4 @@
namespace MiraAPI.Events.Vanilla;
namespace MiraAPI.Events.Vanilla.Map;
/// <summary>
/// Event fired when a player closes the doors in a room.
@@ -1,4 +1,4 @@
namespace MiraAPI.Events.Vanilla;
namespace MiraAPI.Events.Vanilla.Map;
/// <summary>
/// Cancelable event that is invoked before a system is updated. Usually used for sabotage events.
@@ -0,0 +1,28 @@
namespace MiraAPI.Events.Vanilla.Player;
/// <summary>
/// The event that is invoked when a player completes a task. Non cancelable.
/// </summary>
public class CompleteTaskEvent : MiraEvent
{
/// <summary>
/// Gets the instance of the <see cref="PlayerControl"/>.
/// </summary>
public PlayerControl Player { get; }
/// <summary>
/// Gets the instance of the <see cref="PlayerTask"/> that the player completed.
/// </summary>
public PlayerTask Task { get; }
/// <summary>
/// Initializes a new instance of the <see cref="CompleteTaskEvent"/> class.
/// </summary>
/// <param name="player">The player who completed the task.</param>
/// <param name="task">The task that the player completed.</param>
public CompleteTaskEvent(PlayerControl player, PlayerTask task)
{
Player = player;
Task = task;
}
}
@@ -0,0 +1,28 @@
namespace MiraAPI.Events.Vanilla.Player;
/// <summary>
/// Event that is invoked when a player dies. Non cancelable.
/// </summary>
public class PlayerDeathEvent : MiraEvent
{
/// <summary>
/// Gets the player who died.
/// </summary>
public PlayerControl Player { get; }
/// <summary>
/// Gets the reason the player died.
/// </summary>
public DeathReason DeathReason { get; }
/// <summary>
/// Initializes a new instance of the <see cref="PlayerDeathEvent"/> class.
/// </summary>
/// <param name="player">The player who died.</param>
/// <param name="reason">The reason the player died.</param>
public PlayerDeathEvent(PlayerControl player, DeathReason reason)
{
Player = player;
DeathReason = reason;
}
}
@@ -0,0 +1,23 @@
using InnerNet;
namespace MiraAPI.Events.Vanilla.Player;
/// <summary>
/// Event that is invoked when a player joins the lobby. Non cancelable.
/// </summary>
public class PlayerJoinEvent : MiraEvent
{
/// <summary>
/// Gets the player who joined.
/// </summary>
public ClientData ClientData { get; }
/// <summary>
/// Initializes a new instance of the <see cref="PlayerJoinEvent"/> class.
/// </summary>
/// <param name="data">The data of the player who joined.</param>
public PlayerJoinEvent(ClientData data)
{
ClientData = data;
}
}
@@ -0,0 +1,30 @@
using InnerNet;
namespace MiraAPI.Events.Vanilla.Player;
/// <summary>
/// Event that is invoked when a player leaves the game. Non cancelable.
/// </summary>
public class PlayerLeaveEvent : MiraEvent
{
/// <summary>
/// Gets the player who left.
/// </summary>
public ClientData ClientData { get; }
/// <summary>
/// Gets the reason why the player left.
/// </summary>
public DisconnectReasons Reason { get; }
/// <summary>
/// Initializes a new instance of the <see cref="PlayerLeaveEvent"/> class.
/// </summary>
/// <param name="data">The data of the player who left.</param>
/// <param name="reason">The reason why the player left.</param>
public PlayerLeaveEvent(ClientData data, DisconnectReasons reason)
{
ClientData = data;
Reason = reason;
}
}
@@ -1,24 +0,0 @@
using System;
namespace MiraAPI.Events.Vanilla;
/// <summary>
/// Button click event for <see cref="SabotageButton"/> from Vanilla Among Us.
/// </summary>
[Obsolete("This class is deprecated. Use PlayerOpenSabotageEvent instead.")]
public class SabotageButtonClickEvent : MiraCancelableEvent
{
/// <summary>
/// Gets the instance of <see cref="SabotageButton"/> that was clicked.
/// </summary>
public SabotageButton Button { get; }
/// <summary>
/// Initializes a new instance of the <see cref="SabotageButtonClickEvent"/> class.
/// </summary>
/// <param name="button">The SabotageButton.</param>
public SabotageButtonClickEvent(SabotageButton button)
{
Button = button;
}
}
@@ -1,4 +1,4 @@
namespace MiraAPI.Events.Vanilla;
namespace MiraAPI.Events.Vanilla.Usables;
/// <summary>
/// Event that is invoked when a player enters a vent. This event is cancelable.
@@ -1,4 +1,4 @@
namespace MiraAPI.Events.Vanilla;
namespace MiraAPI.Events.Vanilla.Usables;
/// <summary>
/// Event that is invoked when a player exits a vent. This event is cancelable.
@@ -1,24 +0,0 @@
using System;
namespace MiraAPI.Events.Vanilla;
/// <summary>
/// Button click event for <see cref="UseButton"/> from Vanilla Among Us.
/// </summary>
[Obsolete("This class is deprecated. Use PlayerUseEvent instead.")]
public class UseButtonClickEvent : MiraCancelableEvent
{
/// <summary>
/// Gets the instance of <see cref="UseButton"/> that was clicked.
/// </summary>
public UseButton Button { get; }
/// <summary>
/// Initializes a new instance of the <see cref="UseButtonClickEvent"/> class.
/// </summary>
/// <param name="button">The UseButton.</param>
public UseButtonClickEvent(UseButton button)
{
Button = button;
}
}
@@ -1,21 +0,0 @@
namespace MiraAPI.Events.Vanilla;
/// <summary>
/// Button click event for <see cref="VentButton"/> from Vanilla Among Us.
/// </summary>
public class VentButtonClickEvent : MiraCancelableEvent
{
/// <summary>
/// Gets the instance of <see cref="VentButton"/> that was clicked.
/// </summary>
public VentButton Button { get; }
/// <summary>
/// Initializes a new instance of the <see cref="VentButtonClickEvent"/> class.
/// </summary>
/// <param name="button">The VentButton.</param>
public VentButtonClickEvent(VentButton button)
{
Button = button;
}
}
+9
View File
@@ -445,4 +445,13 @@ public abstract class CustomActionButton<T> : CustomActionButton where T : MonoB
return base.CanUse() && Target != null;
}
/// <summary>
/// Use this to reset the button's target after used.
/// </summary>
public virtual void ResetTarget()
{
Target = null;
SetOutline(false);
}
}
+4 -5
View File
@@ -1,14 +1,14 @@
using System.Collections;
using System.Linq;
using AmongUs.GameOptions;
using AmongUs.GameOptions;
using Assets.CoreScripts;
using BepInEx.Unity.IL2CPP.Utils;
using MiraAPI.Events;
using MiraAPI.Events.Vanilla;
using MiraAPI.Events.Vanilla.Gameplay;
using Reactor.Networking.Attributes;
using Reactor.Networking.Rpc;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using System.Collections;
using System.Linq;
using UnityEngine;
namespace MiraAPI.Networking;
@@ -84,7 +84,6 @@ public static class CustomMurderRpc
bool playKillSound = true)
{
source.isKilling = false;
Logger<MiraApiPlugin>.Error($"{source.PlayerId} trying to murder {target.PlayerId}");
var data = target.Data;
if (resultFlags.HasFlag(MurderResultFlags.FailedError))
{
+17 -2
View File
@@ -1,5 +1,7 @@
using HarmonyLib;
using InnerNet;
using MiraAPI.Events;
using MiraAPI.Events.Vanilla.Player;
using MiraAPI.GameOptions;
using MiraAPI.Modifiers;
using MiraAPI.Roles;
@@ -9,11 +11,16 @@ namespace MiraAPI.Patches;
/// <summary>
/// Sync all options, role settings, and modifiers to the player when they join the game.
/// </summary>
[HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.CreatePlayer))]
[HarmonyPatch(typeof(AmongUsClient))]
public static class AmongUsClientSyncPatch
{
public static void Postfix(ClientData clientData)
[HarmonyPostfix]
[HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.CreatePlayer))]
public static void CreatePlayerPatch(ClientData clientData)
{
var joinEvent = new PlayerJoinEvent(clientData);
MiraEventManager.InvokeEvent(joinEvent);
if (!AmongUsClient.Instance.AmHost)
{
return;
@@ -28,4 +35,12 @@ public static class AmongUsClientSyncPatch
CustomRoleManager.SyncAllRoleSettings(clientData.Id);
ModifierManager.SyncAllModifiers(clientData.Id);
}
[HarmonyPostfix]
[HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.OnPlayerLeft))]
public static void PlayerLeftPatch(ClientData data, DisconnectReasons reason)
{
var leftEvent = new PlayerLeaveEvent(data, reason);
MiraEventManager.InvokeEvent(leftEvent);
}
}
+20
View File
@@ -0,0 +1,20 @@
using HarmonyLib;
using MiraAPI.Events;
using MiraAPI.Events.Vanilla.Gameplay;
namespace MiraAPI.Patches.Events;
/// <summary>
/// Patch for trigging the GameEndEvent.
/// </summary>
[HarmonyPatch]
public static class EndGamePatches
{
[HarmonyPostfix]
[HarmonyPatch(typeof(EndGameManager), nameof(EndGameManager.SetEverythingUp))]
public static void SetEverythingUpPatch(EndGameManager __instance)
{
var @event = new GameEndEvent(__instance);
MiraEventManager.InvokeEvent(@event);
}
}
@@ -1,48 +0,0 @@
using HarmonyLib;
using MiraAPI.Events;
using MiraAPI.Events.Vanilla;
namespace MiraAPI.Patches.Events;
/// <summary>
/// Patch for button related MiraEvents.
/// </summary>
[HarmonyPatch]
public static class HudButtonEventPatches
{
[HarmonyPrefix]
[HarmonyPatch(typeof(AdminButton), nameof(AdminButton.DoClick))]
public static bool AdminButtonDoClickPrefix(AdminButton __instance)
{
var @event = new AdminButtonClickEvent(__instance);
MiraEventManager.InvokeEvent(@event);
return !@event.IsCancelled;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(SabotageButton), nameof(SabotageButton.DoClick))]
public static bool SabotageButtonDoClickPrefix(SabotageButton __instance)
{
var @event = new SabotageButtonClickEvent(__instance);
MiraEventManager.InvokeEvent(@event);
return !@event.IsCancelled;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(UseButton), nameof(UseButton.DoClick))]
public static bool UseButtonDoClickPrefix(UseButton __instance)
{
var @event = new UseButtonClickEvent(__instance);
MiraEventManager.InvokeEvent(@event);
return !@event.IsCancelled;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(VentButton), nameof(VentButton.DoClick))]
public static bool VentButtonDoClickPrefix(VentButton __instance)
{
var @event = new VentButtonClickEvent(__instance);
MiraEventManager.InvokeEvent(@event);
return !@event.IsCancelled;
}
}
@@ -0,0 +1,25 @@
using HarmonyLib;
using MiraAPI.Events;
using MiraAPI.Events.Vanilla.Gameplay;
namespace MiraAPI.Patches;
/// <summary>
/// General patches for the KillAnimation class.
/// </summary>
[HarmonyPatch]
public static class KillAnimationPatches
{
/// <summary>
/// Used to trigger the <see cref="AfterMurderEvent"/>.
/// </summary>
/// <param name="source">The killer.</param>
/// <param name="target">The target.</param>
[HarmonyPostfix]
[HarmonyPatch(typeof(KillAnimation), nameof(KillAnimation.CoPerformKill))]
public static void KillAnimPostfix(PlayerControl source, PlayerControl target)
{
var afterMurderEvent = new AfterMurderEvent(source, target);
MiraEventManager.InvokeEvent(afterMurderEvent);
}
}
@@ -1,6 +1,6 @@
using HarmonyLib;
using MiraAPI.Events;
using MiraAPI.Events.Vanilla;
using MiraAPI.Events.Vanilla.Map;
namespace MiraAPI.Patches.Events;
+1 -1
View File
@@ -1,6 +1,6 @@
using HarmonyLib;
using MiraAPI.Events;
using MiraAPI.Events.Vanilla;
using MiraAPI.Events.Vanilla.Usables;
using System.Linq;
namespace MiraAPI.Patches.Events;
+1 -1
View File
@@ -1,6 +1,6 @@
using HarmonyLib;
using MiraAPI.Events;
using MiraAPI.Events.Vanilla.Meeting;
using MiraAPI.Events.Vanilla.Gameplay;
using MiraAPI.Roles;
using MiraAPI.Utilities;
using UnityEngine;
+41 -1
View File
@@ -1,8 +1,12 @@
using HarmonyLib;
using MiraAPI.Events;
using MiraAPI.Events.Vanilla.Gameplay;
using MiraAPI.Events.Vanilla.Player;
using MiraAPI.Hud;
using MiraAPI.Modifiers;
using MiraAPI.Roles;
using Reactor.Utilities.Extensions;
using System.Linq;
namespace MiraAPI.Patches;
@@ -36,14 +40,50 @@ public static class PlayerControlPatches
[HarmonyPatch(nameof(PlayerControl.Die))]
public static void PlayerControlDiePostfix(PlayerControl __instance, DeathReason reason)
{
var deathEvent = new PlayerDeathEvent(__instance, reason);
MiraEventManager.InvokeEvent(deathEvent);
var modifiersComponent = __instance.GetComponent<ModifierComponent>();
if (modifiersComponent)
{
modifiersComponent.ActiveModifiers.ForEach(x=>x.OnDeath(reason));
modifiersComponent.ActiveModifiers.ForEach(x => x.OnDeath(reason));
}
}
/// <summary>
/// Used to trigger the <see cref="CompleteTaskEvent"/>.
/// </summary>
/// <param name="__instance">PlayerControl instance.</param>
/// <param name="idx">The task id.</param>
[HarmonyPostfix]
[HarmonyPatch(nameof(PlayerControl.CompleteTask))]
public static void PlayerCompleteTaskPostfix(PlayerControl __instance, uint idx)
{
var playerTask = __instance.myTasks.ToArray().First(playerTask => playerTask.Id == idx);
if (playerTask != null)
{
var completeTaskEvent = new CompleteTaskEvent(__instance, playerTask);
MiraEventManager.InvokeEvent(completeTaskEvent);
}
}
/// <summary>
/// Used to trigger the <see cref="BeforeMurderEvent"/>.
/// </summary>
/// <param name="__instance">The source player.</param>
/// <param name="target">The target.</param>
/// <param name="didSucceed">Whether the kill succeeded.</param>
[HarmonyPrefix]
[HarmonyPatch(nameof(PlayerControl.RpcMurderPlayer))]
public static void PlayerControlMurderPrefix(PlayerControl __instance, PlayerControl target, ref bool didSucceed)
{
var beforeMurderEvent = new BeforeMurderEvent(__instance, target);
MiraEventManager.InvokeEvent(beforeMurderEvent);
didSucceed = beforeMurderEvent.IsCancelled;
}
/// <summary>
/// FixedUpdate handler for custom roles and custom buttons.
/// </summary>
+5 -5
View File
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP;
using MiraAPI.Colors;
using MiraAPI.Events;
using MiraAPI.GameOptions;
@@ -13,6 +9,10 @@ using MiraAPI.Roles;
using MiraAPI.Utilities;
using Reactor.Networking;
using Reactor.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace MiraAPI.PluginLoading;
+26
View File
@@ -346,6 +346,16 @@ public static class Extensions
.Find(component => component && !component.Reported);
}
/// <summary>
/// Get all living players.
/// </summary>
/// <returns>A list of alive players.</returns>
public static List<PlayerControl> GetAlivePlayers()
{
return PlayerControl.AllPlayerControls.ToArray().Where(x => !x.Data.IsDead).ToList();
}
/// <summary>
/// Finds the nearest object of a specified type to a player. It will only work if the object has a collider.
/// </summary>
@@ -393,4 +403,20 @@ public static class Extensions
return predicate != null ? filteredPlayers.Find(predicate) : filteredPlayers.FirstOrDefault();
}
private static readonly int _outline = Shader.PropertyToID("_Outline");
private static readonly int _outlineColor = Shader.PropertyToID("_OutlineColor");
private static readonly int _addColor = Shader.PropertyToID("_AddColor");
/// <summary>
/// Fixed version of Reactor's SetOutline.
/// </summary>
/// <param name="renderer">The renderer you want to update the outline for.</param>
/// <param name="color">The outline color.</param>
public static void UpdateOutline(this Renderer renderer, Color? color)
{
renderer.material.SetFloat(_outline, color.HasValue ? 1 : 0);
renderer.material.SetColor(_outlineColor, color.HasValue ? color.Value : Color.clear);
renderer.material.SetColor(_addColor, color.HasValue ? color.Value : Color.clear);
}
}