├── .gitignore
├── CodeIsNotAmongUs.sln
├── CodeIsNotAmongUs
├── .gitignore
├── CodeIsNotAmongUs.csproj
├── CodeIsNotAmongUsPlugin.cs
├── MeetingHudMode.cs
└── Patches
│ ├── CustomRegion.cs
│ ├── HideCode.cs
│ ├── RemovePlayerLimit
│ ├── ColorPatches.cs
│ ├── MeetingHudModes
│ │ ├── Pagination.cs
│ │ └── Scrolling.cs
│ ├── MeetingPatches.cs
│ ├── RemovePlayerLimit.cs
│ └── TaskPatches.cs
│ └── ShowAllOptions.cs
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | bin/
2 | obj/
3 | /packages/
4 | riderModule.iml
5 | /_ReSharper.Caches/
6 | .idea
--------------------------------------------------------------------------------
/CodeIsNotAmongUs.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeIsNotAmongUs", "CodeIsNotAmongUs\CodeIsNotAmongUs.csproj", "{A964FB9D-5276-4AE8-BF7C-A89F086AE692}"
4 | EndProject
5 | Global
6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
7 | Debug|Any CPU = Debug|Any CPU
8 | Release|Any CPU = Release|Any CPU
9 | EndGlobalSection
10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
11 | {A964FB9D-5276-4AE8-BF7C-A89F086AE692}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
12 | {A964FB9D-5276-4AE8-BF7C-A89F086AE692}.Debug|Any CPU.Build.0 = Debug|Any CPU
13 | {A964FB9D-5276-4AE8-BF7C-A89F086AE692}.Release|Any CPU.ActiveCfg = Release|Any CPU
14 | {A964FB9D-5276-4AE8-BF7C-A89F086AE692}.Release|Any CPU.Build.0 = Release|Any CPU
15 | EndGlobalSection
16 | EndGlobal
17 |
--------------------------------------------------------------------------------
/CodeIsNotAmongUs/.gitignore:
--------------------------------------------------------------------------------
1 | bin/
2 | obj/
3 | /packages/
4 | riderModule.iml
5 | /_ReSharper.Caches/
6 | .idea
--------------------------------------------------------------------------------
/CodeIsNotAmongUs/CodeIsNotAmongUs.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.1
4 | 1.0.0
5 | latest
6 | 2020.12.9s
7 | NuclearPowered/Mappings:0.1.2
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/CodeIsNotAmongUs/CodeIsNotAmongUsPlugin.cs:
--------------------------------------------------------------------------------
1 | using BepInEx;
2 | using BepInEx.Configuration;
3 | using BepInEx.IL2CPP;
4 | using CodeIsNotAmongUs.Patches;
5 | using CodeIsNotAmongUs.Patches.RemovePlayerLimit;
6 | using HarmonyLib;
7 | using Reactor;
8 |
9 | namespace CodeIsNotAmongUs
10 | {
11 | [BepInPlugin(Id)]
12 | [BepInProcess("Among Us.exe")]
13 | [BepInDependency(ReactorPlugin.Id)]
14 | public class CodeIsNotAmongUsPlugin : BasePlugin
15 | {
16 | public const string Id = "pl.js6pak.CodeIsNotAmongUs";
17 |
18 | public Harmony Harmony { get; } = new Harmony(Id);
19 |
20 | public ConfigEntry HideCode { get; private set; }
21 | public ConfigEntry ShowAllOptions { get; private set; }
22 | public ConfigEntry MeetingHudMode { get; internal set; }
23 |
24 | public override void Load()
25 | {
26 | HideCode = Config.Bind("Tweaks", "Hide code", false, "Hides code while in lobby (its printed out in the logs)");
27 | ShowAllOptions = Config.Bind("Tweaks", "Show all options", true, "Allows changing options like map, impostor count, player max count in lobby");
28 | MeetingHudMode = Config.Bind("RemovePlayerLimit", "MeetingHud Mode", CodeIsNotAmongUs.MeetingHudMode.Pagination);
29 |
30 | CustomRegion.Initialize(this);
31 | RemovePlayerLimit.Initialize();
32 | ColorPatches.Initialize();
33 | Harmony.PatchAll();
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/CodeIsNotAmongUs/MeetingHudMode.cs:
--------------------------------------------------------------------------------
1 | namespace CodeIsNotAmongUs
2 | {
3 | public enum MeetingHudMode
4 | {
5 | Scrolling,
6 | Pagination
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/CodeIsNotAmongUs/Patches/CustomRegion.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Reflection;
4 | using BepInEx.Configuration;
5 | using HarmonyLib;
6 |
7 | namespace CodeIsNotAmongUs.Patches
8 | {
9 | internal static class CustomRegion
10 | {
11 | private static List _defaultRegions;
12 |
13 | private static readonly PropertyInfo _orphanedEntriesProperty = AccessTools.Property(typeof(ConfigFile), "OrphanedEntries");
14 | private const string Section = "Custom regions";
15 |
16 | public static void Initialize(CodeIsNotAmongUsPlugin plugin)
17 | {
18 | _defaultRegions = ServerManager.DefaultRegions.ToList();
19 |
20 | var config = plugin.Config;
21 |
22 | config.ConfigReloaded += (_, _) => Reload(config);
23 | Reload(config);
24 | }
25 |
26 | public static void Reload(ConfigFile config)
27 | {
28 | var orphanedEntries = (Dictionary) _orphanedEntriesProperty.GetValue(config);
29 |
30 | var regions = orphanedEntries.Where(x => x.Key.Section == Section).ToList();
31 |
32 | if (!regions.Any())
33 | {
34 | orphanedEntries.Add(new ConfigDefinition(Section, "localhost"), "127.0.0.1:22023");
35 | config.Save();
36 |
37 | Reload(config);
38 | return;
39 | }
40 |
41 | var newRegions = _defaultRegions.ToList();
42 |
43 | foreach (var pair in regions)
44 | {
45 | newRegions.Add(pair.Key.Key, pair.Value);
46 | }
47 |
48 | ServerManager.DefaultRegions = newRegions.ToArray();
49 | }
50 |
51 | private static void Add(this IList regions, string name, string rawIp)
52 | {
53 | var split = rawIp.Split(':');
54 | var ip = split[0];
55 | var port = ushort.TryParse(split.ElementAtOrDefault(1), out var p) ? p : (ushort) 22023;
56 |
57 | regions.Insert(0, new RegionInfo(
58 | name, ip, new[]
59 | {
60 | new ServerInfo($"{name}-Master-1", ip, port)
61 | })
62 | );
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/CodeIsNotAmongUs/Patches/HideCode.cs:
--------------------------------------------------------------------------------
1 | using HarmonyLib;
2 | using Reactor;
3 |
4 | namespace CodeIsNotAmongUs.Patches
5 | {
6 | [HarmonyPatch(typeof(GameStartManager), nameof(GameStartManager.Start))]
7 | internal static class HideCode
8 | {
9 | public static void Postfix(GameStartManager __instance)
10 | {
11 | var plugin = PluginSingleton.Instance;
12 |
13 | if (plugin.HideCode.Value)
14 | {
15 | __instance.GameRoomName.Text = "Room\r\nhidden";
16 | plugin.Log.LogInfo($"Room code ({GameCode.IntToGameNameV2(AmongUsClient.Instance.GameId)}) hidden");
17 | }
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/CodeIsNotAmongUs/Patches/RemovePlayerLimit/ColorPatches.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Reflection;
4 | using HarmonyLib;
5 | using UnityEngine;
6 |
7 | namespace CodeIsNotAmongUs.Patches.RemovePlayerLimit
8 | {
9 | internal static class ColorPatches
10 | {
11 | public static void Initialize()
12 | {
13 | AddColor("Cyan", Color32(0, 150, 136), Color32(0, 121, 107));
14 | AddColor("Gray", Color32(117, 117, 117), Color32(97, 97, 97));
15 | AddColor("Tan", Color32(145, 137, 119), Color32(81, 66, 62));
16 | }
17 |
18 | private static Color32 Color32(byte r, byte g, byte b)
19 | {
20 | return new Color32(r, g, b, 255);
21 | }
22 |
23 | private static void AddColor(string name, Color32 color, Color32 shadow)
24 | {
25 | Telemetry.ColorNames = Telemetry.ColorNames.AddItem(name).ToArray();
26 | MedScanMinigame.ColorNames = MedScanMinigame.ColorNames.AddItem(name).ToArray();
27 |
28 | Palette.PlayerColors = Palette.PlayerColors.AddItem(color).ToArray();
29 | Palette.ShadowColors = Palette.ShadowColors.AddItem(shadow).ToArray();
30 | }
31 |
32 | [HarmonyPatch(typeof(PlayerTab), nameof(PlayerTab.UpdateAvailableColors))]
33 | public static class UpdateAvailableColorsPatch
34 | {
35 | public static bool Prefix(PlayerTab __instance)
36 | {
37 | PlayerControl.SetPlayerMaterialColors(PlayerControl.LocalPlayer.Data.ColorId, __instance.DemoImage);
38 | for (var i = 0; i < Palette.PlayerColors.Length; i++)
39 | {
40 | __instance.AvailableColors.Add(i);
41 | }
42 |
43 | return false;
44 | }
45 | }
46 |
47 | // [HarmonyPatch(typeof(PlayerTab.c__DisplayClass10_0), nameof(PlayerTab.c__DisplayClass10_0.OnEnable))] // inlined SelectColor
48 | [HarmonyPatch]
49 | public static class SelectColorPatch
50 | {
51 | public static IEnumerable TargetMethods()
52 | {
53 | yield return typeof(PlayerTab.c__DisplayClass10_0).GetMethod("Method_Internal_Void_0"); // TODO unhollower being mean
54 | }
55 |
56 | public static bool Prefix(PlayerTab.c__DisplayClass10_0 __instance)
57 | {
58 | var colorId = __instance.j;
59 |
60 | SaveManager.BodyColor = (byte) colorId;
61 | if (PlayerControl.LocalPlayer)
62 | {
63 | PlayerControl.LocalPlayer.CmdCheckColor((byte) colorId);
64 | }
65 |
66 | return false;
67 | }
68 | }
69 |
70 | [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.CheckColor))]
71 | public static class CheckColorPatch
72 | {
73 | public static bool Prefix(PlayerControl __instance, [HarmonyArgument(0)] byte bodyColor)
74 | {
75 | __instance.RpcSetColor(bodyColor);
76 | return false;
77 | }
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/CodeIsNotAmongUs/Patches/RemovePlayerLimit/MeetingHudModes/Pagination.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using HarmonyLib;
3 | using Reactor;
4 | using UnityEngine;
5 |
6 | namespace CodeIsNotAmongUs.Patches.RemovePlayerLimit.MeetingHudModes
7 | {
8 | internal static class Pagination
9 | {
10 | private static bool Enabled => PluginSingleton.Instance.MeetingHudMode.Value == MeetingHudMode.Pagination;
11 |
12 | public static int Page { get; set; }
13 |
14 | private static string _lastText;
15 |
16 | private static void UpdatePageText(MeetingHud meetingHud, int maxPages)
17 | {
18 | if (meetingHud.TimerText.Text == _lastText)
19 | return;
20 |
21 | meetingHud.TimerText.Text = _lastText = meetingHud.TimerText.Text + $" ({Page + 1}/{maxPages})";
22 | }
23 |
24 | [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.Update))]
25 | public static class ButtonsPatch
26 | {
27 | public static void Postfix(MeetingHud __instance)
28 | {
29 | if (!Enabled)
30 | return;
31 |
32 | var maxPages = (int) Mathf.Ceil(__instance.playerStates.Count / 10f);
33 |
34 | Page = Input.mouseScrollDelta.y switch
35 | {
36 | > 0 => Mathf.Clamp(Page - 1, 0, maxPages - 1),
37 | < 0 => Mathf.Clamp(Page + 1, 0, maxPages - 1),
38 | _ => Page
39 | };
40 |
41 | UpdatePageText(__instance, maxPages);
42 |
43 | var i = 0;
44 |
45 | foreach (var playerVoteArea in __instance.playerStates.ToArray().OrderBy(x => x.isDead).ThenBy(x => x.NameText.Text))
46 | {
47 | var active = i >= 10 * Page && i < 10 * (Page + 1);
48 | playerVoteArea.gameObject.SetActive(active);
49 |
50 | if (active)
51 | {
52 | var paged = i - Page * 10;
53 | var x = paged % 2;
54 | var y = paged / 2;
55 | playerVoteArea.transform.localPosition = __instance.VoteOrigin + new Vector3(__instance.VoteButtonOffsets.x * x, __instance.VoteButtonOffsets.y * y, -1f);
56 | }
57 |
58 | i++;
59 | }
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/CodeIsNotAmongUs/Patches/RemovePlayerLimit/MeetingHudModes/Scrolling.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using HarmonyLib;
3 | using Reactor;
4 | using UnityEngine;
5 |
6 | namespace CodeIsNotAmongUs.Patches.RemovePlayerLimit.MeetingHudModes
7 | {
8 | internal static class Scrolling
9 | {
10 | private static bool Enabled => PluginSingleton.Instance.MeetingHudMode.Value == MeetingHudMode.Scrolling;
11 |
12 | public static float Scroll { get; set; }
13 |
14 | [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.Start))]
15 | public static class StartPatch
16 | {
17 | public static void Postfix(MeetingHud __instance)
18 | {
19 | if (!Enabled)
20 | return;
21 |
22 | var original = __instance.transform.FindChild("Background").FindChild("baseGlass").gameObject;
23 | var mask = Object.Instantiate(original);
24 | mask.name = "Scrolling mask";
25 | mask.transform.position = original.transform.position;
26 | // mask.transform.localScale = new Vector3(0.8f, 0.8f, 1f);
27 | var spriteRenderer = mask.GetComponent();
28 | spriteRenderer.color = Color.red;
29 | var spriteMask = mask.AddComponent();
30 | spriteMask.sprite = spriteRenderer.sprite;
31 | // Object.Destroy(spriteRenderer);
32 | }
33 | }
34 |
35 | [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.Update))]
36 | public static class ButtonsPatch
37 | {
38 | public static void Postfix(MeetingHud __instance)
39 | {
40 | if (!Enabled)
41 | return;
42 |
43 | var maxPages = (int) Mathf.Ceil(__instance.playerStates.Count / 10f);
44 |
45 | Scroll = Mathf.Clamp(Scroll + Input.mouseScrollDelta.y, -maxPages, 0);
46 | System.Console.WriteLine("maxPages " + maxPages);
47 | System.Console.WriteLine("scroll " + Scroll);
48 |
49 | var i = 0;
50 |
51 | foreach (var playerVoteArea in __instance.playerStates.ToArray().OrderBy(x => x.isDead).ThenBy(x => x.NameText.Text))
52 | {
53 | var x = i % 2;
54 | var y = i / 2 + Scroll / 2f;
55 | playerVoteArea.transform.localPosition = __instance.VoteOrigin + new Vector3(__instance.VoteButtonOffsets.x * x, __instance.VoteButtonOffsets.y * y, -1f);
56 |
57 | foreach (var renderer in playerVoteArea.GetComponentsInChildren())
58 | {
59 | renderer.maskInteraction = SpriteMaskInteraction.VisibleInsideMask;
60 | }
61 |
62 | i++;
63 | }
64 | }
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/CodeIsNotAmongUs/Patches/RemovePlayerLimit/MeetingPatches.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using HarmonyLib;
3 | using Hazel;
4 | using UnhollowerBaseLib;
5 | using UnityEngine;
6 | using Object = Il2CppSystem.Object;
7 |
8 | namespace CodeIsNotAmongUs.Patches.RemovePlayerLimit
9 | {
10 | public static class MeetingPatches
11 | {
12 | [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.CheckForEndVoting))]
13 | public static class CheckForEndVotingPatch
14 | {
15 | // "api" for all mayors out there :)
16 | public static byte GetVotePower(PlayerVoteArea playerVoteArea)
17 | {
18 | return 1;
19 | }
20 |
21 | public static int IndexOfMax(T[] self, out bool tie)
22 | {
23 | var max = self.Max();
24 |
25 | if (self.Count(x => x.Equals(max)) > 1)
26 | {
27 | tie = true;
28 | return -1;
29 | }
30 |
31 | tie = false;
32 | return self.ToList().IndexOf(max);
33 | }
34 |
35 | public static bool Prefix(MeetingHud __instance)
36 | {
37 | var playerStates = __instance.playerStates;
38 | if (playerStates.All(ps => ps != null && (ps.isDead || ps.didVote)))
39 | {
40 | var self = new byte[playerStates.Max(x => x.TargetPlayerId) + 2];
41 | foreach (var playerVoteArea in playerStates)
42 | {
43 | if (playerVoteArea.didVote && !playerVoteArea.isDead)
44 | {
45 | // -2 none, -1 skip, 0+ players
46 | if (playerVoteArea.votedFor == -2)
47 | continue;
48 |
49 | var votedFor = playerVoteArea.votedFor + 1;
50 | if (votedFor >= 0 && votedFor < self.Length)
51 | {
52 | self[votedFor] += GetVotePower(playerVoteArea);
53 | }
54 | }
55 | }
56 |
57 | var maxIdx = IndexOfMax(self, out var tie) - 1;
58 | var exiled = GameData.Instance.AllPlayers.ToArray().FirstOrDefault(v => v != null && v.PlayerId == maxIdx);
59 |
60 | var states = playerStates.Select(ps => ps != null ? ps.GetState() : (byte) 0).ToArray();
61 | var votes = playerStates.Select(s => (byte) s.votedFor).ToArray();
62 |
63 | var messageWriter = AmongUsClient.Instance.StartRpc(__instance.NetId, 23, SendOption.Reliable);
64 | messageWriter.WriteBytesAndSize(states);
65 | messageWriter.WriteBytesAndSize(votes);
66 | messageWriter.Write(exiled != null && exiled.Object != null ? exiled.Object.PlayerId : byte.MaxValue);
67 | messageWriter.Write(tie);
68 | messageWriter.EndMessage();
69 |
70 | VotingComplete(__instance, states, votes, exiled, tie);
71 | }
72 |
73 | return false;
74 | }
75 | }
76 |
77 | [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.HandleRpc))]
78 | public static class MeetingHudHandleRpcPatch
79 | {
80 | public static bool Prefix(MeetingHud __instance, [HarmonyArgument(0)] byte callId, [HarmonyArgument(1)] MessageReader reader)
81 | {
82 | if (callId == (int) RpcCalls.VotingComplete)
83 | {
84 | var states = reader.ReadBytesAndSize();
85 | var votes = reader.ReadBytesAndSize();
86 | var playerById = GameData.Instance.GetPlayerById(reader.ReadByte());
87 | var tie = reader.ReadBoolean();
88 | VotingComplete(__instance, states, votes, playerById, tie);
89 |
90 | return false;
91 | }
92 |
93 | return true;
94 | }
95 | }
96 |
97 | private static void VotingComplete(MeetingHud __instance, byte[] states, byte[] votes, GameData.PlayerInfo exiled, bool tie)
98 | {
99 | if (__instance.state == MeetingHud.VoteStates.Results)
100 | {
101 | return;
102 | }
103 |
104 | __instance.state = MeetingHud.VoteStates.Results;
105 | __instance.resultsStartedAt = __instance.discussionTimer;
106 | __instance.exiledPlayer = exiled;
107 | __instance.wasTie = tie;
108 | __instance.SkipVoteButton.gameObject.SetActive(false);
109 | __instance.SkippedVoting.gameObject.SetActive(true);
110 | AmongUsClient.Instance.DisconnectHandlers.Remove(__instance.Cast());
111 | PopulateResults(__instance, states, votes);
112 | __instance.SetupProceedButton();
113 | }
114 |
115 | private static void PopulateResults(MeetingHud __instance, byte[] states, byte[] votes)
116 | {
117 | __instance.TitleText.Text = DestroyableSingleton.Instance.GetString(StringNames.MeetingVotingResults, new Il2CppReferenceArray