change neutral team to Custom and add more customization

This commit is contained in:
XtraCube committed 2025-02-16 22:33:16 -05:00
1 parent 0af392d60e
commit 37446964c5
8 files changed
+138 -81

No files matched your search

+5 -4
View File
@@ -5,17 +5,18 @@ namespace MiraAPI.Example.Roles;
public class NeutralKillerRole : ImpostorRole, ICustomRole
{
public string RoleName => "Neutral Killer";
public string RoleDescription => "Neutral who can kill.";
public string RoleName => "Outcast Killer";
public string RoleDescription => "Outcast who can kill.";
public string RoleLongDescription => RoleDescription;
public Color RoleColor => Color.magenta;
public ModdedRoleTeams Team => ModdedRoleTeams.Neutral;
public ModdedRoleTeams Team => ModdedRoleTeams.Custom;
public CustomRoleConfiguration Configuration => new CustomRoleConfiguration(this)
public CustomRoleConfiguration Configuration => new(this)
{
UseVanillaKillButton = true,
CanGetKilled = true,
CanUseVent = true,
RoleGroup = new RoleGroup("Outcast", Color.gray),
};
public override void SpawnTaskHeader(PlayerControl playerControl)
+43 -5
View File
@@ -30,6 +30,32 @@ public static class IntroCutscenePatches
MiraEventManager.InvokeEvent(@event);
}
[HarmonyPrefix]
[HarmonyPatch(nameof(IntroCutscene.BeginImpostor))]
public static void BeginImpostorPatch(IntroCutscene __instance)
{
if (PlayerControl.LocalPlayer.Data.Role is not ICustomRole customRole)
{
return;
}
if (customRole.Configuration.IntroTeamColor is { } color)
{
__instance.BackgroundBar.material.SetColor(ShaderID.Color, color);
__instance.TeamTitle.color = color;
}
if (customRole.Configuration.IntroTeamTitle is { } title)
{
__instance.TeamTitle.text = title;
}
if (customRole.Configuration.IntroTeamDescription is { } description)
{
__instance.ImpostorText.text = description;
}
}
[HarmonyPrefix]
[HarmonyPatch(nameof(IntroCutscene.BeginCrewmate))]
public static bool BeginCrewmatePatch(IntroCutscene __instance)
@@ -39,7 +65,23 @@ public static class IntroCutscenePatches
return true;
}
if (customRole.Team is not ModdedRoleTeams.Neutral)
if (customRole.Configuration.IntroTeamColor is { } color)
{
__instance.BackgroundBar.material.SetColor(ShaderID.Color, color);
__instance.TeamTitle.color = color;
}
if (customRole.Configuration.IntroTeamTitle is { } title)
{
__instance.TeamTitle.text = title;
}
if (customRole.Configuration.IntroTeamDescription is { } description)
{
__instance.ImpostorText.text = description;
}
if (customRole.Team is not ModdedRoleTeams.Custom)
{
return true;
}
@@ -49,11 +91,7 @@ public static class IntroCutscenePatches
position.y -= 0.25f;
barTransform.position = position;
__instance.BackgroundBar.material.SetColor(ShaderID.Color, Color.gray);
__instance.TeamTitle.text = "NEUTRAL";
__instance.impostorScale = 1f;
__instance.ImpostorText.text = "You are Neutral. You do not have a team.";
__instance.TeamTitle.color = Color.gray;
__instance.ourCrewmate = __instance.CreatePlayer(
0,
@@ -1,14 +1,15 @@
using HarmonyLib;
using System;
using System.Linq;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MiraAPI.Networking;
using MiraAPI.Roles;
using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
using Reactor.Localization.Utilities;
using Reactor.Networking.Rpc;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using System;
using System.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
@@ -54,23 +55,43 @@ public static class RoleSettingMenuPatches
var num3 = 0;
var crewRoles = GameSettingMenuPatches.SelectedMod?.CustomRoles.Values
.OfType<ICustomRole>()
.Where(role => role is { Team: ModdedRoleTeams.Crewmate, Configuration.HideSettings: false })
.ToList() ?? [];
var roleGroups = GameSettingMenuPatches.SelectedMod?.CustomRoles.Values.OfType<ICustomRole>()
.ToLookup(x => x.Configuration.RoleGroup);
if (crewRoles is { Count: > 0 })
if (roleGroups is null)
{
return true;
}
// sort the groups by priority
var sortedRoleGroups = roleGroups
.OrderBy(x => x.Key.Priority)
.ThenBy(x => x.Key.Name);
foreach (var grouping in sortedRoleGroups)
{
if (!grouping.Any())
{
continue;
}
var name = grouping.Key.Name switch
{
"Crewmate" => StringNames.CrewmateRolesHeader,
"Impostor" => StringNames.ImpostorRolesHeader,
_ => CustomStringName.CreateAndRegister(grouping.Key.Name),
};
var categoryHeaderEditRole = Object.Instantiate(
__instance.categoryHeaderEditRoleOrigin,
Vector3.zero,
Quaternion.identity,
__instance.RoleChancesSettings.transform);
categoryHeaderEditRole.SetHeader(StringNames.CrewmateRolesHeader, 20);
categoryHeaderEditRole.SetHeader(name, 20);
categoryHeaderEditRole.transform.localPosition = new Vector3(4.986f, num, -2f);
num -= 0.522f;
foreach (var role in crewRoles)
foreach (var role in grouping)
{
if (role is RoleBehaviour roleBehaviour)
{
@@ -78,65 +99,8 @@ public static class RoleSettingMenuPatches
}
num3++;
}
}
var impRoles = GameSettingMenuPatches.SelectedMod?.CustomRoles.Values
.OfType<ICustomRole>()
.Where(role => role is { Team: ModdedRoleTeams.Impostor, Configuration.HideSettings: false })
.ToList() ?? [];
if (impRoles is { Count: > 0 })
{
num -= 0.4f;
var categoryHeaderEditRole2 = Object.Instantiate(
__instance.categoryHeaderEditRoleOrigin,
Vector3.zero,
Quaternion.identity,
__instance.RoleChancesSettings.transform);
categoryHeaderEditRole2.SetHeader(StringNames.ImpostorRolesHeader, 20);
categoryHeaderEditRole2.transform.localPosition = new Vector3(4.986f, num, -2f);
num -= 0.522f;
foreach (var role in impRoles)
{
if (role is RoleBehaviour roleBehaviour)
{
CreateQuotaOption(__instance, roleBehaviour, ref num, num3);
}
num3++;
}
}
var neutRoles = GameSettingMenuPatches.SelectedMod?.CustomRoles.Values
.OfType<ICustomRole>()
.Where(role => role is { Team: ModdedRoleTeams.Neutral, Configuration.HideSettings: false })
.ToList() ?? [];
if (neutRoles is { Count: > 0 })
{
num -= 0.4f;
var categoryHeaderEditRole3 = Object.Instantiate(
__instance.categoryHeaderEditRoleOrigin,
Vector3.zero,
Quaternion.identity,
__instance.RoleChancesSettings.transform);
categoryHeaderEditRole3.SetHeader(StringNames.None, 20);
categoryHeaderEditRole3.Title.text = "Neutral Roles";
categoryHeaderEditRole3.Background.color = Color.gray;
categoryHeaderEditRole3.Title.color = Color.white;
categoryHeaderEditRole3.transform.localPosition = new Vector3(4.986f, num, -2f);
num -= 0.522f;
foreach (var role in neutRoles)
{
if (role is RoleBehaviour roleBehaviour)
{
CreateQuotaOption(__instance, roleBehaviour, ref num, num3);
}
num3++;
}
}
return false;
}
+2 -2
View File
@@ -90,9 +90,9 @@ public static class TaskAdderPatch
[HarmonyPatch(typeof(TaskAddButton), "Role", MethodType.Setter)]
public static void RoleGetterPatch(TaskAddButton __instance)
{
if (__instance.role is ICustomRole { Team: ModdedRoleTeams.Neutral })
if (__instance.role is ICustomRole { Team: ModdedRoleTeams.Custom } customRole)
{
__instance.FileImage.color = Color.gray;
__instance.FileImage.color = customRole.Configuration.IntroTeamColor ?? Color.gray;
}
__instance.RolloverHandler.OutColor = __instance.FileImage.color;
+39 -1
View File
@@ -38,8 +38,31 @@ public struct CustomRoleConfiguration
TasksCountForProgress = role.Team is ModdedRoleTeams.Crewmate;
HideSettings = roleBehaviour?.IsDead == true;
CanModifyChance = true;
IntroTeamColor = role.Team switch
{
ModdedRoleTeams.Custom => Color.gray,
_ => null,
};
IntroTeamTitle = role.Team switch
{
ModdedRoleTeams.Custom => "NEUTRAL",
_ => null,
};
IntroTeamDescription = role.Team switch
{
ModdedRoleTeams.Custom => "You are Neutral. You do not have a team.",
_ => null,
};
RoleGroup = role.Team switch
{
ModdedRoleTeams.Crewmate => RoleGroup.Crewmate,
ModdedRoleTeams.Impostor => RoleGroup.Impostor,
ModdedRoleTeams.Custom => RoleGroup.Neutral,
};
}
public RoleGroup RoleGroup;
/// <summary>
/// Gets the hard limit of players that can have this role. This property is used to set a limit in the Role Options menu. If set to 0, the role will not be assigned at start.
/// </summary>
@@ -105,6 +128,21 @@ public struct CustomRoleConfiguration
/// </summary>
public bool HideSettings;
/// <summary>
/// Gets the color to show during the "Team" part of the intro cutscene.
/// </summary>
public Color? IntroTeamColor;
/// <summary>
/// Gets the title text to show during the "Team" part of the intro cutscene.
/// </summary>
public string? IntroTeamTitle;
/// <summary>
/// Gets the description text to show during the "Team" part of the intro cutscene.
/// </summary>
public string? IntroTeamDescription;
/// <summary>
/// Gets the outline color for the KillButton if <see cref="UseVanillaKillButton"/> is true.
/// </summary>
@@ -119,4 +157,4 @@ public struct CustomRoleConfiguration
/// Gets the Ghost role that is applied when the player is killed.
/// </summary>
public RoleTypes GhostRole;
}
}
+1 -1
View File
@@ -79,7 +79,7 @@ public static class CustomRoleManager
var roleId = RoleIds[roleType];
roleBehaviour.Role = (RoleTypes)roleId;
roleBehaviour.TeamType = customRole.Team == ModdedRoleTeams.Neutral ? RoleTeamTypes.Crewmate : (RoleTeamTypes)customRole.Team;
roleBehaviour.TeamType = customRole.Team == ModdedRoleTeams.Custom ? RoleTeamTypes.Crewmate : (RoleTeamTypes)customRole.Team;
roleBehaviour.NameColor = customRole.RoleColor;
roleBehaviour.StringName = CustomStringName.CreateAndRegister(customRole.RoleName);
roleBehaviour.BlurbName = CustomStringName.CreateAndRegister(customRole.RoleDescription);
+1 -1
View File
@@ -4,5 +4,5 @@ public enum ModdedRoleTeams
{
Crewmate,
Impostor,
Neutral,
Custom,
}
+16
View File
@@ -0,0 +1,16 @@
using UnityEngine;
namespace MiraAPI.Roles;
/// <summary>
/// Represents a group of roles.
/// </summary>
/// <param name="Name">The group's name.</param>
/// <param name="Color">The group's color.</param>
/// <param name="Priority">The priority to sort by on role setting screen. Negative means first.</param>
public record struct RoleGroup(string Name, Color Color, int Priority = 0)
{
public static RoleGroup Crewmate { get; } = new("Crewmate", Palette.CrewmateBlue, -2);
public static RoleGroup Impostor { get; } = new("Impostor", Palette.ImpostorRed, -1);
public static RoleGroup Neutral { get; } = new("Neutral", Color.gray);
}