Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions NewMod.sln
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@ Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
ANDROID|Any CPU = ANDROID|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FC05DD49-CE3A-41F4-8452-37686FE23D0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC05DD49-CE3A-41F4-8452-37686FE23D0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC05DD49-CE3A-41F4-8452-37686FE23D0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC05DD49-CE3A-41F4-8452-37686FE23D0A}.Release|Any CPU.Build.0 = Release|Any CPU
{FC05DD49-CE3A-41F4-8452-37686FE23D0A}.ANDROID|Any CPU.ActiveCfg = ANDROID|Any CPU
{FC05DD49-CE3A-41F4-8452-37686FE23D0A}.ANDROID|Any CPU.Build.0 = ANDROID|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
2 changes: 1 addition & 1 deletion NewMod/Buttons/Revenant/DoomAwakening.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ public System.Collections.IEnumerator StartDoomAwakening(PlayerControl player)
// Kill any nearby players
foreach (var target in PlayerControl.AllPlayerControls)
{
if (target == player || target.Data.IsDead || target.Data.Disconnected || target.inVent || target.Data.Role.IsImpostor)
if (target == player || target.Data.IsDead || target.Data.Disconnected || target.inVent || target.Data.Role.IsImpostor || target.Data.PlayerName == "Wraith NPC")
continue;

if (Vector2.Distance(player.GetTruePosition(), target.GetTruePosition()) < 1f)
Expand Down
8 changes: 6 additions & 2 deletions NewMod/DiscordStatus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ public static bool StartPrefix(DiscordManager __instance)
{
if (Application.platform == RuntimePlatform.Android) return true;

InitializeDiscord(__instance);
return false;
}

private static void InitializeDiscord(DiscordManager __instance)
{
const long clientId = 1405946628115791933;

discord = new Discord.Discord(clientId, (ulong)CreateFlags.Default);
Expand All @@ -34,8 +40,6 @@ public static bool StartPrefix(DiscordManager __instance)
}));
__instance.presence = discord;
__instance.SetInMenus();

return false;
}

[HarmonyPrefix]
Expand Down
13 changes: 0 additions & 13 deletions NewMod/LocalSettings/NewModLocalSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,6 @@ public class NewModLocalSettings(ConfigFile config) : LocalSettingsTab(config)
TabIcon = NewModAsset.NMIcon,
};

[LocalSliderSetting("Frame Rate Limit", min: 30f, max: 240f, "Lock your framerate (FPS)", displayValue: true, formatString: "0", roundValue: true)]
public ConfigEntry<float> FrameRateLimit { get; } = config.Bind(
"Performance",
"FrameRateLimit",
165f,
"Frames per second limit"
);

[LocalToggleSetting("Enable Custom Cursor", "Enable the custom cursor from the birthday update")]
public ConfigEntry<bool> EnableCustomCursor { get; } = config.Bind(
"Features",
Expand All @@ -45,11 +37,6 @@ public override void OnOptionChanged(ConfigEntryBase configEntry)
{
base.OnOptionChanged(configEntry);

if (configEntry == FrameRateLimit)
{
Application.targetFrameRate = (int)FrameRateLimit.Value;
}

if (configEntry == AlwaysButtonsLeft && Application.platform == RuntimePlatform.Android)
{
foreach (var btn in CustomButtonManager.Buttons)
Expand Down
262 changes: 126 additions & 136 deletions NewMod/NewMod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
using MiraAPI.Events;
using NewMod.Patches.Compatibility;
using NewMod.Buttons.Overload;
using MiraAPI.LocalSettings;

namespace NewMod;

Expand All @@ -36,154 +35,145 @@ namespace NewMod;
[BepInProcess("Among Us.exe")]
public partial class NewMod : BasePlugin, IMiraPlugin
{
public const string Id = "com.callofcreator.newmod";
public const string ModVersion = "1.2.8";
public Harmony Harmony { get; } = new Harmony(Id);
public static BasePlugin Instance;
public static Minigame minigame;
public const string SupportedAmongUsVersion = "2025.10.14";
public static ConfigEntry<bool> ShouldEnableBepInExConsole { get; set; }
public ConfigFile GetConfigFile() => Config;
public string OptionsTitleText => "NewMod";
public override void Load()
{
Instance = this;
AddComponent<DebugWindow>();
ReactorCredits.Register<NewMod>(ReactorCredits.AlwaysShow);
Harmony.PatchAll();
CheckVersionCompatibility();
NewModEventHandler.RegisterEventsLogs();
public const string Id = "com.callofcreator.newmod";
public const string ModVersion = "1.2.9";
public Harmony Harmony { get; } = new Harmony(Id);
public static BasePlugin Instance;
public static Minigame minigame;
public static ConfigEntry<bool> ShouldEnableBepInExConsole { get; set; }
public ConfigFile GetConfigFile() => Config;
public string OptionsTitleText => "NewMod";
public override void Load()
{
Instance = this;
AddComponent<DebugWindow>();
ReactorCredits.Register<NewMod>(ReactorCredits.AlwaysShow);
Harmony.PatchAll();
NewModEventHandler.RegisterEventsLogs();

if (ModCompatibility.IsLaunchpadLoaded())
{
Harmony.PatchAll(typeof(LaunchpadCompatibility));
Harmony.PatchAll(typeof(LaunchpadHackTextPatch));
}
ShouldEnableBepInExConsole = Config.Bind("NewMod", "Console", true, "Whether to enable BepInEx Console for debugging");
if (!ShouldEnableBepInExConsole.Value) ConsoleManager.DetachConsole();
if (ModCompatibility.IsLaunchpadLoaded())
{
Harmony.PatchAll(typeof(LaunchpadCompatibility));
Harmony.PatchAll(typeof(LaunchpadHackTextPatch));
}
ShouldEnableBepInExConsole = Config.Bind("NewMod", "Console", true, "Whether to enable BepInEx Console for debugging");
if (!ShouldEnableBepInExConsole.Value) ConsoleManager.DetachConsole();

var bundle = NewModAsset.Bundle;
var assetNames = bundle.GetAllAssetNames();
var bundle = NewModAsset.Bundle;
var assetNames = bundle.GetAllAssetNames();

Instance.Log.LogMessage($"AssetBundle '{bundle.name}' contains {assetNames.Length} assets");
Instance.Log.LogMessage($"AssetBundle '{bundle.name}' contains {assetNames.Length} assets");

foreach (var name in assetNames)
{
Instance.Log.LogMessage($"{name}");
}
foreach (var name in assetNames)
{
Instance.Log.LogMessage($"{name}");
}

Instance.Log.LogMessage($"Loaded Successfully NewMod v{ModVersion} With MiraAPI Version : {MiraApiPlugin.Version}");
}
public static void CheckVersionCompatibility()
{
if (Application.version != SupportedAmongUsVersion)
{
Instance.Log.LogError($"Detected unsupported Among Us version. Current version: {Application.version}, Supported version: {SupportedAmongUsVersion}");
}
}
Instance.Log.LogMessage($"Loaded Successfully NewMod v{ModVersion} With MiraAPI Version : {MiraApiPlugin.Version}");
}

[HarmonyPatch(typeof(KeyboardJoystick), nameof(KeyboardJoystick.Update))]
public class KeyboardJoystickUpdatePatch
{
public static void Postfix(KeyboardJoystick __instance)
{
InitializeKeyBinds();
}
}
public static void InitializeKeyBinds()
{
if (Input.GetKeyDown(KeyCode.F2) && PlayerControl.LocalPlayer.Data.IsDead && OptionGroupSingleton<GeneralOption>.Instance.AllowCams)
{
var sys = Utils.FindSurveillanceConsole();
var mainCam = Camera.main;
if (mainCam == null) return;
[HarmonyPatch(typeof(KeyboardJoystick), nameof(KeyboardJoystick.Update))]
public class KeyboardJoystickUpdatePatch
{
public static void Postfix(KeyboardJoystick __instance)
{
InitializeKeyBinds();
}
}
public static void InitializeKeyBinds()
{
if (Input.GetKeyDown(KeyCode.F2) && PlayerControl.LocalPlayer.Data.IsDead && OptionGroupSingleton<GeneralOption>.Instance.AllowCams)
{
var sys = Utils.FindSurveillanceConsole();
var mainCam = Camera.main;
if (mainCam == null) return;

var minigame = Object.Instantiate(sys.MinigamePrefab, mainCam.transform, false);
minigame.transform.localPosition = new Vector3(0f, 0f, -50f);
minigame.Begin(null);
}
if (Input.GetKeyDown(KeyCode.F3) && PlayerControl.LocalPlayer.Data.Role is NecromancerRole)
{
var deadBodies = Helpers.GetNearestDeadBodies(PlayerControl.LocalPlayer.GetTruePosition(), 20f, Helpers.CreateFilter(Constants.NotShipMask));
if (deadBodies != null && deadBodies.Count > 0)
{
var randomIndex = Random.Range(0, deadBodies.Count);
var randomBodyPosition = deadBodies[randomIndex].transform.position;
PlayerControl.LocalPlayer.NetTransform.RpcSnapTo(randomBodyPosition);
}
else
{
CoroutinesHelper.CoNotify("<b><color=#FF0000>No dead bodies nearby to teleport to.</color></b>");
}
}
}
var minigame = Object.Instantiate(sys.MinigamePrefab, mainCam.transform, false);
minigame.transform.localPosition = new Vector3(0f, 0f, -50f);
minigame.Begin(null);
}
if (Input.GetKeyDown(KeyCode.F3) && PlayerControl.LocalPlayer.Data.Role is NecromancerRole)
{
var deadBodies = Helpers.GetNearestDeadBodies(PlayerControl.LocalPlayer.GetTruePosition(), 20f, Helpers.CreateFilter(Constants.NotShipMask));
if (deadBodies != null && deadBodies.Count > 0)
{
var randomIndex = Random.Range(0, deadBodies.Count);
var randomBodyPosition = deadBodies[randomIndex].transform.position;
PlayerControl.LocalPlayer.NetTransform.RpcSnapTo(randomBodyPosition);
}
else
{
CoroutinesHelper.CoNotify("<b><color=#FF0000>No dead bodies nearby to teleport to.</color></b>");
}
}
}

[RegisterEvent]
public static void OnBeforeMurder(BeforeMurderEvent evt)
{
if (evt.Target != OverloadRole.chosenPrey) return;
[RegisterEvent]
public static void OnBeforeMurder(BeforeMurderEvent evt)
{
if (evt.Target != OverloadRole.chosenPrey) return;

//TODO: Use the newest MiraAPI roles for button mapping
if (evt.Target.Data.Role is ICustomRole customRole && Utils.RoleToButtonsMap.TryGetValue(customRole.GetType(), out var buttonsType))
{
OverloadRole.CachedButtons = [.. CustomButtonManager.Buttons.Where(b => buttonsType.Contains(b.GetType()))];
Instance.Log.LogMessage($"CachedButton: {buttonsType.GetType().Name}");
}
}
[RegisterEvent]
public static void OnAfterMurder(AfterMurderEvent evt)
{
var source = evt.Source;
var target = evt.Target;
Utils.RecordOnKill(source, target);
//TODO: Use the newest MiraAPI roles for button mapping
if (evt.Target.Data.Role is ICustomRole customRole && Utils.RoleToButtonsMap.TryGetValue(customRole.GetType(), out var buttonsType))
{
OverloadRole.CachedButtons = [.. CustomButtonManager.Buttons.Where(b => buttonsType.Contains(b.GetType()))];
Instance.Log.LogMessage($"CachedButton: {buttonsType.GetType().Name}");
}
}
[RegisterEvent]
public static void OnAfterMurder(AfterMurderEvent evt)
{
var source = evt.Source;
var target = evt.Target;
Utils.RecordOnKill(source, target);

if (target != OverloadRole.chosenPrey) return;
if (target != OverloadRole.chosenPrey) return;

foreach (var pc in PlayerControl.AllPlayerControls.ToArray().Where(p => p.AmOwner && p.Data.Role is OverloadRole))
{
if (target.Data.Role is ICustomRole customRole)
{
foreach (var button in OverloadRole.CachedButtons)
foreach (var pc in PlayerControl.AllPlayerControls.ToArray().Where(p => p.AmOwner && p.Data.Role is OverloadRole))
{
if (target.Data.Role is ICustomRole customRole)
{
CustomButtonSingleton<OverloadButton>.Instance.Absorb(button);
Debug.Log($"[Overload] Successfully absorbed ability: {button.Name}");
foreach (var button in OverloadRole.CachedButtons)
{
CustomButtonSingleton<OverloadButton>.Instance.Absorb(button);
Debug.Log($"[Overload] Successfully absorbed ability: {button.Name}");
}
}
}
else if (target.Data.Role is not ICustomRole)
{
var btn = Object.Instantiate(
HudManager.Instance.AbilityButton,
HudManager.Instance.AbilityButton.transform.parent);
btn.SetFromSettings(target.Data.Role.Ability);
var pb = btn.GetComponent<PassiveButton>();
pb.OnClick.RemoveAllListeners();
pb.OnClick.AddListener((UnityAction)target.Data.Role.UseAbility);
}
}
OverloadRole.CachedButtons.Clear();
OverloadRole.AbsorbedAbilityCount++;
OverloadRole.chosenPrey = null;
Coroutines.Start(CoroutinesHelper.CoNotify($"<color=green>Charge {OverloadRole.AbsorbedAbilityCount}/{OptionGroupSingleton<OverloadOptions>.Instance.NeededCharge}</color>"));
else if (target.Data.Role is not ICustomRole)
{
var btn = Object.Instantiate(
HudManager.Instance.AbilityButton,
HudManager.Instance.AbilityButton.transform.parent);
btn.SetFromSettings(target.Data.Role.Ability);
var pb = btn.GetComponent<PassiveButton>();
pb.OnClick.RemoveAllListeners();
pb.OnClick.AddListener((UnityAction)target.Data.Role.UseAbility);
}
}
OverloadRole.CachedButtons.Clear();
OverloadRole.AbsorbedAbilityCount++;
OverloadRole.chosenPrey = null;
Coroutines.Start(CoroutinesHelper.CoNotify($"<color=green>Charge {OverloadRole.AbsorbedAbilityCount}/{OptionGroupSingleton<OverloadOptions>.Instance.NeededCharge}</color>"));

if (OverloadRole.AbsorbedAbilityCount >= OptionGroupSingleton<OverloadOptions>.Instance.NeededCharge)
{
Coroutines.Start(CoroutinesHelper.CoNotify("<color=#00FF7F>Objective completed: Final Ability unlocked!</color>"));
}
else
{
Coroutines.Start(OverloadRole.CoShowMenu(1f));
}
}
if (OverloadRole.AbsorbedAbilityCount >= OptionGroupSingleton<OverloadOptions>.Instance.NeededCharge)
{
Coroutines.Start(CoroutinesHelper.CoNotify("<color=#00FF7F>Objective completed: Final Ability unlocked!</color>"));
}
else
{
Coroutines.Start(OverloadRole.CoShowMenu(1f));
}
}

[HarmonyPatch(typeof(TaskPanelBehaviour), nameof(TaskPanelBehaviour.SetTaskText))]
public static class SetTaskTextPatch
{
public static void Postfix(TaskPanelBehaviour __instance, [HarmonyArgument(0)] string str)
{
if (PlayerControl.LocalPlayer.Data.IsDead)
{
__instance.taskText.text += "\n" + (OptionGroupSingleton<GeneralOption>.Instance.AllowCams ? "<color=blue>Press F2 For Open Cams</color>" : "<color=red>You cannot open cams because the host has disabled this setting</color>");
}
}
}
[HarmonyPatch(typeof(TaskPanelBehaviour), nameof(TaskPanelBehaviour.SetTaskText))]
public static class SetTaskTextPatch
{
public static void Postfix(TaskPanelBehaviour __instance, [HarmonyArgument(0)] string str)
{
if (PlayerControl.LocalPlayer.Data.IsDead)
{
__instance.taskText.text += "\n" + (OptionGroupSingleton<GeneralOption>.Instance.AllowCams ? "<color=blue>Press F2 For Open Cams</color>" : "<color=red>You cannot open cams because the host has disabled this setting</color>");
}
}
}
}
Loading