mirror of
https://github.com/All-Of-Us-Mods/MiraAPI.git
synced 2026-10-20 01:46:15 +00:00
Merge branch 'dev' into voting
This commit is contained in:
commit
e25b78705b
18 files changed
+373
-54
No files matched your search
@@ -35,7 +35,7 @@ public abstract class AbstractOptionGroup
|
||||
/// <summary>
|
||||
/// Gets the group color. This is used to color the group in the options menu.
|
||||
/// </summary>
|
||||
public virtual Color GroupColor => Color.clear;
|
||||
public virtual Color GroupColor => MiraApiPlugin.DefaultHeaderColor;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the group priority. This is used to determine the order in which groups are displayed in the options menu.
|
||||
|
||||
@@ -168,7 +168,7 @@ public abstract class CustomActionButton
|
||||
/// Allows you to change the button's location.
|
||||
/// </summary>
|
||||
/// <param name="location">The new location.</param>
|
||||
/// <param name="moveButton">Whether the button's position should change ingame.</param>
|
||||
/// <param name="moveButton">Whether the button's position should change in-game.</param>
|
||||
public virtual void SetButtonLocation(ButtonLocation location, bool moveButton = true)
|
||||
{
|
||||
if (!HudManager.InstanceExists || Button == null)
|
||||
@@ -221,7 +221,6 @@ public abstract class CustomActionButton
|
||||
/// A utility function to change the outline color of the button's text.
|
||||
/// </summary>
|
||||
/// <param name="color">The new color.</param>
|
||||
/// <param name="thickness">The thickness of the outline. Set to 0 if you want to remove it.</param>
|
||||
public virtual void SetTextOutline(Color color)
|
||||
{
|
||||
Button?.buttonLabelText.SetOutlineColor(color);
|
||||
@@ -364,7 +363,7 @@ public abstract class CustomActionButton
|
||||
/// <returns>A value that represents whether the button should light up or not.</returns>
|
||||
public virtual bool CanUse()
|
||||
{
|
||||
return !LimitedUses || UsesLeft > 0;
|
||||
return PlayerControl.LocalPlayer.moveable && (!LimitedUses || UsesLeft > 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
using BepInEx;
|
||||
using System;
|
||||
using BepInEx;
|
||||
using BepInEx.Unity.IL2CPP;
|
||||
using HarmonyLib;
|
||||
using Il2CppInterop.Runtime;
|
||||
using MiraAPI.PluginLoading;
|
||||
using MiraAPI.Roles;
|
||||
using MonoMod.Utils;
|
||||
using Reactor;
|
||||
using Reactor.Networking;
|
||||
using Reactor.Networking.Attributes;
|
||||
using Reactor.Utilities;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.ProBuilder;
|
||||
using Delegate = Il2CppSystem.Delegate;
|
||||
|
||||
namespace MiraAPI;
|
||||
|
||||
@@ -20,6 +27,7 @@ namespace MiraAPI;
|
||||
public partial class MiraApiPlugin : BasePlugin
|
||||
{
|
||||
public static Color MiraColor { get; } = new Color32(238, 154, 112, 255);
|
||||
public static Color DefaultHeaderColor = new Color32(77, 77, 77, 255);
|
||||
private static MiraPluginManager? PluginManager { get; set; }
|
||||
internal Harmony Harmony { get; } = new(Id);
|
||||
|
||||
|
||||
@@ -180,6 +180,30 @@ public static class ModifierExtensions
|
||||
return player.GetModifierComponent().HasModifier(typeId, predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all modifiers from a player.
|
||||
/// </summary>
|
||||
/// <param name="plr">The player you want to clear modifiers for.</param>
|
||||
public static void ClearModifiers(this PlayerControl plr)
|
||||
{
|
||||
foreach (var mod in plr.GetModifierComponent().ActiveModifiers)
|
||||
{
|
||||
plr.RemoveModifier(mod);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all modifiers from a player.
|
||||
/// </summary>
|
||||
/// <param name="plr">The player you want to clear modifiers for.</param>
|
||||
public static void RpcClearModifiers(this PlayerControl plr)
|
||||
{
|
||||
foreach (var mod in plr.GetModifierComponent().ActiveModifiers)
|
||||
{
|
||||
plr.RpcRemoveModifier(mod.UniqueId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the player has a specific modifier by its GUID.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MiraAPI.Modifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Utilities to make handling modifiers in-game easier.
|
||||
/// </summary>
|
||||
public static class ModifierUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a list of all active in-game modifiers.
|
||||
/// </summary>
|
||||
/// <param name="predicate">Select if modifier is valid to be added to list.</param>
|
||||
/// <typeparam name="T">The modifier type.</typeparam>
|
||||
/// <returns>A list of modifiers.</returns>
|
||||
public static IEnumerable<T> GetActiveModifiers<T>(Func<T, bool>? predicate = null) where T : BaseModifier
|
||||
{
|
||||
return PlayerControl.AllPlayerControls.ToArray().SelectMany(x => x.GetModifiers<T>(predicate)).OfType<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all players with a certain modifier.
|
||||
/// </summary>
|
||||
/// <param name="predicate">Select if modifier is valid.</param>
|
||||
/// <typeparam name="T">The modifier type.</typeparam>
|
||||
/// <returns>A list of players with that modifier.</returns>
|
||||
public static IEnumerable<PlayerControl> GetPlayersWithModifier<T>(Func<T, bool>? predicate = null) where T : BaseModifier
|
||||
{
|
||||
return PlayerControl.AllPlayerControls.ToArray().Where(x => x.HasModifier<T>(predicate));
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public static class GameOptionsMenuPatch
|
||||
{
|
||||
var filteredGroups =
|
||||
GameSettingMenuPatches.SelectedMod?.OptionGroups
|
||||
.Where(x => x.OptionableType == null) ?? [];
|
||||
.Where(x => x.OptionableType == null && !x.ShowInModifiersMenu) ?? [];
|
||||
|
||||
foreach (var group in filteredGroups)
|
||||
{
|
||||
@@ -144,7 +144,7 @@ public static class GameOptionsMenuPatch
|
||||
}
|
||||
|
||||
var filteredGroups = GameSettingMenuPatches.SelectedMod?.OptionGroups
|
||||
.Where(x => x.OptionableType == null) ?? [];
|
||||
.Where(x => x.OptionableType == null && !x.ShowInModifiersMenu) ?? [];
|
||||
|
||||
foreach (var group in filteredGroups)
|
||||
{
|
||||
@@ -198,16 +198,16 @@ public static class GameOptionsMenuPatch
|
||||
menu.settingsContainer);
|
||||
|
||||
categoryHeaderMasked.SetHeader(CustomStringName.CreateAndRegister(group.GroupName), 20);
|
||||
if (group.GroupColor != Color.clear)
|
||||
{
|
||||
categoryHeaderMasked.Background.color = group.GroupColor;
|
||||
categoryHeaderMasked.Divider.color = group.GroupColor;
|
||||
categoryHeaderMasked.Title.color = group.GroupColor.FindAlternateColor();
|
||||
}
|
||||
categoryHeaderMasked.Background.color = group.GroupColor;
|
||||
categoryHeaderMasked.Divider.color = group.GroupColor;
|
||||
categoryHeaderMasked.Title.color = group.GroupColor.Equals(MiraApiPlugin.DefaultHeaderColor) ? Color.white : group.GroupColor.FindAlternateColor();
|
||||
|
||||
categoryHeaderMasked.Background.sprite = MiraAssets.CategoryHeader.LoadAsset();
|
||||
categoryHeaderMasked.Background.transform.localPosition = new Vector3(0.55f, -0.1833f, 0);
|
||||
categoryHeaderMasked.Background.size = new Vector2(
|
||||
categoryHeaderMasked.Background.size.x + 1.5f,
|
||||
categoryHeaderMasked.Background.size.y);
|
||||
|
||||
categoryHeaderMasked.gameObject.SetActive(false);
|
||||
group.Header = categoryHeaderMasked;
|
||||
|
||||
@@ -230,7 +230,7 @@ public static class GameOptionsMenuPatch
|
||||
SpriteRenderer[] componentsInChildren = newOpt.GetComponentsInChildren<SpriteRenderer>(true);
|
||||
foreach (var renderer in componentsInChildren)
|
||||
{
|
||||
if (group.GroupColor != Color.clear)
|
||||
if (group.GroupColor != MiraApiPlugin.DefaultHeaderColor)
|
||||
{
|
||||
renderer.color = group.GroupColor.FindAlternateColor();
|
||||
if (renderer.transform.parent.TryGetComponent<GameOptionButton>(out var btn))
|
||||
@@ -245,7 +245,7 @@ public static class GameOptionsMenuPatch
|
||||
|
||||
foreach (var textMeshPro in newOpt.GetComponentsInChildren<TextMeshPro>(true))
|
||||
{
|
||||
if (group.GroupColor != Color.clear)
|
||||
if (group.GroupColor != MiraApiPlugin.DefaultHeaderColor)
|
||||
{
|
||||
textMeshPro.color = group.GroupColor;
|
||||
}
|
||||
@@ -257,12 +257,11 @@ 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;
|
||||
toggle.CheckMark.color = group.GroupColor != MiraApiPlugin.DefaultHeaderColor ? group.GroupColor : MiraAssets.AcceptedTeal;
|
||||
var rend = toggle.CheckMark.transform.parent.FindChild("ActiveSprite")
|
||||
.GetComponent<SpriteRenderer>();
|
||||
rend.sprite = MiraAssets.CheckmarkBox.LoadAsset();
|
||||
rend.color = group.GroupColor != Color.clear ? group.GroupColor : MiraAssets.AcceptedTeal;
|
||||
rend.color = group.GroupColor != MiraApiPlugin.DefaultHeaderColor ? group.GroupColor : MiraAssets.AcceptedTeal;
|
||||
}
|
||||
|
||||
menu.Children.Add(newOpt);
|
||||
|
||||
@@ -330,8 +330,8 @@ public static class LobbyViewPanePatches
|
||||
numPerGame,
|
||||
chancePerGame,
|
||||
61,
|
||||
customRole.OptionsMenuColor,
|
||||
customRole.Configuration.Icon.LoadAsset(),
|
||||
customRole.RoleColor,
|
||||
customRole.Configuration.Icon?.LoadAsset() ?? MiraAssets.Empty.LoadAsset(),
|
||||
true);
|
||||
viewSettingsInfoPanelRoleVariant.iconSprite.transform.localScale = new Vector3(0.365f, 0.365f, 1f);
|
||||
viewSettingsInfoPanelRoleVariant.iconSprite.transform.localPosition = new Vector3(0.7144f, -0.028f, -2);
|
||||
@@ -340,7 +340,7 @@ public static class LobbyViewPanePatches
|
||||
viewSettingsInfoPanelRoleVariant.chanceTitle.color =
|
||||
viewSettingsInfoPanelRoleVariant.chanceBackground.color =
|
||||
viewSettingsInfoPanelRoleVariant.background.color =
|
||||
customRole.OptionsMenuColor.FindAlternateColor();
|
||||
customRole.RoleColor.GetAlternateColor();
|
||||
instance.settingsInfo.Add(viewSettingsInfoPanelRoleVariant.gameObject);
|
||||
num -= 0.664f;
|
||||
}
|
||||
@@ -418,7 +418,7 @@ public static class LobbyViewPanePatches
|
||||
role.StringName,
|
||||
maskLayer,
|
||||
role.TeamType == RoleTeamTypes.Crewmate,
|
||||
customRole.Configuration.Icon.LoadAsset());
|
||||
customRole.Configuration.Icon != null ? customRole.Configuration.Icon.LoadAsset() : MiraAssets.Empty.LoadAsset());
|
||||
viewPanel.header.icon.transform.localScale = new Vector3(0.465f, 0.465f, 1f);
|
||||
viewPanel.divider.material.SetInt(PlayerMaterial.MaskLayer, maskLayer);
|
||||
|
||||
|
||||
@@ -127,32 +127,34 @@ public static class RoleSettingMenuPatches
|
||||
chanceLabel.Destroy();
|
||||
countLabel.Destroy();
|
||||
|
||||
if (name is StringNames.CrewmateRolesHeader)
|
||||
{
|
||||
categoryHeaderMasked.Title.color = Palette.CrewmateRoleHeaderTextBlue;
|
||||
categoryHeaderMasked.Background.color = Palette.CrewmateRoleHeaderBlue;
|
||||
}
|
||||
else if (name is StringNames.ImpostorRolesHeader)
|
||||
{
|
||||
categoryHeaderMasked.Title.color = Palette.ImpostorRoleHeaderTextRed;
|
||||
categoryHeaderMasked.Background.color = Palette.ImpostorRoleHeaderRed;
|
||||
}
|
||||
else
|
||||
{
|
||||
categoryHeaderMasked.Title.color = group.Color;
|
||||
categoryHeaderMasked.Divider.color = group.Color;
|
||||
categoryHeaderMasked.Background.color = group.Color;
|
||||
}
|
||||
categoryHeaderMasked.Background.sprite = MiraAssets.CategoryHeader.LoadAsset();
|
||||
categoryHeaderMasked.Background.transform.localPosition = new Vector3(0.55f, -0.1833f, 0);
|
||||
|
||||
categoryHeaderMasked.Title.color = categoryHeaderMasked.Title.color.IsColorDark() ?
|
||||
categoryHeaderMasked.Title.color.LightenColor(0.3f) : categoryHeaderMasked.Title.color.LightenColor(0.1f);
|
||||
switch (name)
|
||||
{
|
||||
case StringNames.CrewmateRolesHeader:
|
||||
categoryHeaderMasked.Title.color = Palette.CrewmateRoleHeaderTextBlue;
|
||||
categoryHeaderMasked.Background.color = Palette.CrewmateRoleHeaderBlue;
|
||||
break;
|
||||
case StringNames.ImpostorRolesHeader:
|
||||
categoryHeaderMasked.Title.color = Palette.ImpostorRoleHeaderTextRed;
|
||||
categoryHeaderMasked.Background.color = Palette.ImpostorRoleHeaderRed;
|
||||
break;
|
||||
default:
|
||||
categoryHeaderMasked.Title.color = group.Color.Equals(MiraApiPlugin.DefaultHeaderColor) ? Color.white : group.Color.FindAlternateColor();
|
||||
categoryHeaderMasked.Divider.color = group.Color;
|
||||
categoryHeaderMasked.Background.color = group.Color;
|
||||
break;
|
||||
}
|
||||
|
||||
categoryHeaderMasked.Title.fontStyle = __instance.categoryHeaderEditRoleOrigin.Title.fontStyle;
|
||||
categoryHeaderMasked.Title.font = __instance.categoryHeaderEditRoleOrigin.Title.font;
|
||||
categoryHeaderMasked.Title.fontMaterial = __instance.categoryHeaderEditRoleOrigin.Title.fontMaterial;
|
||||
|
||||
categoryHeaderMasked.Divider.color = categoryHeaderMasked.Background.color;
|
||||
categoryHeaderMasked.Background.transform.localPosition = new Vector3(0.55f, -0.1833f, 0);
|
||||
categoryHeaderMasked.Background.size = new Vector2(categoryHeaderMasked.Background.size.x + 1.5f, categoryHeaderMasked.Background.size.y);
|
||||
|
||||
categoryHeaderMasked.transform.localScale = Vector3.one * 0.63f;
|
||||
categoryHeaderMasked.transform.localPosition = new Vector3(-0.44f, ScrollerNum, -2f);
|
||||
categoryHeaderMasked.gameObject.SetActive(true);
|
||||
|
||||
@@ -33,4 +33,15 @@ public static class MinigameStubs
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fixes the error when creating custom minigames. Credit to Submerged for discovering this fix.
|
||||
/// </summary>
|
||||
/// <param name="__instance">The Minigame instance.</param>
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(Minigame), nameof(Minigame.Begin))]
|
||||
public static void MinigameErrorFixPatch(Minigame __instance)
|
||||
{
|
||||
__instance.logger ??= new Logger("Minigame", Logger.Level.Info, Logger.Category.Gameplay);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
@@ -1,6 +1,8 @@
|
||||
using AmongUs.GameOptions;
|
||||
using Il2CppSystem.Web.Util;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using UnityEngine;
|
||||
using Helpers = MiraAPI.Utilities.Helpers;
|
||||
|
||||
namespace MiraAPI.Roles;
|
||||
|
||||
@@ -32,7 +34,6 @@ public record struct CustomRoleConfiguration
|
||||
TasksCountForProgress = role.Team is ModdedRoleTeams.Crewmate;
|
||||
HideSettings = roleBehaviour?.IsDead == true;
|
||||
ShowInFreeplay = roleBehaviour?.IsDead == false;
|
||||
OptionsScreenshot = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -58,12 +59,17 @@ public record struct CustomRoleConfiguration
|
||||
/// <summary>
|
||||
/// Gets or sets the Sprite used for the Role Options menu screenshot.
|
||||
/// </summary>
|
||||
public LoadableAsset<Sprite>? OptionsScreenshot { get; set; }
|
||||
public LoadableAsset<Sprite>? OptionsScreenshot { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Sprite used for the Role Icon.
|
||||
/// </summary>
|
||||
public LoadableAsset<Sprite> Icon { get; set; } = MiraAssets.Empty;
|
||||
public LoadableAsset<Sprite>? Icon { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Intro sound for the Role.
|
||||
/// </summary>
|
||||
public LoadableAsset<AudioClip>? IntroSound { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the role is affected by light affectors on Airship.
|
||||
|
||||
@@ -13,6 +13,7 @@ using Reactor.Utilities;
|
||||
using Reactor.Utilities.Extensions;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TextCore;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace MiraAPI.Roles;
|
||||
@@ -93,6 +94,21 @@ public static class CustomRoleManager
|
||||
roleBehaviour.MaxCount = customRole.Configuration.MaxRoleCount;
|
||||
roleBehaviour.RoleScreenshot = customRole.Configuration.OptionsScreenshot?.LoadAsset();
|
||||
|
||||
if (customRole.Configuration.Icon != null)
|
||||
{
|
||||
var asset = customRole.Configuration.Icon.LoadAsset();
|
||||
if (asset != null)
|
||||
{
|
||||
roleBehaviour.RoleIconSolid = asset;
|
||||
roleBehaviour.RoleIconWhite = asset;
|
||||
}
|
||||
}
|
||||
|
||||
if (customRole.Configuration.IntroSound != null)
|
||||
{
|
||||
roleBehaviour.IntroSound = customRole.Configuration.IntroSound.LoadAsset();
|
||||
}
|
||||
|
||||
if (roleBehaviour.IsDead)
|
||||
{
|
||||
RoleManager.GhostRoles.Add(roleBehaviour.Role);
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using AmongUs.GameOptions;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Roles;
|
||||
|
||||
/// <summary>
|
||||
/// Utilities to make handling roles in-game easier.
|
||||
/// </summary>
|
||||
public static class CustomRoleUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets all active in-game roles.
|
||||
/// </summary>
|
||||
/// <returns>A list of roles.</returns>
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
public static IEnumerable<RoleBehaviour> GetActiveRoles() => PlayerControl.AllPlayerControls.ToArray().Select(x => x.Data.Role);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all active in-game roles in a certain team.
|
||||
/// </summary>
|
||||
/// <param name="team">The team you would like to check for.</param>
|
||||
/// <returns>A list of roles with the team.</returns>
|
||||
public static IEnumerable<RoleBehaviour> GetActiveRolesOfTeam(ModdedRoleTeams team) => GetActiveRoles().Where(x => x is ICustomRole customRole && customRole.Team == team);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all active in-game roles of a certain type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The role Type you would like to check for. Must be a RoleBehaviour.</typeparam>
|
||||
/// <returns>A list of roles with that specific type.</returns>
|
||||
public static IEnumerable<T> GetActiveRolesOfType<T>() where T : RoleBehaviour => GetActiveRoles().OfType<T>();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a string builder for the Role Tab.
|
||||
/// </summary>
|
||||
/// <param name="role">The ICustomRole object.</param>
|
||||
/// <returns>A StringBuilder.</returns>
|
||||
public static StringBuilder CreateForRole(ICustomRole role)
|
||||
{
|
||||
var taskStringBuilder = new StringBuilder();
|
||||
taskStringBuilder.AppendLine(CultureInfo.InvariantCulture, $"{role.RoleColor.ToTextColor()}You are a <b>{role.RoleName}.</b></color>");
|
||||
taskStringBuilder.Append("<size=70%>");
|
||||
taskStringBuilder.AppendLine(CultureInfo.InvariantCulture, $"{role.RoleLongDescription}");
|
||||
return taskStringBuilder;
|
||||
}
|
||||
}
|
||||
@@ -206,7 +206,7 @@ public interface ICustomRole : IOptionable
|
||||
/// Get the custom Role Tab text for this role.
|
||||
/// </summary>
|
||||
/// <returns>A StringBuilder with the role tab text.</returns>
|
||||
StringBuilder SetTabText() => Helpers.CreateForRole(this);
|
||||
StringBuilder SetTabText() => CustomRoleUtils.CreateForRole(this);
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether a given modifier can be applied to this role.
|
||||
|
||||
@@ -10,6 +10,7 @@ public static class MiraAssets
|
||||
public static readonly LoadableResourceAsset NextButtonActive = new("MiraAPI.Resources.NextButtonActive.png");
|
||||
public static readonly LoadableResourceAsset Cog = new("MiraAPI.Resources.Cog.png");
|
||||
public static readonly LoadableResourceAsset Checkmark = new("MiraAPI.Resources.Checkmark.png");
|
||||
public static readonly LoadableResourceAsset CategoryHeader = new("MiraAPI.Resources.CategoryHeader.png");
|
||||
public static readonly LoadableResourceAsset CheckmarkBox = new("MiraAPI.Resources.CheckMarkBox.png");
|
||||
public static readonly Color32 AcceptedTeal = new(43, 233, 198, 255);
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Reactor.Utilities.Extensions;
|
||||
using UnityEngine;
|
||||
@@ -30,6 +31,9 @@ public static class SpriteTools
|
||||
throw new ArgumentException($"Resource not found: {resourcePath}");
|
||||
}
|
||||
|
||||
return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f), pixelsPerUnit);
|
||||
tex.name = resourcePath;
|
||||
var sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f), pixelsPerUnit);
|
||||
sprite.name = resourcePath;
|
||||
return sprite;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using HarmonyLib;
|
||||
using MiraAPI.GameOptions;
|
||||
using MiraAPI.Networking;
|
||||
@@ -40,6 +41,30 @@ public static class Extensions
|
||||
BitConverter.GetBytes(count.Value).AddRangeToArray(BitConverter.GetBytes(chance.Value)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a PlayerControl from their PlayerVoteArea in a meeting.
|
||||
/// </summary>
|
||||
/// <param name="state">The vote area.</param>
|
||||
/// <returns>The player's PlayerControl.</returns>
|
||||
public static PlayerControl? GetPlayer(this PlayerVoteArea state) => GameData.Instance.GetPlayerById(state.TargetPlayerId)?.Object;
|
||||
|
||||
/// <summary>
|
||||
/// Gets an int representing the amount of tasks a player has left.
|
||||
/// </summary>
|
||||
/// <param name="player">The player.</param>
|
||||
/// <returns>A count of how many tasks the player has left.</returns>
|
||||
public static int GetTasksLeft(this PlayerControl player) => player.Data.Tasks.ToArray().Count(x => !x.Complete);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a PlayerControl is the game's host.
|
||||
/// </summary>
|
||||
/// <param name="playerControl">The player you're checking for.</param>
|
||||
/// <returns>If the player is the host, true, else false.</returns>
|
||||
public static bool IsHost(this PlayerControl playerControl)
|
||||
{
|
||||
return TutorialManager.InstanceExists || AmongUsClient.Instance.HostId == playerControl.OwnerId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a float is an integer.
|
||||
/// </summary>
|
||||
@@ -131,6 +156,17 @@ public static class Extensions
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a proper string for an enum. (with spaces).
|
||||
/// </summary>
|
||||
/// <param name="enum">The enum you would like to change.</param>
|
||||
/// <returns>A proper string for the enum.</returns>
|
||||
public static string ToDisplayString(this Enum @enum)
|
||||
{
|
||||
var regex = new Regex(@"([^\^])([A-Z][a-z$])");
|
||||
return regex.Replace(@enum.ToString(), m => $"{m.Groups[1].Value} {m.Groups[2].Value}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the constructors of a type that match the specified arguments.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using AmongUs.GameOptions;
|
||||
using HarmonyLib;
|
||||
using MiraAPI.Roles;
|
||||
using Reactor.Utilities;
|
||||
using Reactor.Utilities.Extensions;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TextCore;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace MiraAPI.Utilities;
|
||||
@@ -24,6 +30,123 @@ public static class Helpers
|
||||
return PlayerControl.AllPlayerControls.ToArray().Where(x => !x.Data.IsDead).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a given probability check succeeds.
|
||||
/// </summary>
|
||||
/// <param name="probability">An integer value representing the success probability (0-100).</param>
|
||||
/// <returns>True if the number falls in the range, false if not.</returns>
|
||||
public static bool CheckChance(int probability)
|
||||
{
|
||||
switch (probability)
|
||||
{
|
||||
case 0:
|
||||
return false;
|
||||
case 100:
|
||||
return true;
|
||||
default:
|
||||
{
|
||||
var num = Random.RandomRangeInt(1, 101);
|
||||
return num <= probability;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a vent from the ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The vent ID.</param>
|
||||
/// <returns>The vent.</returns>
|
||||
public static Vent? GetVentById(int id)
|
||||
{
|
||||
return ShipStatus.Instance.AllVents.FirstOrDefault(vent => vent.Id == id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an arrow.
|
||||
/// </summary>
|
||||
/// <param name="parent">The arrow gameObject's parent.</param>
|
||||
/// <param name="color">The color of the arrow.</param>
|
||||
/// <returns>The created ArrowBehaviour.</returns>
|
||||
public static ArrowBehaviour CreateArrow(Transform parent, Color color)
|
||||
{
|
||||
var prefab = Object.FindObjectOfType<ArrowBehaviour>(true);
|
||||
var arrow = Object.Instantiate(prefab, parent);
|
||||
arrow.image = arrow.gameObject.GetComponent<SpriteRenderer>();
|
||||
arrow.image.color = color;
|
||||
arrow.gameObject.layer = 5;
|
||||
arrow.gameObject.SetActive(true);
|
||||
return arrow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the closest object of a specific type.
|
||||
/// </summary>
|
||||
/// <param name="objectList">A list of all the objects you'd like to check the distance for.</param>
|
||||
/// <param name="position">The position of where you want to check from. For example: PlayerControl.LocalPlayer.transform.position.</param>
|
||||
/// <typeparam name="T">The object type.</typeparam>
|
||||
/// <returns>The closest object.</returns>
|
||||
public static T? FindClosestObjectOfType<T>(List<T> objectList, Vector3 position) where T : MonoBehaviour
|
||||
{
|
||||
T? closest = null;
|
||||
var closestDistanceSqr = Mathf.Infinity;
|
||||
|
||||
foreach (var obj in objectList)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var sqrDistance = (obj.transform.position - position).sqrMagnitude;
|
||||
if (sqrDistance < closestDistanceSqr)
|
||||
{
|
||||
closestDistanceSqr = sqrDistance;
|
||||
closest = obj;
|
||||
}
|
||||
}
|
||||
|
||||
return closest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and shows a notification.
|
||||
/// </summary>
|
||||
/// <param name="text">The text you want to display.</param>
|
||||
/// <param name="color">The color of the text and image.</param>
|
||||
/// <param name="clip">The sound you want to play with the notification.</param>
|
||||
/// <param name="spr">The sprite beside the notification.</param>
|
||||
/// <returns>The created notification.</returns>
|
||||
public static LobbyNotificationMessage CreateAndShowNotification(string text, Color color, AudioClip? clip = null, Sprite? spr = null)
|
||||
{
|
||||
return CreateAndShowNotification(text, color, new Vector3(0f, 0f, -2f), clip, spr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and shows a notification.
|
||||
/// </summary>
|
||||
/// <param name="text">The text you want to display.</param>
|
||||
/// <param name="color">The color of the text and image.</param>
|
||||
/// <param name="localPos">The position of the notification.</param>
|
||||
/// <param name="clip">The sound you want to play with the notification.</param>
|
||||
/// <param name="spr">The sprite beside the notification.</param>
|
||||
/// <returns>The created notification.</returns>
|
||||
public static LobbyNotificationMessage CreateAndShowNotification(string text, Color color, Vector3 localPos, AudioClip? clip = null, Sprite? spr = null)
|
||||
{
|
||||
var popper = HudManager.Instance.Notifier;
|
||||
var newMessage = Object.Instantiate(popper.notificationMessageOrigin, Vector3.zero, Quaternion.identity, popper.transform);
|
||||
newMessage.transform.localPosition = localPos;
|
||||
newMessage.SetUp(text, spr ?? null, color, new System.Action(() => popper.OnMessageDestroy(newMessage)));
|
||||
popper.lastMessageKey = -1;
|
||||
popper.ShiftMessages();
|
||||
popper.AddMessageToQueue(newMessage);
|
||||
|
||||
if (clip == null) return newMessage;
|
||||
SoundManager.Instance.StopSound(clip);
|
||||
SoundManager.Instance.PlaySound(clip, false, 2f);
|
||||
|
||||
return newMessage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty coroutine.
|
||||
/// </summary>
|
||||
@@ -265,16 +388,24 @@ public static class Helpers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a string builder for the Role Tab.
|
||||
/// Converts the first letter of a string to uppercase.
|
||||
/// </summary>
|
||||
/// <param name="role">The ICustomRole object.</param>
|
||||
/// <returns>A StringBuilder.</returns>
|
||||
public static StringBuilder CreateForRole(ICustomRole role)
|
||||
/// <param name="str">The string.</param>
|
||||
/// <returns>The fixed string.</returns>
|
||||
public static string FirstLetterToUpper(string str)
|
||||
{
|
||||
var taskStringBuilder = new StringBuilder();
|
||||
taskStringBuilder.AppendLine(CultureInfo.InvariantCulture, $"{role.RoleColor.ToTextColor()}You are a <b>{role.RoleName}.</b></color>");
|
||||
taskStringBuilder.Append("<size=70%>");
|
||||
taskStringBuilder.AppendLine(CultureInfo.InvariantCulture, $"{role.RoleLongDescription}");
|
||||
return taskStringBuilder;
|
||||
return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(str.ToLower(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random string based on characters.
|
||||
/// </summary>
|
||||
/// <param name="length">The length of the string.</param>
|
||||
/// <param name="chars">The characters in the random string.</param>
|
||||
/// <returns>The random string.</returns>
|
||||
public static string RandomString(int length, string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
|
||||
{
|
||||
return new string(Enumerable.Repeat(chars, length)
|
||||
.Select(s => s[Random.RandomRangeInt(0, s.Length)]).ToArray());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user