mirror of
https://github.com/All-Of-Us-Mods/MiraAPI.git
synced 2026-10-19 15:51:48 +00:00
Fix crashing on Epic and MS Store
This commit is contained in:
1 parent
df7c182abb
commit
043845ee11
2 files changed
+111
-76
No files matched your search
@@ -1,76 +0,0 @@
|
||||
using AmongUs.GameOptions;
|
||||
using HarmonyLib;
|
||||
using Il2CppSystem.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MiraAPI.Roles;
|
||||
|
||||
namespace MiraAPI.Patches.Roles;
|
||||
|
||||
[HarmonyPatch(typeof(LogicRoleSelectionNormal))]
|
||||
public static class LogicRoleSelectionNormalPatch
|
||||
{
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(LogicRoleSelectionNormal.AssignRolesForTeam))]
|
||||
public static bool AssignRolesForTeam(
|
||||
LogicRoleSelectionNormal __instance,
|
||||
List<NetworkedPlayerInfo> players,
|
||||
IGameOptions opts,
|
||||
RoleTeamTypes team,
|
||||
int teamMax,
|
||||
Il2CppSystem.Nullable<RoleTypes> defaultRole)
|
||||
{
|
||||
int num = 0;
|
||||
var source = RoleManager.Instance.AllRoles.ToArray()
|
||||
.Where(role => role.TeamType == team && !RoleManager.IsGhostRole(role.Role) &&
|
||||
CustomRoleUtils.CanSpawnOnCurrentMode(role));
|
||||
List<RoleTypes> list = new List<RoleTypes>();
|
||||
IRoleOptionsCollection roleOptions = opts.RoleOptions;
|
||||
|
||||
// Assign guaranteed roles first, just like the vanilla selector. This is
|
||||
// important because the list of players is shared by both team passes.
|
||||
foreach (var role in source.Where(x => roleOptions.GetChancePerGame(x.Role) == 100)
|
||||
.Select(role => role.Role))
|
||||
{
|
||||
for (var i = 0; i < roleOptions.GetNumPerGame(role); i++)
|
||||
{
|
||||
list.Add(role);
|
||||
}
|
||||
}
|
||||
|
||||
__instance.AssignRolesFromList(players, teamMax, list, ref num);
|
||||
|
||||
// A 100% role was already assigned above. Including it here can consume
|
||||
// another player and, more importantly, leaves the fallback count wrong.
|
||||
list.Clear();
|
||||
foreach (var role in source.Where(x =>
|
||||
roleOptions.GetChancePerGame(x.Role) > 0 &&
|
||||
roleOptions.GetChancePerGame(x.Role) < 100)
|
||||
.Select(role => role.Role))
|
||||
{
|
||||
for (var i = 0; i < roleOptions.GetNumPerGame(role); i++)
|
||||
{
|
||||
if (HashRandom.Next(101) < roleOptions.GetChancePerGame(role))
|
||||
{
|
||||
list.Add(role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__instance.AssignRolesFromList(players, teamMax, list, ref num);
|
||||
|
||||
// Do not read defaultRole here. The nullable argument is not marshalled
|
||||
// reliably by IL2CPP and can return Crewmate for the impostor pass.
|
||||
var defaultRole2 = team is RoleTeamTypes.Crewmate ? RoleTypes.Crewmate : RoleTypes.Impostor;
|
||||
|
||||
// Assign the remaining players up to the requested team limit. The
|
||||
// vanilla list has been consumed by AssignRolesFromList at this point,
|
||||
// so checking list.Count can leave players unassigned.
|
||||
while (players.Count > 0 && num < teamMax)
|
||||
{
|
||||
list.Add(defaultRole2);
|
||||
__instance.AssignRolesFromList(players, teamMax, list, ref num);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
using System.Collections.Generic;
|
||||
using AmongUs.GameOptions;
|
||||
using HarmonyLib;
|
||||
using System.Linq;
|
||||
using InnerNet;
|
||||
using MiraAPI.Roles;
|
||||
|
||||
namespace MiraAPI.Patches.Roles;
|
||||
|
||||
[HarmonyPatch(typeof(RoleManager))]
|
||||
public static class SelectRolesPatch
|
||||
{
|
||||
public static bool ApiHandlesRoleSelect = true;
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(RoleManager.SelectRoles))]
|
||||
public static bool SelectRoles()
|
||||
{
|
||||
if (!ApiHandlesRoleSelect)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Il2CppSystem.Collections.Generic.List<ClientData> list = new();
|
||||
AmongUsClient.Instance.GetAllClients(list);
|
||||
List<NetworkedPlayerInfo> list2 = list.ToArray()
|
||||
.Where(c => c.Character != null && c.Character.Data != null && !c.Character.Data.Disconnected &&
|
||||
!c.Character.Data.IsDead).OrderBy(c => c.Id).Select(c => c.Character.Data)
|
||||
.ToList();
|
||||
|
||||
foreach (NetworkedPlayerInfo networkedPlayerInfo in GameData.Instance.AllPlayers)
|
||||
{
|
||||
if (networkedPlayerInfo.Object != null && networkedPlayerInfo.Object.isDummy)
|
||||
{
|
||||
list2.Add(networkedPlayerInfo);
|
||||
}
|
||||
}
|
||||
IGameOptions currentGameOptions = GameOptionsManager.Instance.CurrentGameOptions;
|
||||
int adjustedNumImpostors = GameOptionsManager.Instance.CurrentGameOptions.GetAdjustedNumImpostors(list2.Count);
|
||||
AssignRolesForTeam(list2, currentGameOptions, RoleTeamTypes.Impostor, adjustedNumImpostors, RoleTypes.Impostor);
|
||||
AssignRolesForTeam(list2, currentGameOptions, RoleTeamTypes.Crewmate, int.MaxValue, RoleTypes.Crewmate);
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void AssignRolesForTeam(
|
||||
List<NetworkedPlayerInfo> players,
|
||||
IGameOptions opts,
|
||||
RoleTeamTypes team,
|
||||
int teamMax,
|
||||
RoleTypes defaultRole)
|
||||
{
|
||||
int num = 0;
|
||||
var source = RoleManager.Instance.AllRoles.ToArray()
|
||||
.Where(role => role.TeamType == team && !RoleManager.IsGhostRole(role.Role) &&
|
||||
CustomRoleUtils.CanSpawnOnCurrentMode(role));
|
||||
List<RoleTypes> list = new List<RoleTypes>();
|
||||
IRoleOptionsCollection roleOptions = opts.RoleOptions;
|
||||
|
||||
// Assign guaranteed roles first, just like the vanilla selector. This is
|
||||
// important because the list of players is shared by both team passes.
|
||||
foreach (var role in source.Where(x => roleOptions.GetChancePerGame(x.Role) == 100)
|
||||
.Select(role => role.Role))
|
||||
{
|
||||
for (var i = 0; i < roleOptions.GetNumPerGame(role); i++)
|
||||
{
|
||||
list.Add(role);
|
||||
}
|
||||
}
|
||||
|
||||
AssignRolesFromList(players, teamMax, list, ref num);
|
||||
|
||||
// A 100% role was already assigned above. Including it here can consume
|
||||
// another player and, more importantly, leaves the fallback count wrong.
|
||||
list.Clear();
|
||||
foreach (var role in source.Where(x =>
|
||||
roleOptions.GetChancePerGame(x.Role) > 0 &&
|
||||
roleOptions.GetChancePerGame(x.Role) < 100)
|
||||
.Select(role => role.Role))
|
||||
{
|
||||
for (var i = 0; i < roleOptions.GetNumPerGame(role); i++)
|
||||
{
|
||||
if (HashRandom.Next(101) < roleOptions.GetChancePerGame(role))
|
||||
{
|
||||
list.Add(role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AssignRolesFromList(players, teamMax, list, ref num);
|
||||
|
||||
// Assign the remaining players up to the requested team limit. The
|
||||
// vanilla list has been consumed by AssignRolesFromList at this point,
|
||||
// so checking list.Count can leave players unassigned.
|
||||
while (players.Count > 0 && num < teamMax)
|
||||
{
|
||||
list.Add(defaultRole);
|
||||
AssignRolesFromList(players, teamMax, list, ref num);
|
||||
}
|
||||
}
|
||||
private static void AssignRolesFromList(List<NetworkedPlayerInfo> players, int teamMax, List<RoleTypes> roleList, ref int rolesAssigned)
|
||||
{
|
||||
while (roleList.Count > 0 && players.Count > 0 && rolesAssigned < teamMax)
|
||||
{
|
||||
int index = HashRandom.FastNext(roleList.Count);
|
||||
RoleTypes roleType = roleList[index];
|
||||
roleList.RemoveAt(index);
|
||||
int index2 = HashRandom.FastNext(players.Count);
|
||||
players[index2].Object.RpcSetRole(roleType, false);
|
||||
players.RemoveAt(index2);
|
||||
rolesAssigned++;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user