Compare commits

..
Author SHA1 Message Date
Atony e8536e5d4b Merge pull request #80 from All-Of-Us-Mods/dev
## What's New
- Individual game options can be reset if they are a part of a preset.
- A new meeting-specific murder rpc is now available for use, checking for kills happening within and outside of a meeting.
- ## What's Changed
- Framerate Slider has been renamed to be more accurate
- Memory usage per frame has been improved
2026-02-08 16:30:05 -06:00
Atony 50030c113b Merge pull request #78 from All-Of-Us-Mods/dev
## What's New
- Screen shake no longer interferes with scrolling in the host options menu
## What's Changed
- Sabotage flashes no longer break on Starlight
- Using the button scale setting no longer breaks the UI.
- If a role fails to register to a marshalling error (nullables) the game will no longer crash.
2026-01-04 12:41:46 -06:00
Atony fe3bfcdbc4 Merge pull request #77 from All-Of-Us-Mods/dev
- Added Vanilla Button Click Event (and respective Cancel Event)
- Added accessibility settings for sabotage flashes and blares
- Added an in-game slider for resizing ability buttons
2025-12-28 18:00:57 -06:00
Atony 7ad003ed1e Merge pull request #75 from All-Of-Us-Mods/dev
- Adds custom game tabs, with their own names and description blurbs.
- All keybinds have been moved to the right for consistency and to prevent hide and seek vent uses being obscured.
- Holding shift will change most options to be split in half, like 2.5s -> 1.25s
- Vanilla roles can be blacklisted from spawning or appearing in menus via other mira mods.
- Roles can check if they can spawn on the current gamemode or under specific conditions, such as the current map.
- Adds options that can have customizable text for -1 and 0 values respectively.
- Adds support for modded roles in Hide and Seek
- Fixes vanilla roles bypassing murder attempts
- Fixes keybinds not being hidden on buttons
- Fixes buttons used via keybinds bypassing ButtonClickEvents
- Fixes crashing for Epic Games users when opening the keybinds menu.
2025-12-14 07:58:01 -06:00
Atony 056a9b6102 Merge pull request #72 from All-Of-Us-Mods/dev
Fix Logger error for v0.3.3
2025-10-14 13:53:21 -05:00
Atony ae917a9c77 Merge pull request #71 from All-Of-Us-Mods/dev
MiraAPI v0.3.3
2025-10-14 13:46:58 -05:00
Atony fc9e9740be Merge pull request #70 from All-Of-Us-Mods/dev
MiraAPI v0.3.2
2025-10-14 09:08:53 -05:00
Atony f9096b6160 Merge pull request #69 from All-Of-Us-Mods/dev
MiraAPI v0.3.1
2025-09-28 13:17:06 -05:00
6 changed files with 4 additions and 257 deletions

No files matched your search

+1 -1
View File
@@ -8,7 +8,7 @@
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<VersionPrefix>0.3.8</VersionPrefix>
<VersionPrefix>0.3.7</VersionPrefix>
<VersionSuffix>dev</VersionSuffix>
<Authors>All Of Us, XtraCube, Angxl</Authors>
@@ -24,7 +24,6 @@ public static class ModdedOptionsManager
private static readonly Dictionary<Type, AbstractOptionGroup> TypeToGroup = [];
internal static readonly Dictionary<OptionBehaviour, ModdedPlayerOption> CreatedPlayerOptions = [];
internal static readonly Dictionary<OptionBehaviour, ModdedStringOption> CreatedStringOptions = [];
internal static readonly Dictionary<uint, IModdedOption> ModdedOptions = [];
internal static readonly List<AbstractOptionGroup> Groups = [];
@@ -1,177 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MiraAPI.Networking;
using Reactor.Localization.Utilities;
using UnityEngine;
using Object = UnityEngine.Object;
namespace MiraAPI.GameOptions.OptionTypes;
/// <summary>
/// An option for selecting an enum value.
/// </summary>
public class ModdedStringOption : ModdedOption<string>
{
/// <summary>
/// Gets or sets the string values of the option.
/// </summary>
public string[] Values { get; set; }
/// <summary>
/// Gets or sets the String Name values of the option.
/// </summary>
public StringNames[] StringNameValues { get; set; }
/// <summary>
/// Gets the string's index
/// </summary>
/// <param name="value">The option's string value.</param>
/// <returns>The option's value in the index.</returns>
public int GetIndex(string value, int location)
{
if (Values.Contains(value))
{
return Values.ToList().IndexOf(value);
}
Info($"Cannot find a valid index for {value} in {location}. Returning 0 instead. Values: {string.Join(", ", Values)}");
return 0;
}
/// <summary>
/// Adds a value to the option.
/// </summary>
/// <param name="value">The option's string value.</param>
/// <param name="index">The additional value's index on the list.</param>
public void RegisterExtraValue(string value, int index = -1)
{
if (!Values.Contains(value))
{
if (index <= -1)
index = Values.Length;
var newVals = Values.ToList();
newVals.Insert(index, value);
Values = newVals.ToArray();
var newStrVals = StringNameValues.ToList();
newStrVals.Insert(index, CustomStringName.CreateAndRegister(value));
StringNameValues = newStrVals.ToArray();
}
if (Data != null)
{
var data = (StringGameSetting)Data;
data.Values = StringNameValues;
data.Index = GetIndex(Value, 1);
if (OptionBehaviour != null)
{
var strOpt = OptionBehaviour.TryCast<StringOption>();
if (strOpt != null)
{
strOpt.Values = StringNameValues;
strOpt.Value = GetIndex(Value, 2);
Warning("StringOption is valid");
}
else
{
Error("StringOption is null.");
}
Warning("OptionBehaviour is valid");
}
else
{
Error("OptionBehaviour is null.");
}
Warning("Data is valid");
}
else
{
Error("Data is null.");
}
}
/// <summary>
/// Initializes a new instance of the <see cref="ModdedStringOption"/> class.
/// </summary>
/// <param name="title">The title of the option.</param>
/// <param name="defaultValue">The default value as a string.</param>
/// <param name="values">An option list of string values to use.</param>
/// <param name="includeInPreset">Whether to include this option in the preset or not.</param>
public ModdedStringOption(string title, string defaultValue, string[] values, bool includeInPreset=true) : base(title, defaultValue, includeInPreset)
{
Values = values;
Data = ScriptableObject.CreateInstance<StringGameSetting>();
var data = (StringGameSetting)Data;
data.Title = StringName;
data.Type = global::OptionTypes.String;
StringNameValues = values.Select(CustomStringName.CreateAndRegister).ToArray();
data.Values = StringNameValues;
data.Index = GetIndex(Value, 3);
}
/// <inheritdoc />
public override OptionBehaviour CreateOption(ToggleOption toggleOpt, NumberOption numberOpt, StringOption stringOpt, PlayerOption playerOpt, Transform container)
{
var stringOption = Object.Instantiate(stringOpt, container);
stringOption.name =
$"{ParentMod!.OptionsTitleText}.StringOption.{TranslationController.Instance.GetString(StringName)}";
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 = (Data as StringGameSetting)?.Values ?? new Il2CppStructArray<StringNames>(0);
stringOption.Value = GetIndex(Value, 4);
OptionBehaviour = stringOption;
ModdedOptionsManager.CreatedStringOptions.TryAdd(stringOption, this);
return stringOption;
}
/// <inheritdoc />
public override float GetFloatData()
{
return Values.IndexOf(Value);
}
/// <inheritdoc />
public override NetData GetNetData()
{
return new NetData(Id, Encoding.Unicode.GetBytes(Convert.ToString(Value, NumberFormatInfo.InvariantInfo)!));
}
/// <inheritdoc />
public override void HandleNetData(byte[] data)
{
SetValue(Encoding.Unicode.GetString(data));
}
/// <inheritdoc />
public override string GetValueFromOptionBehaviour(OptionBehaviour optionBehaviour)
{
return Values[optionBehaviour.GetInt()];
}
/// <inheritdoc />
protected override void OnValueChanged(string newValue)
{
HudManager.Instance.Notifier.AddSettingsChangeMessage(StringName, Data.GetValueString(GetIndex(newValue, 5)), false);
if (!OptionBehaviour)
{
return;
}
if (OptionBehaviour is StringOption opt)
{
opt.Value = GetIndex(newValue, 5);
}
}
}
+3 -59
View File
@@ -7,12 +7,10 @@ using Assets.CoreScripts;
using BepInEx.Unity.IL2CPP.Utils;
using MiraAPI.Events;
using MiraAPI.Events.Vanilla.Gameplay;
using MiraAPI.Utilities;
using Reactor.Networking.Attributes;
using Reactor.Networking.Rpc;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using Rewired;
using UnityEngine;
using Object = UnityEngine.Object;
@@ -24,7 +22,7 @@ namespace MiraAPI.Networking;
public static class CustomMurderRpc
{
/// <summary>
/// Networked Custom Murder method, ran by clients for the host to confirm kills.
/// Networked Custom Murder method.
/// </summary>
/// <param name="source">The killer.</param>
/// <param name="target">The player to murder.</param>
@@ -56,7 +54,7 @@ public static class CustomMurderRpc
}
/// <summary>
/// Networked Custom Murder method, which checks for meetings as well, ran by clients for the host to confirm kills.
/// Networked Custom Murder method, which checks for meetings as well.
/// </summary>
/// <param name="source">The killer.</param>
/// <param name="target">The player to murder.</param>
@@ -79,10 +77,6 @@ public static class CustomMurderRpc
bool showKillAnim = true,
bool playKillSound = true)
{
if (LobbyBehaviour.Instance)
{
return;
}
var murderResultFlags = didSucceed ? MurderResultFlags.Succeeded : MurderResultFlags.FailedError;
var beforeMurderEvent = new BeforeMurderEvent(source, target, inMeeting);
@@ -98,52 +92,6 @@ public static class CustomMurderRpc
murderResultFlags = MurderResultFlags.FailedError;
}
if (!PlayerControl.LocalPlayer.IsHost())
{
return;
}
RpcConfirmCustomMurder(
PlayerControl.LocalPlayer,
source,
target,
murderResultFlags,
resetKillTimer,
createDeadBody,
teleportMurderer,
showKillAnim,
playKillSound);
}
/// <summary>
/// Networked Custom Murder method, which checks for meetings as well, ran by clients for the host to confirm kills.
/// </summary>
/// <param name="host">The game host.</param>
/// <param name="source">The killer.</param>
/// <param name="target">The player to murder.</param>
/// <param name="murderResultFlags">End result for the murder.</param>
/// <param name="resetKillTimer">Should the kill timer be reset.</param>
/// <param name="createDeadBody">Should a dead body be created.</param>
/// <param name="teleportMurderer">Should the killer be snapped to the dead player.</param>
/// <param name="showKillAnim">Should the kill animation be shown.</param>
/// <param name="playKillSound">Should the kill sound be played.</param>
[MethodRpc((uint)MiraRpc.ConfirmCustomMurder, LocalHandling = RpcLocalHandling.Before)]
public static void RpcConfirmCustomMurder(
this PlayerControl host,
PlayerControl source,
PlayerControl target,
MurderResultFlags murderResultFlags,
bool resetKillTimer = true,
bool createDeadBody = true,
bool teleportMurderer = true,
bool showKillAnim = true,
bool playKillSound = true)
{
if (LobbyBehaviour.Instance || !host.IsHost() || target.Data.IsDead || target.Data.Disconnected)
{
return;
}
var murderResultFlags2 = MurderResultFlags.DecisionByHost | murderResultFlags;
source.CustomMurder(
@@ -178,7 +126,7 @@ public static class CustomMurderRpc
bool playKillSound = true)
{
source.isKilling = false;
if (resultFlags.HasFlag(MurderResultFlags.FailedError) || LobbyBehaviour.Instance)
if (resultFlags.HasFlag(MurderResultFlags.FailedError))
{
return;
}
@@ -301,10 +249,6 @@ public static class CustomMurderRpc
bool createDeadBody = true,
bool teleportMurderer = true)
{
if (LobbyBehaviour.Instance)
{
yield break;
}
var cam = Camera.main?.GetComponent<FollowerCamera>();
var isParticipant = source.AmOwner || target.AmOwner;
var sourcePhys = source.MyPhysics;
-5
View File
@@ -35,11 +35,6 @@ public enum MiraRpc : uint
/// </summary>
CustomMurder,
/// <summary>
/// Custom Murder RPC Confirmation.
/// </summary>
ConfirmCustomMurder,
/// <summary>
/// Custom Game Over RPC.
/// </summary>
-14
View File
@@ -117,20 +117,6 @@ internal static class PlayerControlPatches
__instance.RpcMurderPlayer(target, true);
}
[HarmonyPrefix]
[HarmonyPatch(nameof(PlayerControl.RpcMurderPlayer))]
[HarmonyPatch(nameof(PlayerControl.MurderPlayer))]
// ReSharper disable once InconsistentNaming
public static bool MurderPlayerPrefix(PlayerControl __instance)
{
if (LobbyBehaviour.Instance)
{
return false;
}
return true;
}
[HarmonyPostfix]
[HarmonyPatch(nameof(PlayerControl.FixedUpdate))]
// ReSharper disable once InconsistentNaming