--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Collections;
+using UnityEngine;
+using static TheOtherRoles.TheOtherRoles;
+
+namespace TheOtherRoles{
+ public class Arrow {
+ public float perc = 0.925f;
+ public SpriteRenderer image;
+ public GameObject arrow;
+ private Vector3 oldTarget;
+
+ private static Sprite sprite;
+ public static Sprite getSprite() {
+ if (sprite) return sprite;
+ sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.Arrow.png", 200f);
+ return sprite;
+ }
+
+
+ public Arrow(Color color) {
+ arrow = new GameObject("Arrow");
+ arrow.layer = 5;
+ image = arrow.AddComponent<SpriteRenderer>();
+ image.sprite = getSprite();
+ image.color = color;
+ }
+
+ public void Update() {
+ Vector3 target = oldTarget;
+ if (target == null) target = Vector3.zero;
+ Update(target);
+ }
+
+ public void Update(Vector3 target)
+ {
+ if (arrow == null) return;
+ oldTarget = target;
+
+ Camera main = Camera.main;
+ Vector2 vector = target - main.transform.position;
+ float num = vector.magnitude / (main.orthographicSize * perc);
+ image.enabled = ((double)num > 0.3);
+ Vector2 vector2 = main.WorldToViewportPoint(target);
+ if (Between(vector2.x, 0f, 1f) && Between(vector2.y, 0f, 1f))
+ {
+ arrow.transform.position = target - (Vector3)vector.normalized * 0.6f;
+ float num2 = Mathf.Clamp(num, 0f, 1f);
+ arrow.transform.localScale = new Vector3(num2, num2, num2);
+ }
+ else
+ {
+ Vector2 vector3 = new Vector2(Mathf.Clamp(vector2.x * 2f - 1f, -1f, 1f), Mathf.Clamp(vector2.y * 2f - 1f, -1f, 1f));
+ float orthographicSize = main.orthographicSize;
+ float num3 = main.orthographicSize * main.aspect;
+ Vector3 vector4 = new Vector3(Mathf.LerpUnclamped(0f, num3 * 0.88f, vector3.x), Mathf.LerpUnclamped(0f, orthographicSize * 0.79f, vector3.y), 0f);
+ arrow.transform.position = main.transform.position + vector4;
+ arrow.transform.localScale = Vector3.one;
+ }
+
+ LookAt2d(arrow.transform, target);
+ }
+
+ private void LookAt2d(Transform transform, Vector3 target) {
+ Vector3 vector = target - transform.position;
+ vector.Normalize();
+ float num = Mathf.Atan2(vector.y, vector.x);
+ if (transform.lossyScale.x < 0f)
+ num += 3.1415927f;
+ transform.rotation = Quaternion.Euler(0f, 0f, num * 57.29578f);
+ }
+
+ private bool Between(float value, float min, float max) {
+ return value > min && value < max;
+ }
+ }
+}
\ No newline at end of file
+++ /dev/null
-using System.Net;
-using System.Linq;
-using BepInEx;
-using BepInEx.Configuration;
-using BepInEx.IL2CPP;
-using HarmonyLib;
-using Hazel;
-using Reactor;
-using System;
-using System.Collections.Generic;
-using System.Collections;
-using System.IO;
-using UnityEngine;
-using Reactor.Unstrip;
-using Reactor.Extensions;
-
-namespace BonusRoles
-{
- [HarmonyPatch]
- public static class BonusRoles
- {
- public static System.Random rnd = new System.Random((int)DateTime.Now.Ticks);
-
- public static void clearAndReloadRoles() {
- Jester.clearAndReload();
- Mayor.clearAndReload();
- Engineer.clearAndReload();
- Sheriff.clearAndReload();
- Lighter.clearAndReload();
- Godfather.clearAndReload();
- Mafioso.clearAndReload();
- Janitor.clearAndReload();
- Detective.clearAndReload();
- TimeMaster.clearAndReload();
- Medic.clearAndReload();
- Shifter.clearAndReload();
- Swapper.clearAndReload();
- Lovers.clearAndReload();
- Seer.clearAndReload();
- Morphling.clearAndReload();
- Camouflager.clearAndReload();
- Spy.clearAndReload();
- Child.clearAndReload();
- }
-
- public static class Jester {
- public static PlayerControl jester;
- public static Color color = new Color(255f / 255f, 84f / 255f, 167f / 255f, 1);
-
- public static void clearAndReload() {
- jester = null;
- }
- }
-
- public static class Mayor {
- public static PlayerControl mayor;
- public static Color color = new Color(105f / 255f, 58f / 255f, 58f / 255f, 1);
-
- public static void clearAndReload() {
- mayor = null;
- }
- }
-
- public static class Engineer {
- public static PlayerControl engineer;
- public static Color color = new Color(98f / 255f, 216f / 255f, 240f / 255f, 1);
- public static bool usedRepair;
- private static Sprite buttonSprite;
-
- public static Sprite getButtonSprite() {
- if (buttonSprite) return buttonSprite;
- buttonSprite = Helpers.loadSpriteFromResources("BonusRoles.Resources.RepairButton.png", 100f);
- return buttonSprite;
- }
-
- public static void clearAndReload() {
- engineer = null;
- usedRepair = false;
- }
- }
-
- public static class Godfather {
- public static PlayerControl godfather;
- public static Color color = Palette.ImpostorRed;
-
- public static void clearAndReload() {
- godfather = null;
- }
- }
-
- public static class Mafioso {
- public static PlayerControl mafioso;
- public static Color color = Palette.ImpostorRed;
-
- public static void clearAndReload() {
- mafioso = null;
- }
- }
-
-
- public static class Janitor {
- public static PlayerControl janitor;
- public static Color color = Palette.ImpostorRed;
-
- public static float cooldown = float.MaxValue;
-
- private static Sprite buttonSprite;
- public static Sprite getButtonSprite() {
- if (buttonSprite) return buttonSprite;
- buttonSprite = Helpers.loadSpriteFromResources("BonusRoles.Resources.CleanButton.png", 100f);
- return buttonSprite;
- }
-
- public static void clearAndReload() {
- janitor = null;
- cooldown = BonusRolesPlugin.janitorCooldown.GetValue();
- }
- }
-
- public static class Sheriff {
- public static PlayerControl sheriff;
- public static Color color = new Color(255f / 255f, 204f / 255f, 0f / 255f, 1);
-
- public static float cooldown = float.MaxValue;
- public static bool jesterCanDieToSheriff = false;
-
- public static PlayerControl currentTarget;
-
- public static void clearAndReload() {
- sheriff = null;
- currentTarget = null;
- cooldown = BonusRolesPlugin.sheriffCooldown.GetValue();
- jesterCanDieToSheriff = BonusRolesPlugin.jesterCanDieToSheriff.GetValue();
- }
- }
-
- public static class Lighter {
- public static PlayerControl lighter;
- public static Color color = new Color(250f / 255f, 204f / 255f, 37f / 255f, 1);
-
- public static float lighterVision = 2f;
-
- public static void clearAndReload() {
- lighter = null;
- lighterVision = BonusRolesPlugin.lighterVision.GetValue();
- }
- }
-
- public static class Detective {
- public static PlayerControl detective;
- public static Color color = new Color(2f / 255f, 61f / 255f, 156f / 255f, 1);
-
- public static float footprintIntervall = 1f;
- public static float footprintDuration = 1f;
- public static bool anonymousFootprints = false;
-
- public static float timer = 1f;
-
- public static void clearAndReload() {
- detective = null;
- anonymousFootprints = BonusRolesPlugin.detectiveAnonymousFootprints.GetValue();
- footprintIntervall = BonusRolesPlugin.detectiveFootprintIntervall.GetValue();
- footprintDuration = BonusRolesPlugin.detectiveFootprintDuration.GetValue();
- timer = footprintIntervall;
- }
- }
- }
-
- public static class TimeMaster {
- public static PlayerControl timeMaster;
- public static Color color = new Color(114f / 255f, 234f / 255f, 247f / 255f, 1);
-
- public static bool reviveDuringRewind = false;
- public static float rewindTime = 3f;
- public static float cooldown = float.MaxValue;
-
- public static bool isRewinding = false;
-
- private static Sprite buttonSprite;
- public static Sprite getButtonSprite() {
- if (buttonSprite) return buttonSprite;
- buttonSprite = Helpers.loadSpriteFromResources("BonusRoles.Resources.RewindButton.png", 100f);
- return buttonSprite;
- }
-
- public static void clearAndReload() {
- timeMaster = null;
- isRewinding = false;
- reviveDuringRewind = BonusRolesPlugin.timeMasterReviveDuringRewind.GetValue();
- rewindTime = BonusRolesPlugin.timeMasterRewindTime.GetValue();
- cooldown = BonusRolesPlugin.timeMasterCooldown.GetValue();
- }
- }
-
- public static class Medic {
- public static PlayerControl medic;
- public static PlayerControl shielded;
- public static Color color = new Color(0f / 255f, 80f / 255f, 105f / 255f, 1);
- public static bool usedShield;
-
- public static float reportNameDuration = 10f;
- public static float reportColorDuration = 20f;
- public static int showShielded = 0;
- public static bool showAttemptToShielded = false;
-
- public static Color shieldedColor = new Color(0f / 255f, 221f / 255f, 255f / 255f, 1);
- public static PlayerControl currentTarget;
-
- private static Sprite buttonSprite;
- public static Sprite getButtonSprite() {
- if (buttonSprite) return buttonSprite;
- buttonSprite = Helpers.loadSpriteFromResources("BonusRoles.Resources.ShieldButton.png", 100f);
- return buttonSprite;
- }
-
- public static void clearAndReload() {
- medic = null;
- shielded = null;
- currentTarget = null;
- usedShield = false;
- shieldedColor = new Color(0f / 255f, 221f / 255f, 255f / 255f, 1);
- reportNameDuration = BonusRolesPlugin.medicReportNameDuration.GetValue();
- reportColorDuration = BonusRolesPlugin.medicReportColorDuration.GetValue();
- showShielded = BonusRolesPlugin.medicShowShielded.GetValue();
- showAttemptToShielded = BonusRolesPlugin.medicShowAttemptToShielded.GetValue();
- }
- }
-
- public static class Shifter {
- public static PlayerControl shifter;
- public static Color color = new Color(90f / 255f, 90f / 255f, 90f / 255f, 1);
-
- public static float cooldown = float.MaxValue;
-
- public static PlayerControl currentTarget;
-
- private static Sprite buttonSprite;
- public static Sprite getButtonSprite() {
- if (buttonSprite) return buttonSprite;
- buttonSprite = Helpers.loadSpriteFromResources("BonusRoles.Resources.ShiftButton.png", 100f);
- return buttonSprite;
- }
-
- public static void clearAndReload() {
- shifter = null;
- currentTarget = null;
- cooldown = BonusRolesPlugin.shifterCooldown.GetValue();
- }
- }
-
- public static class Swapper {
- public static PlayerControl swapper;
- public static Color color = new Color(240f / 255f, 128f / 255f, 72f / 255f, 1);
- private static Sprite spriteCheck;
-
- public static byte playerId1 = Byte.MaxValue;
- public static byte playerId2 = Byte.MaxValue;
-
- public static Sprite getCheckSprite() {
- if (spriteCheck) return spriteCheck;
- spriteCheck = Helpers.loadSpriteFromResources("BonusRoles.Resources.SwapperCheck.png", 150f);
- return spriteCheck;
- }
-
- public static void clearAndReload() {
- swapper = null;
- playerId1 = Byte.MaxValue;
- playerId2 = Byte.MaxValue;
- }
- }
-
- public static class Lovers {
- public static PlayerControl lover1;
- public static PlayerControl lover2;
- public static Color color = new Color(252f / 255f, 3f / 255f, 190f / 255f, 1);
-
- public static bool bothDie = true;
- // Lovers save if next to be exiled is a lover, because RPC of ending game comes before RPC of exiled
- public static bool notAckedExiledIsLover = false;
-
- public static bool existingAndAlive() {
- return lover1 != null && lover2 != null && !lover1.Data.IsDead && !lover2.Data.IsDead && !notAckedExiledIsLover; // ADD NOT ACKED IS LOVER
- }
-
- public static bool existingWithImpLover() {
- return lover1 != null && lover2 != null && (lover1.Data.IsImpostor || lover2.Data.IsImpostor);
- }
-
- public static void clearAndReload() {
- lover1 = null;
- lover2 = null;
- notAckedExiledIsLover = false;
- bothDie = BonusRolesPlugin.loversBothDie.GetValue();
- }
- }
-
- public static class Seer {
- public static PlayerControl seer;
- public static Color color = new Color(60f / 255f, 181f / 255f, 100f / 255f, 1);
- public static Dictionary<PlayerControl, PlayerControl> revealedPlayers = new Dictionary<PlayerControl, PlayerControl>();
-
- public static float cooldown = float.MaxValue;
- public static int kindOfInfo = 0;
- public static int playersWithNotification = 0;
- public static float chanceOfSeeingRight = 100;
-
- public static PlayerControl currentTarget;
-
- private static Sprite buttonSprite;
- public static Sprite getButtonSprite() {
- if (buttonSprite) return buttonSprite;
- buttonSprite = Helpers.loadSpriteFromResources("BonusRoles.Resources.SeerButton.png", 100f);
- return buttonSprite;
- }
-
- public static void clearAndReload() {
- seer = null;
- revealedPlayers = new Dictionary<PlayerControl, PlayerControl>();
- cooldown = BonusRolesPlugin.seerCooldown.GetValue();
- kindOfInfo = BonusRolesPlugin.seerKindOfInfo.GetValue();
- playersWithNotification = BonusRolesPlugin.seerPlayersWithNotification.GetValue();
- chanceOfSeeingRight = BonusRolesPlugin.seerChanceOfSeeingRight.GetValue();
- }
- }
-
- public static class Morphling {
- public static PlayerControl morphling;
- public static Color color = Palette.ImpostorRed;
- private static Sprite sampleSprite;
- private static Sprite morphSprite;
-
- public static float cooldown = float.MaxValue;
-
- public static PlayerControl currentTarget;
- public static PlayerControl sampledTarget;
- public static PlayerControl morphTarget;
- public static float morphTimer = 0f;
-
-
- public static void clearAndReload() {
- morphling = null;
- currentTarget = null;
- sampledTarget = null;
- morphTarget = null;
- morphTimer = 0f;
- cooldown = BonusRolesPlugin.morphlingCooldown.GetValue();
- }
-
- public static Sprite getSampleSprite() {
- if (sampleSprite) return sampleSprite;
- sampleSprite = Helpers.loadSpriteFromResources("BonusRoles.Resources.SampleButton.png", 100f);
- return sampleSprite;
- }
-
- public static Sprite getMorphSprite() {
- if (morphSprite) return morphSprite;
- morphSprite = Helpers.loadSpriteFromResources("BonusRoles.Resources.MorphButton.png", 100f);
- return morphSprite;
- }
- }
-
- public static class Camouflager {
- public static PlayerControl camouflager;
- public static Color color = Palette.ImpostorRed;
-
- public static float cooldown = float.MaxValue;
- public static float camouflageTimer = 0f;
-
- private static Sprite buttonSprite;
- public static Sprite getButtonSprite() {
- if (buttonSprite) return buttonSprite;
- buttonSprite = Helpers.loadSpriteFromResources("BonusRoles.Resources.CamoButton.png", 100f);
- return buttonSprite;
- }
-
- public static void clearAndReload() {
- camouflager = null;
- camouflageTimer = 0f;
- cooldown = BonusRolesPlugin.camouflagerCooldown.GetValue();
- }
- }
-
- public static class Spy {
- public static PlayerControl spy;
- private static Sprite adminTableIcon;
- public static Color color = new Color(252f / 255f, 90f / 255f, 30f / 255f, 1);
-
- public static float cooldown = float.MaxValue;
- public static float duration = 10f;
-
- public static float spyTimer = 0f;
-
- public static Sprite getAdminTableIconSprite() {
- if (adminTableIcon) return adminTableIcon;
- adminTableIcon = Helpers.loadSpriteFromResources("BonusRoles.Resources.AdminTableIcon.png", 350f);
- return adminTableIcon;
- }
-
- private static Sprite buttonSprite;
- public static Sprite getButtonSprite() {
- if (buttonSprite) return buttonSprite;
- buttonSprite = Helpers.loadSpriteFromResources("BonusRoles.Resources.SpyButton.png", 100f);
- return buttonSprite;
- }
-
- public static void clearAndReload() {
- spy = null;
- spyTimer = 0f;
- cooldown = BonusRolesPlugin.spyCooldown.GetValue();
- duration = BonusRolesPlugin.spySpyingDuration.GetValue();
- }
- }
-
- public static class Child {
- public static PlayerControl child;
- public static Color color = Color.white;
-
- public static float growingUpDuration = float.MaxValue;
- public static DateTime timeOfGrowthStart = DateTime.UtcNow;
-
- public static void clearAndReload() {
- child = null;
- growingUpDuration = BonusRolesPlugin.childGrowingUpDuration.GetValue();
- timeOfGrowthStart = DateTime.UtcNow;
- }
-
- public static float growingProgress() {
- if (timeOfGrowthStart == null) return 0f;
-
- float timeSinceStart = (float)(DateTime.UtcNow - timeOfGrowthStart).TotalMilliseconds;
- return Mathf.Clamp(timeSinceStart/(growingUpDuration*1000), 0f, 1f);
- }
-
- public static bool isGrownUp() {
- return growingProgress() == 1f;
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-<Project Sdk="Microsoft.NET.Sdk">
- <PropertyGroup>
- <TargetFramework>netstandard2.1</TargetFramework>
- <Version>1.0.0</Version>
- <Mappings>NuclearPowered/Mappings:0.2.0</Mappings>
-
- <Description>TheOtherRoles</Description>
- <Authors>Eisbison</Authors>
- </PropertyGroup>
-
- <PropertyGroup Condition="'$(GamePlatform)' == 'Steam'">
- <GameVersion>2021.3.5s</GameVersion>
- <DefineConstants>$(DefineConstants);STEAM</DefineConstants>
- </PropertyGroup>
-
- <PropertyGroup Condition="'$(GamePlatform)' == 'Itch'">
- <GameVersion>2021.3.5i</GameVersion>
- <DefineConstants>$(DefineConstants);ITCH</DefineConstants>
- </PropertyGroup>
-
- <ItemGroup>
- <Deobfuscate Include="$(AmongUs)\BepInEx\plugins\Reactor-$(GameVersion).dll" />
-
- <PackageReference Include="Reactor.OxygenFilter.MSBuild" Version="0.2.9" />
- </ItemGroup>
-
- <ItemGroup>
- <Reference Include="Essentials">
- <HintPath>$(AmongUs)\BepInEx\plugins\Essentials-$(GameVersion).dll</HintPath>
- </Reference>
- </ItemGroup>
-
- <ItemGroup>
- <EmbeddedResource Include="Resources\RepairButton.png"/>
- <EmbeddedResource Include="Resources\CleanButton.png"/>
- <EmbeddedResource Include="Resources\RewindButton.png"/>
- <EmbeddedResource Include="Resources\ShieldButton.png"/>
- <EmbeddedResource Include="Resources\ShiftButton.png"/>
- <EmbeddedResource Include="Resources\SeerButton.png"/>
- <EmbeddedResource Include="Resources\MorphButton.png"/>
- <EmbeddedResource Include="Resources\SampleButton.png"/>
- <EmbeddedResource Include="Resources\CamoButton.png"/>
- <EmbeddedResource Include="Resources\SpyButton.png"/>
- <EmbeddedResource Include="Resources\Footprint.png"/>
- <EmbeddedResource Include="Resources\AdminTableIcon.png"/>
- <EmbeddedResource Include="Resources\SwapperCheck.png"/>
- </ItemGroup>
-
- <Target Name="Copy" AfterTargets="Reobfuscate">
- <Copy SourceFiles="$(OutputPath)reobfuscated/$(AssemblyName)-$(GameVersion).dll" DestinationFolder="$(AmongUs)/BepInEx/plugins/" Condition="'$(Configuration)' == 'Debug'" />
- </Target>
-</Project>
\ No newline at end of file
using System.IO;
using System.Net.Http;
using UnityEngine;
-using static BonusRoles.BonusRoles;
+using static TheOtherRoles.TheOtherRoles;
using Reactor.Extensions;
using System.Collections.Generic;
using System.Linq;
using UnhollowerBaseLib;
-namespace BonusRoles
+namespace TheOtherRoles
{
[HarmonyPatch(typeof(HudManager), nameof(HudManager.Start))]
static class HudManagerStartPatch
private static CustomButton morphlingButton;
private static CustomButton camouflagerButton;
private static CustomButton spyButton;
+ private static CustomButton trackerButton;
+ private static CustomButton vampireKillButton;
+ private static CustomButton garlicButton;
public static void setCustomButtonCooldowns() {
engineerRepairButton.MaxTimer = 0f;
morphlingButton.MaxTimer = Morphling.cooldown;
camouflagerButton.MaxTimer = Camouflager.cooldown;
spyButton.MaxTimer = Spy.cooldown;
+ vampireKillButton.MaxTimer = PlayerControl.GameOptions.KillCooldown;
+ trackerButton.MaxTimer = 0f;
+ garlicButton.MaxTimer = 0f;
spyButton.EffectDuration = Spy.duration;
+ vampireKillButton.EffectDuration= Vampire.delay;
}
public static void Postfix(HudManager __instance)
},
() => {},
Engineer.getButtonSprite(),
- Vector3.zero,
+ new Vector3(-1.3f, 0, 0),
__instance
);
() => { return __instance.ReportButton.renderer.color == Palette.EnabledColor && PlayerControl.LocalPlayer.CanMove; },
() => { janitorCleanButton.Timer = janitorCleanButton.MaxTimer;},
Janitor.getButtonSprite(),
- Vector3.zero,
+ new Vector3(-1.3f, 0, 0),
__instance
);
() => { return Sheriff.currentTarget && PlayerControl.LocalPlayer.CanMove; },
() => { sheriffKillButton.Timer = sheriffKillButton.MaxTimer;},
__instance.KillButton.renderer.sprite,
- Vector3.zero,
+ new Vector3(-1.3f, 0, 0),
__instance
);
() => { return PlayerControl.LocalPlayer.CanMove; },
() => { timeMasterRewindTimeButton.Timer = timeMasterRewindTimeButton.MaxTimer;},
TimeMaster.getButtonSprite(),
- Vector3.zero,
+ new Vector3(-1.3f, 0, 0),
__instance
);
() => { return !Medic.usedShield && Medic.currentTarget && PlayerControl.LocalPlayer.CanMove; },
() => {},
Medic.getButtonSprite(),
- Vector3.zero,
+ new Vector3(-1.3f, 0, 0),
__instance
);
() => { return Shifter.currentTarget && PlayerControl.LocalPlayer.CanMove; },
() => { shifterShiftButton.Timer = shifterShiftButton.MaxTimer; },
Shifter.getButtonSprite(),
- Vector3.zero,
+ new Vector3(-1.3f, 0, 0),
__instance
);
() => { return Seer.currentTarget && PlayerControl.LocalPlayer.CanMove; },
() => {},
Seer.getButtonSprite(),
- Vector3.zero,
+ new Vector3(-1.3f, 0, 0),
__instance
);
Morphling.sampledTarget = null;
},
Morphling.getSampleSprite(),
- new Vector3(0f, 1.3f, 0f),
+ new Vector3(-1.3f, 1.3f, 0f),
__instance,
true,
10f,
camouflagerButton.killButtonManager.TimerText.Color = Palette.EnabledColor;
},
Camouflager.getButtonSprite(),
- new Vector3(0f, 1.3f, 0f),
+ new Vector3(-1.3f, 1.3f, 0f),
__instance,
true,
10f,
spyButton.killButtonManager.TimerText.Color = Palette.EnabledColor;
},
Spy.getButtonSprite(),
- Vector3.zero,
+ new Vector3(-1.3f, 0, 0),
__instance,
true,
0f,
spyButton.Timer = spyButton.MaxTimer;
}
);
+
+ // Tracker button
+ trackerButton = new CustomButton(
+ () => {
+ MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.TrackerUsedTracker, Hazel.SendOption.None, -1);
+ writer.Write(Tracker.currentTarget.PlayerId);
+ AmongUsClient.Instance.FinishRpcImmediately(writer);
+ RPCProcedure.trackerUsedTracker(Tracker.currentTarget.PlayerId);
+ },
+ () => { return Tracker.tracker != null && Tracker.tracker == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; },
+ () => { return PlayerControl.LocalPlayer.CanMove && Tracker.currentTarget != null && !Tracker.usedTracker; },
+ () => { },
+ Tracker.getButtonSprite(),
+ new Vector3(-1.3f, 0, 0),
+ __instance
+ );
+
+ vampireKillButton = new CustomButton(
+ () => {
+ if (Helpers.handleMurderAttempt(Vampire.currentTarget)) {
+ if (Vampire.targetNearGarlic) {
+ PlayerControl.LocalPlayer.RpcMurderPlayer(Vampire.currentTarget);
+ vampireKillButton.HasEffect = false; // Block effect on this click
+ vampireKillButton.Timer = vampireKillButton.MaxTimer;
+ } else {
+ Vampire.bitten = Vampire.currentTarget;
+ Reactor.Coroutines.Start(Vampire.killWithDelay());
+ MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.VampireBiteNotification, Hazel.SendOption.None, -1);
+ writer.Write(Vampire.bitten.PlayerId);
+ AmongUsClient.Instance.FinishRpcImmediately(writer);
+ RPCProcedure.vampireBiteNotification(Vampire.bitten.PlayerId);
+ vampireKillButton.HasEffect = true; // Trigger effect on this click
+ }
+ } else {
+ vampireKillButton.HasEffect = false; // Block effect if no action was fired
+ }
+ },
+ () => { return Vampire.vampire != null && Vampire.vampire == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; },
+ () => {
+ if (Vampire.targetNearGarlic)
+ vampireKillButton.killButtonManager.renderer.sprite = __instance.KillButton.renderer.sprite;
+ else
+ vampireKillButton.killButtonManager.renderer.sprite = Vampire.getButtonSprite();
+ return Vampire.currentTarget != null && PlayerControl.LocalPlayer.CanMove;
+ },
+ () => {
+ vampireKillButton.Timer = vampireKillButton.MaxTimer;
+ vampireKillButton.isEffectActive = false;
+ vampireKillButton.killButtonManager.TimerText.Color = Palette.EnabledColor;
+ },
+ Vampire.getButtonSprite(),
+ new Vector3(-1.3f, 0, 0),
+ __instance,
+ false,
+ 0f,
+ () => {
+ vampireKillButton.Timer = vampireKillButton.MaxTimer;
+ }
+ );
+
+ garlicButton = new CustomButton(
+ () => {
+ Vampire.localPlacedGarlic = true;
+ var pos = PlayerControl.LocalPlayer.transform.position;
+ byte[] buff = new byte[sizeof(float) * 2];
+ Buffer.BlockCopy(BitConverter.GetBytes(pos.x), 0, buff, 0*sizeof(float), sizeof(float));
+ Buffer.BlockCopy(BitConverter.GetBytes(pos.y), 0, buff, 1*sizeof(float), sizeof(float));
+
+ MessageWriter writer = AmongUsClient.Instance.StartRpc(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.PlaceGarlic, Hazel.SendOption.None);
+ writer.WriteBytesAndSize(buff);
+ writer.EndMessage();
+ RPCProcedure.placeGarlic(buff);
+ },
+ () => { return !Vampire.localPlacedGarlic && !PlayerControl.LocalPlayer.Data.IsDead && Vampire.garlicsActive; },
+ () => { return PlayerControl.LocalPlayer.CanMove && !Vampire.localPlacedGarlic; },
+ () => { },
+ Vampire.getGarlicButtonSprite(),
+ Vector3.zero,
+ __instance,
+ true
+ );
}
}
}
\ No newline at end of file
using System.Text;
using System.Threading.Tasks;
-namespace BonusRoles
+namespace TheOtherRoles
{
[HarmonyPatch(typeof(VersionShower), nameof(VersionShower.Start))]
public static class VersionShowerPatch
static void Postfix(VersionShower __instance) {
string spacer = new String('\n', 15);
if (__instance.text.Text.Contains(spacer))
- __instance.text.Text += "\n[FFFFFFFF]- Loaded [FCCE03FF]TheOtherRoles[FFFFFFFF] v1.5\n by [FCCE03FF]Eisbison";
+ __instance.text.Text += "\n[FFFFFFFF]- Loaded [FCCE03FF]TheOtherRoles[FFFFFFFF] v1.7\n by [FCCE03FF]Eisbison";
else
- __instance.text.Text += spacer + "[FFFFFFFF]- Loaded [FCCE03FF]TheOtherRoles[FFFFFFFF] v1.5\n by [FCCE03FF]Eisbison";
+ __instance.text.Text += spacer + "[FFFFFFFF]- Loaded [FCCE03FF]TheOtherRoles[FFFFFFFF] v1.7\n by [FCCE03FF]Eisbison";
}
}
public float EffectDuration;
public Sprite Sprite;
private HudManager hudManager;
+ private bool mirror;
- public CustomButton(Action OnClick, Func<bool> HasButton, Func<bool> CouldUse, Action OnMeetingEnds, Sprite Sprite, Vector3 PositionOffset, HudManager hudManager, bool HasEffect, float EffectDuration, Action OnEffectEnds)
+ public CustomButton(Action OnClick, Func<bool> HasButton, Func<bool> CouldUse, Action OnMeetingEnds, Sprite Sprite, Vector3 PositionOffset, HudManager hudManager, bool HasEffect, float EffectDuration, Action OnEffectEnds, bool mirror = false)
{
this.hudManager = hudManager;
this.OnClick = OnClick;
this.EffectDuration = EffectDuration;
this.OnEffectEnds = OnEffectEnds;
this.Sprite = Sprite;
+ this.mirror = mirror;
Timer = 16.2f;
buttons.Add(this);
killButtonManager = UnityEngine.Object.Instantiate(hudManager.KillButton, hudManager.transform);
setActive(false);
}
- public CustomButton(Action OnClick, Func<bool> HasButton, Func<bool> CouldUse, Action OnMeetingEnds, Sprite Sprite, Vector3 PositionOffset, HudManager hudManager)
- : this(OnClick, HasButton, CouldUse, OnMeetingEnds, Sprite, PositionOffset, hudManager, false, 0f, () => {}) { }
+ public CustomButton(Action OnClick, Func<bool> HasButton, Func<bool> CouldUse, Action OnMeetingEnds, Sprite Sprite, Vector3 PositionOffset, HudManager hudManager, bool mirror = false)
+ : this(OnClick, HasButton, CouldUse, OnMeetingEnds, Sprite, PositionOffset, hudManager, false, 0f, () => {}, mirror) { }
public static void HudUpdate()
{
setActive(hudManager.UseButton.isActiveAndEnabled);
killButtonManager.renderer.sprite = Sprite;
-
- if (killButtonManager.transform.position == hudManager.KillButton.transform.position)
- {
- Vector3 vector = killButtonManager.transform.localPosition;
- vector += new Vector3(PositionOffset.x, PositionOffset.y);
- killButtonManager.transform.localPosition = vector;
+ if (hudManager.UseButton != null) {
+ Vector3 pos = hudManager.UseButton.transform.localPosition;
+ if (mirror) pos = new Vector3(-pos.x, pos.y, pos.z);
+ killButtonManager.transform.localPosition = pos + PositionOffset;
+ if (hudManager.KillButton != null) hudManager.KillButton.transform.localPosition = hudManager.UseButton.transform.localPosition - new Vector3(1.3f, 0, 0); // Align the kill button (because it's on another position depending on the screen resolution)
}
-
-
if (CouldUse()) {
killButtonManager.renderer.color = Palette.EnabledColor;
killButtonManager.renderer.material.SetFloat("_Desat", 0f);
using HarmonyLib;
-using static BonusRoles.BonusRoles;
-using static BonusRoles.GameHistory;
+using static TheOtherRoles.TheOtherRoles;
+using static TheOtherRoles.GameHistory;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Text;
-namespace BonusRoles {
+namespace TheOtherRoles {
enum WinCondition {
Default,
LoversTeamWin,
LoversSoloWin,
JesterWin,
- ChildDied
+ BountyHunterWin,
+ JesterAndBountyHunterWin
}
static class AdditionalTempData {
if (jesterWinner != null) TempData.winners.Remove(jesterWinner);
}
-
- // Child win condition (should be implemented using a proper GameOverReason in the future)
- if (Child.child != null && Child.child.Data.IsImpostor) {
- AdditionalTempData.winCondition = WinCondition.ChildDied;
+ // Jester and Bounty Hunter win condition (should be implemented using a proper GameOverReason in the future)
+ bool jesterWin = Jester.jester != null && Jester.jester.Data.IsImpostor;
+ bool bountyHunterWin = BountyHunter.bountyHunter != null && BountyHunter.bountyHunter.Data.IsImpostor;
+ if (jesterWin || bountyHunterWin) {
TempData.winners = new Il2CppSystem.Collections.Generic.List<WinningPlayerData>();
- WinningPlayerData wpd = new WinningPlayerData(Child.child.Data);
- wpd.IsImpostor = false;
- wpd.IsYou = false;
- TempData.winners.Add(wpd);
- }
-
- // Jester win condition (should be implemented using a proper GameOverReason in the future)
- else if (Jester.jester != null && Jester.jester.Data.IsImpostor) {
- AdditionalTempData.winCondition = WinCondition.JesterWin;
- TempData.winners = new Il2CppSystem.Collections.Generic.List<WinningPlayerData>();
- WinningPlayerData wpd = new WinningPlayerData(Jester.jester.Data);
- wpd.IsImpostor = false;
- TempData.winners.Add(wpd);
+ if (jesterWin) {
+ WinningPlayerData wpd = new WinningPlayerData(Jester.jester.Data);
+ wpd.IsImpostor = false;
+ TempData.winners.Add(wpd);
+ AdditionalTempData.winCondition = WinCondition.JesterWin;
+ }
+ if (bountyHunterWin) {
+ WinningPlayerData wpd = new WinningPlayerData(BountyHunter.bountyHunter.Data);
+ wpd.IsImpostor = false;
+ TempData.winners.Add(wpd);
+ if (AdditionalTempData.winCondition == WinCondition.JesterWin)
+ AdditionalTempData.winCondition = WinCondition.JesterAndBountyHunterWin;
+ else
+ AdditionalTempData.winCondition = WinCondition.BountyHunterWin;
+ }
}
// Lovers win conditions (should be implemented using a proper GameOverReason in the future)
TextRenderer textRenderer = bonusText.GetComponent<TextRenderer>();
textRenderer.Text = "";
- if (AdditionalTempData.winCondition == WinCondition.ChildDied) {
- textRenderer.Text = "Child Died";
- textRenderer.Color = Child.color;
- }
- else if (AdditionalTempData.winCondition == WinCondition.JesterWin) {
+ if (AdditionalTempData.winCondition == WinCondition.JesterWin) {
textRenderer.Text = "Jester Wins";
textRenderer.Color = Jester.color;
}
+ else if (AdditionalTempData.winCondition == WinCondition.BountyHunterWin) {
+ textRenderer.Text = "Bounty Hunter Wins";
+ textRenderer.Color = BountyHunter.color;
+ }
+ else if (AdditionalTempData.winCondition == WinCondition.JesterAndBountyHunterWin) {
+ textRenderer.Text = "[AD653BFF]Bounty Hunter[FFFFFFFF] and [FF54A7FF]Jester[FFFFFFFF] Win";
+ textRenderer.Color = Color.white;
+ }
else if (AdditionalTempData.winCondition == WinCondition.LoversTeamWin) {
if (AdditionalTempData.localIsLover) {
__instance.WinText.Text = "Double Victory";
using System.Collections.Generic;
using System.Collections;
using UnityEngine;
-using static BonusRoles.BonusRoles;
+using static TheOtherRoles.TheOtherRoles;
-namespace BonusRoles{
+namespace TheOtherRoles{
class Footprint {
private static List<Footprint> footprints = new List<Footprint>();
private static Sprite sprite;
public static Sprite getFootprintSprite() {
if (sprite) return sprite;
- sprite = Helpers.loadSpriteFromResources("BonusRoles.Resources.Footprint.png", 600f);
+ sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.Footprint.png", 600f);
return sprite;
}
IEnumerator CoFadeOutAndDestroy(float duration)
{
- for (float t = 0f; t < duration; t += Time.deltaTime)
- {
- // Check not null since if game ends, this access throws an error
+ for (float t = 0f; t < duration; t += Time.deltaTime) {
if (spriteRenderer) spriteRenderer.color = new Color(color.r, color.g, color.b, Mathf.Clamp(1f - t/duration, 0f, 1f));
yield return null;
using System.Collections;
using System;
using UnityEngine;
-using static BonusRoles.BonusRoles;
+using static TheOtherRoles.TheOtherRoles;
-namespace BonusRoles{
+namespace TheOtherRoles{
public class DeadPlayer
{
public PlayerControl player;
using System.IO;
using System.Net.Http;
using UnityEngine;
-using static BonusRoles.BonusRoles;
+using static TheOtherRoles.TheOtherRoles;
using Reactor.Extensions;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+using System.Text;
+using Essentials.Options;
-namespace BonusRoles
+namespace TheOtherRoles
{
[HarmonyPriority(Priority.Low)]
[HarmonyPatch(typeof(GameOptionsMenu), nameof(GameOptionsMenu.Update))]
__instance.GetComponentInParent<Scroller>().YBounds.max = -0.5F + __instance.Children.Length * 0.5F;
}
}
+
+ [HarmonyPatch(typeof(KeyboardJoystick), nameof(KeyboardJoystick.Update))]
+ public static class GameOptionsNextPagePatch
+ {
+ private static readonly System.Random random = new System.Random((int)DateTime.Now.Ticks);
+ private static List<PlayerControl> bots = new List<PlayerControl>();
+
+ public static void Postfix(KeyboardJoystick __instance)
+ {
+ if(Input.GetKeyDown(KeyCode.Tab)) {
+ TheOtherRolesPlugin.optionsPage = (TheOtherRolesPlugin.optionsPage + 1) % 3;
+ }
+ }
+ }
+
+ [HarmonyPatch(typeof(GameOptionsData), "NHJLMAAHKJF")]
+ class GameOptionsDataPatch
+ {
+
+ private static void Postfix(ref string __result)
+ {
+ StringBuilder stringBuilder = new StringBuilder(__result);
+ foreach (CustomOption customOption in TheOtherRolesPlugin.options) {
+ stringBuilder.AppendLine(string.Format("{0}[]: {1}", customOption.Name, customOption));
+ }
+ var hudString = stringBuilder.ToString();
+
+ int defaultSettingsLines = 19;
+ int roleSettingsLines = 19 + 22;
+ int end1 = hudString.TakeWhile(c => (defaultSettingsLines -= (c == '\n' ? 1 : 0)) > 0).Count();
+ int end2 = hudString.TakeWhile(c => (roleSettingsLines -= (c == '\n' ? 1 : 0)) > 0).Count();
+ int counter = TheOtherRolesPlugin.optionsPage;
+ if (counter == 0) {
+ hudString = hudString.Substring(0, end1) + "\n";
+ } else if (counter == 1) {
+ hudString = hudString.Substring(end1 + 1, end2 - end1);
+ // Temporary fix, should add a new CustomOption for spaces
+ int gap = 2;
+ int index = hudString.TakeWhile(c => (gap -= (c == '\n' ? 1 : 0)) > 0).Count();
+ hudString = hudString.Insert(index, "\n");
+ gap = 7;
+ index = hudString.TakeWhile(c => (gap -= (c == '\n' ? 1 : 0)) > 0).Count();
+ hudString = hudString.Insert(index + 1, "\n");
+ gap = 11;
+ index = hudString.TakeWhile(c => (gap -= (c == '\n' ? 1 : 0)) > 0).Count();
+ hudString = hudString.Insert(index + 1, "\n");
+ } else if (counter == 2) {
+ hudString = hudString.Substring(end2 + 1);
+ }
+ hudString += "\n Press tab for more...";
+ __result = hudString;
+ }
+ }
}
\ No newline at end of file
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Collections;
+using UnityEngine;
+using static TheOtherRoles.TheOtherRoles;
+
+namespace TheOtherRoles{
+ class Garlic {
+ public static List<Garlic> garlics = new List<Garlic>();
+
+ public GameObject garlic;
+ private GameObject background;
+
+ private static Sprite garlicSprite;
+ public static Sprite getGarlicSprite() {
+ if (garlicSprite) return garlicSprite;
+ garlicSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.Garlic.png", 300f);
+ return garlicSprite;
+ }
+
+ private static Sprite backgroundSprite;
+ public static Sprite getBackgroundSprite() {
+ if (backgroundSprite) return backgroundSprite;
+ backgroundSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.GarlicBackground.png", 60f);
+ return backgroundSprite;
+ }
+
+ public Garlic(Vector2 p) {
+ garlic = new GameObject("Garlic");
+ background = new GameObject("Background");
+ background.transform.SetParent(garlic.transform);
+ Vector3 position = new Vector3(p.x, p.y, PlayerControl.LocalPlayer.transform.position.z + 1f);
+ garlic.transform.position = position;
+ garlic.transform.localPosition = position;
+ background.transform.localPosition = new Vector3(0 , 0, 0.01f);
+
+ var garlicRenderer = garlic.AddComponent<SpriteRenderer>();
+ garlicRenderer.sprite = getGarlicSprite();
+ var backgroundRenderer = background.AddComponent<SpriteRenderer>();
+ backgroundRenderer.sprite = getBackgroundSprite();
+
+
+ garlic.SetActive(true);
+ garlics.Add(this);
+ }
+
+ public static void clearGarlics() {
+ garlics = new List<Garlic>();
+ }
+
+ public static void UpdateAll() {
+ foreach (Garlic garlic in garlics) {
+ if (garlic != null)
+ garlic.Update();
+ }
+ }
+
+ public void Update() {
+ if (background != null)
+ background.transform.Rotate(Vector3.forward * 6 * Time.deltaTime);
+ }
+ }
+}
\ No newline at end of file
using Reactor.Unstrip;
using UnhollowerBaseLib;
using UnityEngine;
-using static BonusRoles.BonusRoles;
+using static TheOtherRoles.TheOtherRoles;
+using HarmonyLib;
+using Hazel;
-namespace BonusRoles {
+namespace TheOtherRoles {
public static class Helpers {
public static Sprite LoadSpriteFromEmbeddedResources(string resource, float PixelPerUnit) {
if (renderer != null) renderer.enabled = false;
}
+
+ public static bool handleMurderAttempt(PlayerControl target, bool notifyOthers = true) {
+ // Block impostor shielded kill
+ if (Medic.shielded != null && Medic.shielded == target) {
+ if (notifyOthers) {
+ MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ShieldedMurderAttempt, Hazel.SendOption.None, -1);
+ AmongUsClient.Instance.FinishRpcImmediately(writer);
+ }
+ RPCProcedure.shieldedMurderAttempt();
+
+ return false;
+ }
+ // Block impostor not fully grown child kill
+ else if (Child.child != null && target == Child.child && !Child.isGrownUp()) {
+ return false;
+ }
+ return true;
+ }
+
public static IEnumerator Slide2D(Transform target, Vector2 source, Vector2 dest, float duration = 0.75f)
{
Vector3 temp = default(Vector3);
c = Camouflager.color;
g = false;
}
+ else if (Vampire.vampire != null && p == Vampire.vampire) {
+ r = "Vampire";
+ c = Vampire.color;
+ g = false;
+ }
else if (Detective.detective != null && p == Detective.detective) {
r = "Detective";
c = Detective.color;
r = "Child";
c = Child.color;
}
+ else if (BountyHunter.bountyHunter != null && p == BountyHunter.bountyHunter) {
+ r = "Bounty Hunter";
+ c = BountyHunter.color;
+ g = false;
+ }
+ else if (Tracker.tracker != null && p == Tracker.tracker) {
+ r = "Tracker";
+ c = Tracker.color;
+ }
+ else if (Snitch.snitch != null && p == Snitch.snitch) {
+ r = "Snitch";
+ c = Snitch.color;
+ }
else if (p.Data.IsImpostor) { // Just Impostor
r = "Impostor";
c = Palette.ImpostorRed;
using HarmonyLib;
using System;
-using static BonusRoles.BonusRoles;
+using static TheOtherRoles.TheOtherRoles;
using UnityEngine;
-namespace BonusRoles
+namespace TheOtherRoles
{
[HarmonyPatch(typeof(IntroCutscene.CoBegin__d), nameof(IntroCutscene.CoBegin__d.MoveNext))]
class IntroPatch
__instance.__this.ImpostorText.Text = "Camouflage and kill the crewmates";
__instance.__this.BackgroundBar.material.color = Camouflager.color;
}
+ else if (PlayerControl.LocalPlayer == Vampire.vampire)
+ {
+ __instance.__this.ImpostorText.gameObject.SetActive(true);
+ __instance.__this.Title.Text = "Vampire";
+ __instance.__this.Title.Color = Vampire.color;
+ __instance.__this.ImpostorText.Text = "Kill the crewmates with your bites";
+ __instance.__this.BackgroundBar.material.color = Vampire.color;
+ }
else if (PlayerControl.LocalPlayer == Sheriff.sheriff)
{
__instance.__this.Title.Text = "Sheriff";
__instance.__this.ImpostorText.Text = "No one will harm you until you grow up";
__instance.__this.BackgroundBar.material.color = Child.color;
}
+ else if (PlayerControl.LocalPlayer == BountyHunter.bountyHunter)
+ {
+ __instance.__this.Title.Text = "Bounty Hunter";
+ __instance.__this.Title.Color = BountyHunter.color;
+ __instance.__this.ImpostorText.Text = "Hunt [ED653BFF]" + BountyHunter.target?.Data?.PlayerName + "[FFFFFFFF] down";
+ __instance.__this.BackgroundBar.material.color = BountyHunter.color;
+ }
+ else if (PlayerControl.LocalPlayer == Tracker.tracker)
+ {
+ __instance.__this.Title.Text = "Tracker";
+ __instance.__this.Title.Color = Tracker.color;
+ __instance.__this.ImpostorText.Text = "Track the [FF1919FF]Impostors[FFFFFFFF] down";
+ __instance.__this.BackgroundBar.material.color = Tracker.color;
+ }
+ else if (PlayerControl.LocalPlayer == Snitch.snitch)
+ {
+ __instance.__this.Title.Text = "Snitch";
+ __instance.__this.Title.Color = Snitch.color;
+ __instance.__this.ImpostorText.Text = "Finish your tasks to find the [FF1919FF]Impostors[FFFFFFFF]";
+ __instance.__this.BackgroundBar.material.color = Snitch.color;
+ }
}
}
}
using Reactor;
using System.Collections.Generic;
using Essentials.Options;
-using UnityEngine;
using System.Linq;
using System.Net;
using System.IO;
using System;
using System.Reflection;
using UnhollowerBaseLib;
+using UnityEngine;
+using static TheOtherRoles.TheOtherRoles;
-namespace BonusRoles
+namespace TheOtherRoles
{
[BepInPlugin(Id)]
[BepInProcess("Among Us.exe")]
[BepInDependency(ReactorPlugin.Id)]
- public class BonusRolesPlugin : BasePlugin
+ public class TheOtherRolesPlugin : BasePlugin
{
- public const string Id = "me.eisbison.bonusroles";
+ public const string Id = "me.eisbison.theotherroles";
public Harmony Harmony { get; } = new Harmony(Id);
- // Role spawn chances
- public static CustomNumberOption mafiaSpawnChance = CustomOption.AddNumber("Mafia Spawn Chance", 100, 0, 100, 10);
- public static CustomNumberOption loversSpawnChance = CustomOption.AddNumber("Lovers Spawn Chance", 100, 0, 100, 10);
- public static CustomNumberOption morphlingSpawnChance = CustomOption.AddNumber("Morphling Spawn Chance", 100, 0, 100, 10);
- public static CustomNumberOption camouflagerSpawnChance = CustomOption.AddNumber("Camouflager Spawn Chance", 100, 0, 100, 10);
- public static CustomNumberOption jesterSpawnChance = CustomOption.AddNumber("Jester Spawn Chance", 100, 0, 100, 10);
- public static CustomNumberOption mayorSpawnChance = CustomOption.AddNumber("Mayor Spawn Chance", 100, 0, 100, 10);
- public static CustomNumberOption engineerSpawnChance = CustomOption.AddNumber("Engineer Spawn Chance", 100, 0, 100, 10);
- public static CustomNumberOption sheriffSpawnChance = CustomOption.AddNumber("Sheriff Spawn Chance", 100, 0, 100, 10);
- public static CustomNumberOption lighterSpawnChance = CustomOption.AddNumber("Lighter Spawn Chance", 100, 0, 100, 10);
- public static CustomNumberOption detectiveSpawnChance = CustomOption.AddNumber("Detective Spawn Chance", 100, 0, 100, 10);
- public static CustomNumberOption timeMasterSpawnChance = CustomOption.AddNumber("Time Master Spawn Chance", 100, 0, 100, 10);
- public static CustomNumberOption medicSpawnChance = CustomOption.AddNumber("Medic Spawn Chance", 100, 0, 100, 10);
- public static CustomNumberOption shifterSpawnChance = CustomOption.AddNumber("Shifter Spawn Chance", 100, 0, 100, 10);
- public static CustomNumberOption swapperSpawnChance = CustomOption.AddNumber("Swapper Spawn Chance", 100, 0, 100, 10);
- public static CustomNumberOption seerSpawnChance = CustomOption.AddNumber("Seer Spawn Chance", 100, 0, 100, 10);
- public static CustomNumberOption spySpawnChance = CustomOption.AddNumber("Spy Spawn Chance", 100, 0, 100, 10);
- public static CustomNumberOption childSpawnChance = CustomOption.AddNumber("Child Spawn Chance", 100, 0, 100, 10);
+ // Roles
+ public static int num = 0;
+ public static string[] rates = new string[]{"0%", "10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"};
+
+ public static CustomNumberOption crewmateRolesCount = CustomOption.AddNumber(num++.ToString(), "[CCCC00FF]Number Of Crewmate/Neutral Roles", 10, 0, 10, 0.5f);
+ public static CustomNumberOption impostorRolesCount = CustomOption.AddNumber(num++.ToString(), "[CCCC00FF]Number Of Impostor Roles", 3, 0, 3, 0.5f);
+
+ public static CustomStringOption mafiaSpawnRate = CustomOption.AddString(num++.ToString(), cs(Janitor.color) + "Mafia", rates);
+ public static CustomStringOption morphlingSpawnRate = CustomOption.AddString(num++.ToString(), cs(Morphling.color) + "Morphling", rates);
+ public static CustomStringOption camouflagerSpawnRate = CustomOption.AddString(num++.ToString(), cs(Camouflager.color) + "Camouflager", rates);
+ public static CustomStringOption vampireSpawnRate = CustomOption.AddString(num++.ToString(), cs(Vampire.color) + "Vampire", rates);
+
+ public static CustomStringOption loversSpawnRate = CustomOption.AddString(num++.ToString(), cs(Lovers.color) + "Lovers", rates);
+ public static CustomStringOption jesterSpawnRate = CustomOption.AddString(num++.ToString(), cs(Jester.color) + "Jester", rates);
+ public static CustomStringOption shifterSpawnRate = CustomOption.AddString(num++.ToString(), cs(Shifter.color) + "Shifter", rates);
+
+ public static CustomStringOption mayorSpawnRate = CustomOption.AddString(num++.ToString(), cs(Mayor.color) + "Mayor", rates);
+ public static CustomStringOption engineerSpawnRate = CustomOption.AddString(num++.ToString(), cs(Engineer.color) + "Engineer", rates);
+ public static CustomStringOption sheriffSpawnRate = CustomOption.AddString(num++.ToString(), cs(Sheriff.color) + "Sheriff", rates);
+ public static CustomStringOption lighterSpawnRate = CustomOption.AddString(num++.ToString(), cs(Lighter.color) + "Lighter", rates);
+ public static CustomStringOption detectiveSpawnRate = CustomOption.AddString(num++.ToString(), cs(Detective.color) + "Detective", rates);
+ public static CustomStringOption timeMasterSpawnRate = CustomOption.AddString(num++.ToString(), cs(TimeMaster.color) + "Time Master", rates);
+ public static CustomStringOption medicSpawnRate = CustomOption.AddString(num++.ToString(), cs(Medic.color) + "Medic", rates);
+ public static CustomStringOption swapperSpawnRate = CustomOption.AddString(num++.ToString(), cs(Swapper.color) + "Swapper", rates);
+ public static CustomStringOption seerSpawnRate = CustomOption.AddString(num++.ToString(), cs(Seer.color) + "Seer", rates);
+ public static CustomStringOption spySpawnRate = CustomOption.AddString(num++.ToString(), cs(Spy.color) + "Spy", rates);
+ public static CustomStringOption childSpawnRate = CustomOption.AddString(num++.ToString(), cs(Child.color) + "Child", rates);
+ // public static CustomStringOption bountyHunterSpawnRate = CustomOption.AddString(num++.ToString(), cs(BountyHunter.color) + "Bounty Hunter", rates);
+ public static CustomStringOption trackerSpawnRate = CustomOption.AddString(num++.ToString(), cs(Tracker.color) + "Tracker", rates);
+ public static CustomStringOption snitchSpawnRate = CustomOption.AddString(num++.ToString(), cs(Snitch.color) + "Snitch", rates);
// Role settings
- public static CustomNumberOption janitorCooldown = CustomOption.AddNumber("Janitor Cooldown", 30f, 10f, 60f, 2.5f);
- public static CustomNumberOption morphlingCooldown = CustomOption.AddNumber("Morphling Cooldown", 30f, 10f, 60f, 2.5f);
- public static CustomNumberOption camouflagerCooldown = CustomOption.AddNumber("Camouflager Cooldown", 30f, 10f, 60f, 2.5f);
- public static CustomToggleOption loversBothDie = CustomOption.AddToggle("Both Lovers Die", true);
- public static CustomNumberOption sheriffCooldown = CustomOption.AddNumber("Sheriff Cooldown", 30f, 10f, 60f, 2.5f);
- public static CustomToggleOption jesterCanDieToSheriff = CustomOption.AddToggle("Jester Can Die To Sheriff", false);
- public static CustomNumberOption lighterVision = CustomOption.AddNumber("Lighter Vision", 2f, 0.25f, 5f, 0.25f);
- public static CustomToggleOption detectiveAnonymousFootprints = CustomOption.AddToggle("Anonymous Footprints", false);
- public static CustomNumberOption detectiveFootprintIntervall = CustomOption.AddNumber("Footprint Intervall", 0.5f, 0.25f, 10f, 0.25f);
- public static CustomNumberOption detectiveFootprintDuration = CustomOption.AddNumber("Footprint Duration", 5f, 0.25f, 10f, 0.25f);
- public static CustomNumberOption timeMasterCooldown = CustomOption.AddNumber("Time Master Cooldown", 30f, 10f, 60f, 2.5f);
- public static CustomNumberOption timeMasterRewindTime = CustomOption.AddNumber("Rewind Time", 3f, 1f, 10f, 1f);
- public static CustomToggleOption timeMasterReviveDuringRewind = CustomOption.AddToggle("Revive During Rewind", false);
- public static CustomNumberOption medicReportNameDuration = CustomOption.AddNumber("Time Where Medic Reports Will Have Name", 10, 0, 60, 2.5f);
- public static CustomNumberOption medicReportColorDuration = CustomOption.AddNumber("Time Where Medic Reports Will Have Color Type", 20, 0, 120, 2.5f);
- public static CustomStringOption medicShowShielded = CustomOption.AddString("Show Shielded Player", new string[] {"Everyone", "Shielded + Medic", "Medic"});
- public static CustomToggleOption medicShowAttemptToShielded = CustomOption.AddToggle("Shielded Player Sees Murder Attempt", false);
- public static CustomNumberOption shifterCooldown = CustomOption.AddNumber("Shifter Cooldown", 30f, 10f, 60f, 2.5f);
- public static CustomNumberOption seerCooldown = CustomOption.AddNumber("Seer Cooldown (No Reset After Meeting)", 15f, 30f, 180f, 15f);
- public static CustomNumberOption seerChanceOfSeeingRight = CustomOption.AddNumber("Seer Chance Of Seeing Right", 100, 0, 100, 5);
- public static CustomStringOption seerKindOfInfo = CustomOption.AddString("Info That Seer Reveals", new string[] {"Role", "Good/Bad"});
- public static CustomStringOption seerPlayersWithNotification = CustomOption.AddString("Players That See When They Are Being Revealed", new string[] {"Everyone", "The Good", "The Bad", "Nobody"});
- public static CustomNumberOption spyCooldown = CustomOption.AddNumber("Spy Cooldown", 30f, 10f, 120f, 5f);
- public static CustomNumberOption spySpyingDuration = CustomOption.AddNumber("Spy Duration", 10f, 2.5f, 60f, 2.5f);
- public static CustomNumberOption childGrowingUpDuration = CustomOption.AddNumber("Child Growing Up Duration", 400f, 100f, 1500f, 100f);
+ public static CustomNumberOption janitorCooldown = CustomOption.AddNumber(num++.ToString(), "Janitor Cooldown", 30f, 10f, 60f, 2.5f);
+ public static CustomNumberOption morphlingCooldown = CustomOption.AddNumber(num++.ToString(), "Morphling Cooldown", 30f, 10f, 60f, 2.5f);
+ public static CustomNumberOption camouflagerCooldown = CustomOption.AddNumber(num++.ToString(), "Camouflager Cooldown", 30f, 10f, 60f, 2.5f);
+ public static CustomNumberOption vampireKillDelay = CustomOption.AddNumber(num++.ToString(), "Vampire Kill Delay", 10f, 2.5f, 30f, 2.5f);
+
+ public static CustomToggleOption loversBothDie = CustomOption.AddToggle(num++.ToString(), "Both Lovers Die", true);
+ public static CustomNumberOption shifterCooldown = CustomOption.AddNumber(num++.ToString(), "Shifter Cooldown", 30f, 10f, 60f, 2.5f);
+
+ public static CustomNumberOption sheriffCooldown = CustomOption.AddNumber(num++.ToString(), "Sheriff Cooldown", 30f, 10f, 60f, 2.5f);
+ public static CustomToggleOption jesterCanDieToSheriff = CustomOption.AddToggle(num++.ToString(), "Jester Can Die To Sheriff", false);
+ public static CustomNumberOption lighterVision = CustomOption.AddNumber(num++.ToString(), "Lighter Vision", 2f, 0.25f, 5f, 0.25f);
+ public static CustomToggleOption detectiveAnonymousFootprints = CustomOption.AddToggle(num++.ToString(), "Anonymous Footprints", false);
+ public static CustomNumberOption detectiveFootprintIntervall = CustomOption.AddNumber(num++.ToString(), "Footprint Intervall", 0.5f, 0.25f, 10f, 0.25f);
+ public static CustomNumberOption detectiveFootprintDuration = CustomOption.AddNumber(num++.ToString(), "Footprint Duration", 5f, 0.25f, 10f, 0.25f);
+ public static CustomNumberOption timeMasterCooldown = CustomOption.AddNumber(num++.ToString(), "Time Master Cooldown", 30f, 10f, 60f, 2.5f);
+ public static CustomNumberOption timeMasterRewindTime = CustomOption.AddNumber(num++.ToString(), "Rewind Time", 3f, 1f, 10f, 1f);
+ public static CustomToggleOption timeMasterReviveDuringRewind = CustomOption.AddToggle(num++.ToString(), "Revive During Rewind", false);
+ public static CustomNumberOption medicReportNameDuration = CustomOption.AddNumber(num++.ToString(), "Time Where Medic Reports Will Have Name", 10, 0, 60, 2.5f);
+ public static CustomNumberOption medicReportColorDuration = CustomOption.AddNumber(num++.ToString(), "Time Where Medic Reports Will Have Color Type", 20, 0, 120, 2.5f);
+ public static CustomStringOption medicShowShielded = CustomOption.AddString(num++.ToString(), "Show Shielded Player", new string[] {"Everyone", "Shielded + Medic", "Medic"});
+ public static CustomToggleOption medicShowAttemptToShielded = CustomOption.AddToggle(num++.ToString(), "Shielded Player Sees Murder Attempt", false);
+ public static CustomNumberOption seerCooldown = CustomOption.AddNumber(num++.ToString(), "Seer Cooldown (No Reset After Meeting)", 15f, 30f, 180f, 15f);
+ public static CustomNumberOption seerChanceOfSeeingRight = CustomOption.AddNumber(num++.ToString(), "Seer Chance Of Seeing Right", 100, 0, 100, 5);
+ public static CustomStringOption seerKindOfInfo = CustomOption.AddString(num++.ToString(), "Info That Seer Reveals", new string[] {"Role", "Good/Bad"});
+ public static CustomStringOption seerPlayersWithNotification = CustomOption.AddString(num++.ToString(), "Players That See When They Are Being Revealed", new string[] {"Everyone", "The Good", "The Bad", "Nobody"});
+ public static CustomNumberOption spyCooldown = CustomOption.AddNumber(num++.ToString(), "Spy Cooldown", 30f, 10f, 120f, 5f);
+ public static CustomNumberOption spySpyingDuration = CustomOption.AddNumber(num++.ToString(), "Spy Duration", 10f, 2.5f, 60f, 2.5f);
+ public static CustomNumberOption childGrowingUpDuration = CustomOption.AddNumber(num++.ToString(), "Child Growing Up Duration", 400f, 100f, 1500f, 100f);
+ // public static CustomToggleOption bountyHunterNotifyBounty = CustomOption.AddToggle(num++.ToString(), "Bounty Gets Notified", true);
+ public static CustomNumberOption trackerUpdateIntervall = CustomOption.AddNumber(num++.ToString(), "Tracker Update Intervall", 5f, 2.5f, 30f, 2.5f);
+ public static CustomNumberOption snitchLeftTasksForImpostors = CustomOption.AddNumber(num++.ToString(), "Task Count Where Impostors See Snitch", 1f, 0f, 5f, 1f);
+
+ public static List<CustomOption> options = new List<CustomOption>();
+ public static int optionsPage = 1;
public static ConfigEntry<bool> DebugMode { get; private set; }
-
-
- public override void Load()
- {
+ public override void Load() {
DebugMode = Config.Bind("Custom", "Enable Debug Mode", false);
CustomOption.ShamelessPlug = false;
Harmony.PatchAll();
}
+
+ public static string cs(Color c) {
+ return string.Format("[{0:X2}{1:X2}{2:X2}{3:X2}]", ToByte(c.r), ToByte(c.g), ToByte(c.b), ToByte(c.a));
+ }
+
+ private static byte ToByte(float f) {
+ f = Mathf.Clamp01(f);
+ return (byte)(f * 255);
+ }
+
+ public TheOtherRolesPlugin() {
+ options = new List<CustomOption>() {
+ crewmateRolesCount,
+ impostorRolesCount,
+
+ mafiaSpawnRate,
+ morphlingSpawnRate,
+ camouflagerSpawnRate,
+ vampireSpawnRate,
+
+ loversSpawnRate,
+ jesterSpawnRate,
+ shifterSpawnRate,
+
+ mayorSpawnRate,
+ engineerSpawnRate,
+ sheriffSpawnRate,
+ lighterSpawnRate,
+ detectiveSpawnRate,
+ timeMasterSpawnRate,
+ medicSpawnRate,
+ swapperSpawnRate,
+ seerSpawnRate,
+ spySpawnRate,
+ childSpawnRate,
+ // bountyHunterSpawnRate,
+ trackerSpawnRate,
+ snitchSpawnRate,
+
+ janitorCooldown,
+ morphlingCooldown,
+ camouflagerCooldown,
+ vampireKillDelay,
+
+ loversBothDie,
+ shifterCooldown,
+
+ sheriffCooldown,
+ jesterCanDieToSheriff,
+ lighterVision,
+ detectiveAnonymousFootprints,
+ detectiveFootprintIntervall,
+ detectiveFootprintDuration,
+ timeMasterCooldown,
+ timeMasterRewindTime,
+ timeMasterReviveDuringRewind,
+ medicReportNameDuration,
+ medicReportColorDuration,
+ medicShowShielded,
+ medicShowAttemptToShielded,
+ seerCooldown,
+ seerChanceOfSeeingRight,
+ seerKindOfInfo,
+ seerPlayersWithNotification,
+ spyCooldown,
+ spySpyingDuration,
+ childGrowingUpDuration,
+ // bountyHunterNotifyBounty,
+ trackerUpdateIntervall,
+ snitchLeftTasksForImpostors
+ };
+ }
}
// Deactivate bans, since I always leave my local testing game and ban myself
public static void Postfix(KeyboardJoystick __instance)
{
- if (!BonusRolesPlugin.DebugMode.Value) return;
+ if (!TheOtherRolesPlugin.DebugMode.Value) return;
// Spawn dummys
if (Input.GetKeyDown(KeyCode.F)) {
using System.Collections.Generic;
using System.Linq;
using UnhollowerBaseLib;
-using static BonusRoles.BonusRoles;
+using static TheOtherRoles.TheOtherRoles;
using System.Collections;
using System;
using System.Text;
using UnityEngine;
-namespace BonusRoles
+namespace TheOtherRoles
{
[HarmonyPatch(typeof(MeetingHud), "CalculateVotes")]
class MeetingCalculateVotesPatch {
}
}
+ [HarmonyPatch(typeof(ExileController), "Begin")]
+ class ExileBeginPatch {
+ public static void Prefix(ref GameData.PlayerInfo IHDMFDEEDEL, bool DCHFIBODGIL) {
+ // Prevent growing Child exile
+ if (Child.child != null && IHDMFDEEDEL != null && IHDMFDEEDEL.PlayerId == Child.child.PlayerId && !Child.isGrownUp()) {
+ IHDMFDEEDEL = null;
+ }
+ }
+ }
+
+
[HarmonyPatch(typeof(UnityEngine.Object), nameof(UnityEngine.Object.Destroy), new Type[] { typeof(UnityEngine.Object) })]
class MeetingExiledEndPatch
{
// Reset custom button timers where necessary
CustomButton.MeetingEndedUpdate();
- // Jester win condition
- if (Jester.jester != null && ExileController.Instance.exiled != null && ExileController.Instance.exiled.PlayerId == Jester.jester.PlayerId)
- {
- MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.JesterWin, Hazel.SendOption.None, -1);
- AmongUsClient.Instance.FinishRpcImmediately(writer);
-
- RPCProcedure.jesterWin();
- }
-
- // Child win condition
- if (Child.child != null && ExileController.Instance.exiled != null && ExileController.Instance.exiled.PlayerId == Child.child.PlayerId && !Child.isGrownUp()) {
- MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ChildDied, Hazel.SendOption.None, -1);
- AmongUsClient.Instance.FinishRpcImmediately(writer);
- RPCProcedure.childDied();
+ // Jester and Bounty Hunter win condition
+ if (ExileController.Instance.exiled != null) {
+ byte exiledId = ExileController.Instance.exiled.PlayerId;
+ if ((Jester.jester != null && Jester.jester.PlayerId == exiledId) || (BountyHunter.bountyHunter != null && !BountyHunter.bountyHunter.Data.IsDead && BountyHunter.target != null && BountyHunter.target.PlayerId == exiledId)) {
+ MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.JesterBountyHunterWin, Hazel.SendOption.None, -1);
+ writer.Write(exiledId);
+ AmongUsClient.Instance.FinishRpcImmediately(writer);
+ RPCProcedure.jesterBountyHunterWin(exiledId);
+ }
}
}
}
__result = ExileController.Instance.exiled.PlayerName + " was The Spy.";
else if(Child.child != null && ExileController.Instance.exiled.Object.PlayerId == Child.child.PlayerId)
__result = ExileController.Instance.exiled.PlayerName + " was The Child.";
+ else if(BountyHunter.bountyHunter != null && ExileController.Instance.exiled.Object.PlayerId == BountyHunter.bountyHunter.PlayerId)
+ __result = ExileController.Instance.exiled.PlayerName + " was The Bounty Hunter.";
+ else if(Tracker.tracker != null && ExileController.Instance.exiled.Object.PlayerId == Tracker.tracker.PlayerId)
+ __result = ExileController.Instance.exiled.PlayerName + " was The Tracker.";
+ else if(Snitch.snitch != null && ExileController.Instance.exiled.Object.PlayerId == Snitch.snitch.PlayerId)
+ __result = ExileController.Instance.exiled.PlayerName + " was The Snitch.";
else
__result = ExileController.Instance.exiled.PlayerName + " was not The Impostor.";
}
__result = ExileController.Instance.exiled.PlayerName + " was The ImpLover.";
else if(Lovers.lover2 != null && ExileController.Instance.exiled.Object.PlayerId == Lovers.lover2.PlayerId)
__result = ExileController.Instance.exiled.PlayerName + " was The ImpLover.";
+ else if(Vampire.vampire != null && ExileController.Instance.exiled.Object.PlayerId == Vampire.vampire.PlayerId)
+ __result = ExileController.Instance.exiled.PlayerName + " was The Vamipre.";
}
// Hide number of remaining impostors on Jester win
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-using static BonusRoles.BonusRoles;
-using static BonusRoles.GameHistory;
+using static TheOtherRoles.TheOtherRoles;
+using static TheOtherRoles.GameHistory;
using UnityEngine;
-namespace BonusRoles {
+namespace TheOtherRoles {
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.FixedUpdate))]
public static class PlayerControlFixedUpdatePatch
{
}
}
- static PlayerControl setAnyRoleTarget() {
+ static PlayerControl setTarget(bool onlyCrewmates = false, bool targetPlayersInVents = false) {
PlayerControl result = null;
float num = GameOptionsData.KillDistances[Mathf.Clamp(PlayerControl.GameOptions.KillDistance, 0, 2)];
if (!ShipStatus.Instance) return result;
for (int i = 0; i < allPlayers.Count; i++)
{
GameData.PlayerInfo playerInfo = allPlayers[i];
- if (!playerInfo.Disconnected && playerInfo.PlayerId != PlayerControl.LocalPlayer.PlayerId && !playerInfo.IsDead)
+ if (!playerInfo.Disconnected && playerInfo.PlayerId != PlayerControl.LocalPlayer.PlayerId && !playerInfo.IsDead && (!onlyCrewmates || !playerInfo.IsImpostor))
{
PlayerControl @object = playerInfo.Object;
- if (@object && !@object.inVent)
+ if (@object && (!@object.inVent || targetPlayersInVents))
{
Vector2 vector = @object.GetTruePosition() - truePosition;
float magnitude = vector.magnitude;
static void medicSetTarget() {
if (Medic.medic == null || Medic.medic != PlayerControl.LocalPlayer) return;
- Medic.currentTarget = setAnyRoleTarget();
+ Medic.currentTarget = setTarget();
}
static void shifterSetTarget() {
if (Shifter.shifter == null || Shifter.shifter != PlayerControl.LocalPlayer) return;
- Shifter.currentTarget = setAnyRoleTarget();
+ Shifter.currentTarget = setTarget();
}
static void morphlingSetTarget() {
if (Morphling.morphling == null || Morphling.morphling != PlayerControl.LocalPlayer) return;
- Morphling.currentTarget = setAnyRoleTarget();
+ Morphling.currentTarget = setTarget();
}
static void sheriffSetTarget() {
if (Sheriff.sheriff == null || Sheriff.sheriff != PlayerControl.LocalPlayer) return;
- Sheriff.currentTarget = setAnyRoleTarget();
+ Sheriff.currentTarget = setTarget();
}
static void seerSetTarget() {
if (Seer.seer == null || Seer.seer != PlayerControl.LocalPlayer) return;
- Seer.currentTarget = setAnyRoleTarget();
+ Seer.currentTarget = setTarget();
if (Seer.currentTarget != null && Seer.revealedPlayers.Keys.Any(p => p.Data.PlayerId == Seer.currentTarget.Data.PlayerId)) Seer.currentTarget = null; // Remove target if already revealed
+ }
+ static void trackerSetTarget() {
+ if (Tracker.tracker == null || Tracker.tracker != PlayerControl.LocalPlayer) return;
+ Tracker.currentTarget = setTarget();
}
static void detectiveSetFootPrints() {
if (Detective.timer <= 0f) {
Detective.timer = Detective.footprintIntervall;
foreach (PlayerControl player in PlayerControl.AllPlayerControls) {
- if (player != null && player != PlayerControl.LocalPlayer && !player.Data.IsDead) {
+ if (player != null && player != PlayerControl.LocalPlayer && !player.Data.IsDead && !player.inVent) {
new Footprint(Detective.footprintDuration, Detective.anonymousFootprints, player);
}
}
}
+ }
+
+ static void vampireSetTarget() {
+ if (Vampire.vampire == null || Vampire.vampire != PlayerControl.LocalPlayer) return;
+ PlayerControl target = setTarget(true, true);
+ bool targetNearGarlic = false;
+ if (target != null) {
+ foreach (Garlic garlic in Garlic.garlics) {
+ if (Vector2.Distance(garlic.garlic.transform.position, target.transform.position) <= 1.91f) {
+ targetNearGarlic = true;
+ }
+ }
+ }
+ Vampire.targetNearGarlic = targetNearGarlic;
+ Vampire.currentTarget = target;
+ }
+
+ static void engineerUpdate() {
+ if (PlayerControl.LocalPlayer.Data.IsImpostor && Engineer.engineer != null) {
+ foreach (Vent vent in ShipStatus.Instance.AllVents) {
+ if (vent.Field_7?.material != null) {
+ if (Engineer.engineer.inVent) {
+ vent.Field_7.material.SetFloat("_Outline", 1f);
+ vent.Field_7.material.SetColor("_OutlineColor", Engineer.color);
+ } else if (vent.Field_7.material.GetColor("_AddColor") != Color.red) {
+ vent.Field_7.material.SetFloat("_Outline", 0);
+ }
+ }
+ }
+ }
+ }
+
+ static void trackerUpdate() {
+ if (Tracker.tracker == null || Tracker.tracked == null) return;
+
+ if (Tracker.arrow?.arrow != null && PlayerControl.LocalPlayer != Tracker.tracker) {
+ Tracker.arrow.arrow.SetActive(false);
+ return;
+ }
+
+ if (Tracker.arrow?.arrow != null && Tracker.tracked != null) {
+ Tracker.timeUntilUpdate -= Time.fixedDeltaTime;
+
+ if (Tracker.timeUntilUpdate <= 0f) {
+ bool trackedOnMap = !Tracker.tracked.Data.IsDead;
+ System.Console.WriteLine("Update");
+ Vector3 position = Tracker.tracked.transform.position;
+ if (!trackedOnMap) { // Check for dead body
+ DeadBody body = UnityEngine.Object.FindObjectsOfType<DeadBody>().FirstOrDefault(b => b.ParentId == Tracker.tracked.PlayerId);
+ if (body != null) {
+ trackedOnMap = true;
+ position = body.transform.position;
+ System.Console.WriteLine("DeadBody");
+ }
+ }
+ Tracker.arrow.Update(position);
+ Tracker.arrow.arrow.SetActive(trackedOnMap);
+ Tracker.timeUntilUpdate = Tracker.updateIntervall;
+ } else {
+ Tracker.arrow.Update();
+ }
+ }
}
public static void Postfix(PlayerControl __instance) {
seerSetTarget();
// Detective
detectiveSetFootPrints();
+ // Tracker
+ trackerSetTarget();
+ // Vampire
+ vampireSetTarget();
+ Garlic.UpdateAll();
+ // Engineer
+ engineerUpdate();
+ // Tracker
+ trackerUpdate();
}
}
}
+ [HarmonyPatch(typeof(HudManager), nameof(HudManager.OpenMeetingRoom))]
+ class StartMeetingHostPatch {
+ public static void Prefix(PlayerControl __instance) {
+ // Perform vampire bite kill before the meeting starts for HOST
+ if (!MeetingHud.Instance && AmongUsClient.Instance.AmHost)
+ RPCProcedure.vampireTryKill();
+ }
+ }
+
+ [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.CoStartMeeting))]
+ class StartMeetingClientPatch {
+ public static void Prefix(PlayerControl __instance) {
+ // Perform vampire bite kill before the meeting starts for CLIENTS
+ if (AmongUsClient.Instance.AmClient)
+ RPCProcedure.vampireTryKill();
+ }
+ }
+
[HarmonyPatch(typeof(KillButtonManager), nameof(KillButtonManager.PerformKill))]
class PerformKillPatch
{
public static bool Prefix(KillButtonManager __instance) {
- // Block impostor shielded kill
- if (Medic.shielded != null && Medic.shielded == __instance.CurrentTarget) {
- MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ShieldedMurderAttempt, Hazel.SendOption.None, -1);
- AmongUsClient.Instance.FinishRpcImmediately(writer);
- RPCProcedure.shieldedMurderAttempt();
- return false;
- }
- // Block impostor not fully grown child kill
- else if (Child.child != null && __instance.CurrentTarget == Child.child && !Child.isGrownUp()) {
- return false;
- }
- return true;
+ return Helpers.handleMurderAttempt(__instance.CurrentTarget);
}
}
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.MurderPlayer))]
public static class MurderPlayerPatch
{
- public static void Prefix(PlayerControl __instance, PlayerControl PAIBDFDMIGK, out bool __state)
- {
- // __state denotes if the player performing the murder needs to be reset to crewmate
- __state = false;
+ public static bool resetToCrewmate = false;
- // Allow Sheriff to kill "as crewmate" by assigning the impostor role
- if (Sheriff.sheriff != null && __instance == Sheriff.sheriff) {
- __instance.Data.IsImpostor = true;
- __state = true;
- }
- // Allow Shifter to suicide
- else if (Shifter.shifter != null && __instance == Shifter.shifter) {
- __instance.Data.IsImpostor = true;
- __state = true;
- }
- // Allow Lover which is no impostor to suicide
- else if ((Lovers.lover1 != null && __instance == Lovers.lover1) || (Lovers.lover2 != null && __instance == Lovers.lover2)) {
- if (!__instance.Data.IsImpostor) {
- __instance.Data.IsImpostor = true;
- __state = true;
- }
- }
+ public static void Prefix(PlayerControl __instance, PlayerControl PAIBDFDMIGK)
+ {
+ // Allow everyone to murder players
+ resetToCrewmate = !__instance.Data.IsImpostor;
+ __instance.Data.IsImpostor = true;
}
- public static void Postfix(PlayerControl __instance, PlayerControl PAIBDFDMIGK, bool __state)
+ public static void Postfix(PlayerControl __instance, PlayerControl PAIBDFDMIGK)
{
// Collect dead player info
DeadPlayer deadPlayer = new DeadPlayer(PAIBDFDMIGK, DateTime.UtcNow, DeathReason.Kill, __instance);
GameHistory.deadPlayers.Add(deadPlayer);
- // Reset killer to crewmate if __state
- if (__state) __instance.Data.IsImpostor = false;
+ // Reset killer to crewmate if resetToCrewmate
+ if (resetToCrewmate) __instance.Data.IsImpostor = false;
// Lover suicide trigger on murder
if ((Lovers.lover1 != null && PAIBDFDMIGK == Lovers.lover1) || (Lovers.lover2 != null && PAIBDFDMIGK == Lovers.lover2)) {
RPCProcedure.loverSuicide(otherLover.PlayerId);
}
}
-
}
}
}
using HarmonyLib;
using Hazel;
-using static BonusRoles.BonusRoles;
-using static BonusRoles.HudManagerStartPatch;
-using static BonusRoles.GameHistory;
+using static TheOtherRoles.TheOtherRoles;
+using static TheOtherRoles.HudManagerStartPatch;
+using static TheOtherRoles.GameHistory;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using UnityEngine;
using System;
-namespace BonusRoles
+namespace TheOtherRoles
{
enum RoleId {
- Jester = 0,
- Mayor = 1,
- Engineer = 2,
- Sheriff = 3,
- Lighter = 4,
- Godfather = 5,
- Mafioso = 6,
- Janitor = 7,
- Detective = 8,
- TimeMaster = 9,
- Medic = 10,
- Shifter = 11,
- Swapper = 12,
- Lover1 = 13,
- Lover2 = 14,
- Seer = 15,
- Morphling = 16,
- Camouflager = 17,
- Spy = 18,
- Child = 19,
+ Jester,
+ Mayor,
+ Engineer,
+ Sheriff,
+ Lighter,
+ Godfather,
+ Mafioso,
+ Janitor,
+ Detective,
+ TimeMaster,
+ Medic,
+ Shifter,
+ Swapper,
+ Lover1,
+ Lover2,
+ Seer,
+ Morphling,
+ Camouflager,
+ Spy,
+ Child,
+ BountyHunter,
+ Tracker,
+ Vampire,
+ Snitch
}
enum CustomRPC
// Role functionality
- JesterWin = 80,
+ JesterBountyHunterWin = 80,
EngineerFixLights = 81,
EngineerUsedRepair = 82,
JanitorClean = 83,
SeerReveal = 91,
MorphlingMorph = 92,
CamouflagerCamouflage = 93,
- ChildDied = 94,
+ TrackerUsedTracker = 94,
LoverSuicide = 95,
+ SetBountyHunterTarget = 96,
+ VampireBiteNotification = 97,
+ VampireTryKill = 98,
+ PlaceGarlic = 99,
}
public static class RPCProcedure {
// Main Controls
public static void resetVariables() {
+ Garlic.clearGarlics();
clearAndReloadRoles();
clearGameHistory();
setCustomButtonCooldowns();
case RoleId.Child:
Child.child = player;
break;
+ case RoleId.BountyHunter:
+ BountyHunter.bountyHunter = player;
+ break;
+ case RoleId.Tracker:
+ Tracker.tracker = player;
+ break;
+ case RoleId.Vampire:
+ Vampire.vampire = player;
+ break;
+ case RoleId.Snitch:
+ Snitch.snitch = player;
+ break;
}
}
}
// Role functionality
- public static void jesterWin() {
- Jester.jester.Revive();
- Jester.jester.Data.IsDead = false;
- Jester.jester.Data.IsImpostor = true;
+ public static void jesterBountyHunterWin(byte exiledId) {
+ PlayerControl exiled = Helpers.playerById(exiledId);
+ if (exiled == null) return;
+
+ bool jesterWin = false;
+ bool bountyHunterWin = false;
+
+ if (Jester.jester != null && exiled == Jester.jester) {
+ Jester.jester.Revive();
+ Jester.jester.Data.IsDead = false;
+ Jester.jester.Data.IsImpostor = true;
+ jesterWin = true;
+ }
+ if (BountyHunter.bountyHunter != null && !BountyHunter.bountyHunter.Data.IsDead && BountyHunter.target == exiled) {
+ BountyHunter.bountyHunter.Data.IsImpostor = true;
+ bountyHunterWin = true;
+ }
+
foreach (PlayerControl player in PlayerControl.AllPlayerControls)
{
- if (player != Jester.jester)
+ if (player != null && player != Jester.jester && player != BountyHunter.bountyHunter)
{
player.RemoveInfected();
player.Die(DeathReason.Exile);
player.Data.IsImpostor = false;
}
}
+ if (jesterWin && !bountyHunterWin && BountyHunter.bountyHunter != null) {
+ BountyHunter.bountyHunter.RemoveInfected();
+ BountyHunter.bountyHunter.Die(DeathReason.Exile);
+ BountyHunter.bountyHunter.Data.IsDead = true;
+ BountyHunter.bountyHunter.Data.IsImpostor = false;
+ } else if (bountyHunterWin && !jesterWin && Jester.jester != null) {
+ Jester.jester.RemoveInfected();
+ Jester.jester.Die(DeathReason.Exile);
+ Jester.jester.Data.IsDead = true;
+ Jester.jester.Data.IsImpostor = false;
+ }
}
public static void engineerFixLights() {
Spy.spy = oldShifter;
} else if (Child.child != null && Child.child == player) {
Child.child = oldShifter;
- } else { // Crewmate
+ } else if (BountyHunter.bountyHunter != null && BountyHunter.bountyHunter == player) {
+ BountyHunter.bountyHunter = oldShifter;
+ } else if (Tracker.tracker != null && Tracker.tracker == player) {
+ Tracker.tracker = oldShifter;
+ } else if (Snitch.snitch != null && Snitch.snitch == player) {
+ Snitch.snitch = oldShifter;
+ }else { // Crewmate
}
Shifter.shifter = player;
Camouflager.camouflageTimer = 10f;
}
- public static void childDied() {
- Child.child.Revive();
- Child.child.Data.IsDead = false;
- Child.child.Data.IsImpostor = true;
- foreach (PlayerControl player in PlayerControl.AllPlayerControls)
- {
- if (player != null && player != Child.child)
- {
- player.RemoveInfected();
- player.Die(DeathReason.Exile);
- player.Data.IsDead = true;
- player.Data.IsImpostor = false;
- }
- }
- }
-
public static void loverSuicide(byte remainingLoverId) {
if (Lovers.lover1 != null && !Lovers.lover1.Data.IsDead && Lovers.lover1.PlayerId == remainingLoverId) {
Lovers.lover1.MurderPlayer(Lovers.lover1);
} else if (Lovers.lover2 != null && !Lovers.lover2.Data.IsDead && Lovers.lover2.PlayerId == remainingLoverId) {
Lovers.lover2.MurderPlayer(Lovers.lover2);
}
- }
+ }
+
+ public static void setBountyHunterTarget(byte targetId) {
+ foreach (PlayerControl player in PlayerControl.AllPlayerControls)
+ if (player.PlayerId == targetId)
+ BountyHunter.target = player;
+ }
+
+ public static void vampireBiteNotification(byte targetId) {
+ if (Vampire.vampire == null) return;
+ foreach (PlayerControl player in PlayerControl.AllPlayerControls) {
+ if (player.PlayerId == targetId && !player.Data.IsDead) {
+ Vampire.bitten = player;
+ }
+ }
+ }
+
+ public static void vampireTryKill() {
+ if (Vampire.vampire == null || Vampire.bitten == null) return;
+
+ if (!Vampire.bitten.Data.IsDead && Helpers.handleMurderAttempt(Vampire.bitten, false)) {
+ Vampire.bitten.MurderPlayer(Vampire.bitten); // Suicide because of the kill animation teleport
+ }
+ Vampire.bitten = null;
+ }
+
+ public static void placeGarlic(byte[] buff) {
+ Vector3 position = Vector3.zero;
+ position.x = BitConverter.ToSingle(buff, 0*sizeof(float));
+ position.y = BitConverter.ToSingle(buff, 1*sizeof(float));
+ new Garlic(position);
+ }
+
+ public static void trackerUsedTracker(byte targetId) {
+ Tracker.usedTracker = true;
+ foreach (PlayerControl player in PlayerControl.AllPlayerControls)
+ if (player.PlayerId == targetId)
+ Tracker.tracked = player;
+ }
}
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.HandleRpc))]
// Role functionality
- case (byte)CustomRPC.JesterWin:
- RPCProcedure.jesterWin();
+ case (byte)CustomRPC.JesterBountyHunterWin:
+ RPCProcedure.jesterBountyHunterWin(HFPCBBHJIPJ.ReadByte());
break;
case (byte)CustomRPC.EngineerFixLights:
RPCProcedure.engineerFixLights();
case (byte)CustomRPC.CamouflagerCamouflage:
RPCProcedure.camouflagerCamouflage();
break;
- case (byte)CustomRPC.ChildDied:
- RPCProcedure.childDied();
- break;
case (byte)CustomRPC.LoverSuicide:
RPCProcedure.loverSuicide(HFPCBBHJIPJ.ReadByte());
break;
+ case (byte)CustomRPC.SetBountyHunterTarget:
+ RPCProcedure.setBountyHunterTarget(HFPCBBHJIPJ.ReadByte());
+ break;
+ case (byte)CustomRPC.VampireBiteNotification:
+ RPCProcedure.vampireBiteNotification(HFPCBBHJIPJ.ReadByte());
+ break;
+ case (byte)CustomRPC.VampireTryKill:
+ RPCProcedure.vampireTryKill();
+ break;
+ case (byte)CustomRPC.PlaceGarlic:
+ RPCProcedure.placeGarlic(HFPCBBHJIPJ.ReadBytesAndSize());
+ break;
+ case (byte)CustomRPC.TrackerUsedTracker:
+ RPCProcedure.trackerUsedTracker(HFPCBBHJIPJ.ReadByte());
+ break;
}
}
}
using System.Collections.Generic;
using System.Linq;
using UnhollowerBaseLib;
+using UnityEngine;
using System;
-using static BonusRoles.BonusRoles;
+using static TheOtherRoles.TheOtherRoles;
-namespace BonusRoles
+namespace TheOtherRoles
{
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.RpcSetInfected))]
class SetInfectedPatch
{
+
private static void setRoleToRandomPlayer(byte roleId, List<PlayerControl> playerList) {
var index = rnd.Next(0, playerList.Count);
byte playerId = playerList[index].PlayerId;
playerList.RemoveAt(index);
+ setRoleToPlayer(roleId, playerId);
+ }
+
+ private static void setRoleToPlayer(byte roleId, byte playerId) {
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetRole, Hazel.SendOption.None, -1);
writer.Write(roleId);
writer.Write(playerId);
List<PlayerControl> impostors = PlayerControl.AllPlayerControls.ToArray().ToList().OrderBy(x => Guid.NewGuid()).ToList();
impostors.RemoveAll(x => !x.Data.IsImpostor);
- // Special roles impostors can be converted to
- if (impostors.Count >= 3 && (rnd.Next(1, 101) <= BonusRolesPlugin.mafiaSpawnChance.GetValue())) {
+ float crewCountSettings = TheOtherRolesPlugin.crewmateRolesCount.GetValue();
+ float impCountSettings = TheOtherRolesPlugin.impostorRolesCount.GetValue();
+
+ if (crewCountSettings % 1 == 0.5f) crewCountSettings += 0.5f * (rnd.Next(2) * 2 - 1);
+ if (impCountSettings % 1 == 0.5f) impCountSettings += 0.5f * (rnd.Next(2) * 2 - 1);
+
+ int maxCrewmateRoles = Mathf.Min(crewmates.Count, Mathf.RoundToInt(crewCountSettings));
+ int maxImpostorRoles = Mathf.Min(impostors.Count, Mathf.RoundToInt(impCountSettings));
+
+ Dictionary<byte, int> impSettings = new Dictionary<byte, int>();
+ Dictionary<byte, int> crewSettings = new Dictionary<byte, int>();
+
+ impSettings.Add((byte)RoleId.Morphling, TheOtherRolesPlugin.morphlingSpawnRate.GetValue());
+ impSettings.Add((byte)RoleId.Camouflager, TheOtherRolesPlugin.camouflagerSpawnRate.GetValue());
+ impSettings.Add((byte)RoleId.Vampire, TheOtherRolesPlugin.vampireSpawnRate.GetValue());
+
+ crewSettings.Add((byte)RoleId.Jester, TheOtherRolesPlugin.jesterSpawnRate.GetValue());
+ crewSettings.Add((byte)RoleId.Mayor, TheOtherRolesPlugin.mayorSpawnRate.GetValue());
+ crewSettings.Add((byte)RoleId.Engineer, TheOtherRolesPlugin.engineerSpawnRate.GetValue());
+ crewSettings.Add((byte)RoleId.Sheriff, TheOtherRolesPlugin.sheriffSpawnRate.GetValue());
+ crewSettings.Add((byte)RoleId.Lighter, TheOtherRolesPlugin.lighterSpawnRate.GetValue());
+ crewSettings.Add((byte)RoleId.Detective, TheOtherRolesPlugin.detectiveSpawnRate.GetValue());
+ crewSettings.Add((byte)RoleId.TimeMaster, TheOtherRolesPlugin.timeMasterSpawnRate.GetValue());
+ crewSettings.Add((byte)RoleId.Medic, TheOtherRolesPlugin.medicSpawnRate.GetValue());
+ crewSettings.Add((byte)RoleId.Shifter, TheOtherRolesPlugin.shifterSpawnRate.GetValue());
+ crewSettings.Add((byte)RoleId.Swapper,TheOtherRolesPlugin.swapperSpawnRate.GetValue());
+ crewSettings.Add((byte)RoleId.Seer, TheOtherRolesPlugin.seerSpawnRate.GetValue());
+ crewSettings.Add((byte)RoleId.Spy, TheOtherRolesPlugin.spySpawnRate.GetValue());
+ crewSettings.Add((byte)RoleId.Child, TheOtherRolesPlugin.childSpawnRate.GetValue());
+ crewSettings.Add((byte)RoleId.Tracker, TheOtherRolesPlugin.trackerSpawnRate.GetValue());
+ crewSettings.Add((byte)RoleId.Snitch, TheOtherRolesPlugin.snitchSpawnRate.GetValue());
+ // crewSettings.Add((byte)RoleId.BountyHunter, TheOtherRolesPlugin.bountyHunterSpawnRate.GetValue()); BOUNTY HUNTER
+
+ // Set multiple player roles
+ if (impostors.Count >= 3 && maxImpostorRoles >= 3 && (rnd.Next(1, 101) <= TheOtherRolesPlugin.mafiaSpawnRate.GetValue() * 10)) {
setRoleToRandomPlayer((byte)RoleId.Godfather, impostors);
setRoleToRandomPlayer((byte)RoleId.Janitor, impostors);
setRoleToRandomPlayer((byte)RoleId.Mafioso, impostors);
+ maxImpostorRoles -= 3;
}
- // Special roles that involve crewmates and impostors
- if (rnd.Next(1, 101) <= BonusRolesPlugin.loversSpawnChance.GetValue())
- {
- if (impostors.Count > 0 && crewmates.Count > 0 && rnd.Next(1, 101) <= 33) {
+ if (rnd.Next(1, 101) <= TheOtherRolesPlugin.loversSpawnRate.GetValue() * 10) {
+ if (impostors.Count > 0 && crewmates.Count > 0 && maxCrewmateRoles > 0 && maxImpostorRoles > 0 && rnd.Next(1, 101) <= 33) {
setRoleToRandomPlayer((byte)RoleId.Lover1, impostors);
- setRoleToRandomPlayer((byte)RoleId.Lover2, crewmates);
- } else if (crewmates.Count >= 2) {
+ setRoleToRandomPlayer((byte)RoleId.Lover2, crewmates);
+ maxCrewmateRoles--;
+ maxImpostorRoles--;
+ } else if (crewmates.Count >= 2 && maxCrewmateRoles >= 2) {
setRoleToRandomPlayer((byte)RoleId.Lover1, crewmates);
setRoleToRandomPlayer((byte)RoleId.Lover2, crewmates);
+ maxCrewmateRoles -= 2;
}
}
- // Special roles impostors can be converted to
- if (impostors.Count >= 1 && (rnd.Next(1, 101) <= BonusRolesPlugin.morphlingSpawnChance.GetValue()))
- setRoleToRandomPlayer((byte)RoleId.Morphling, impostors);
+ // Set tickets and always active roles
- if (impostors.Count >= 1 && (rnd.Next(1, 101) <= BonusRolesPlugin.camouflagerSpawnChance.GetValue()))
- setRoleToRandomPlayer((byte)RoleId.Camouflager, impostors);
-
- // Special roles crewmates can be converted to
- if (crewmates.Count > 0 && (rnd.Next(1, 101) <= BonusRolesPlugin.jesterSpawnChance.GetValue()))
- setRoleToRandomPlayer((byte)RoleId.Jester, crewmates);
- if (crewmates.Count > 0 && (rnd.Next(1, 101) <= BonusRolesPlugin.mayorSpawnChance.GetValue()))
- setRoleToRandomPlayer((byte)RoleId.Mayor, crewmates);
- if (crewmates.Count > 0 && (rnd.Next(1, 101) <= BonusRolesPlugin.engineerSpawnChance.GetValue()))
- setRoleToRandomPlayer((byte)RoleId.Engineer, crewmates);
- if (crewmates.Count > 0 && (rnd.Next(1, 101) <= BonusRolesPlugin.sheriffSpawnChance.GetValue()))
- setRoleToRandomPlayer((byte)RoleId.Sheriff, crewmates);
- if (crewmates.Count > 0 && (rnd.Next(1, 101) <= BonusRolesPlugin.lighterSpawnChance.GetValue()))
- setRoleToRandomPlayer((byte)RoleId.Lighter, crewmates);
- if (crewmates.Count > 0 && (rnd.Next(1, 101) <= BonusRolesPlugin.detectiveSpawnChance.GetValue()))
- setRoleToRandomPlayer((byte)RoleId.Detective, crewmates);
- if (crewmates.Count > 0 && (rnd.Next(1, 101) <= BonusRolesPlugin.timeMasterSpawnChance.GetValue()))
- setRoleToRandomPlayer((byte)RoleId.TimeMaster, crewmates);
- if (crewmates.Count > 0 && (rnd.Next(1, 101) <= BonusRolesPlugin.medicSpawnChance.GetValue()))
- setRoleToRandomPlayer((byte)RoleId.Medic, crewmates);
- if (crewmates.Count > 0 && (rnd.Next(1, 101) <= BonusRolesPlugin.shifterSpawnChance.GetValue()))
- setRoleToRandomPlayer((byte)RoleId.Shifter, crewmates);
- if (crewmates.Count > 0 && (rnd.Next(1, 101) <= BonusRolesPlugin.swapperSpawnChance.GetValue()))
- setRoleToRandomPlayer((byte)RoleId.Swapper, crewmates);
- if (crewmates.Count > 0 && (rnd.Next(1, 101) <= BonusRolesPlugin.seerSpawnChance.GetValue()))
- setRoleToRandomPlayer((byte)RoleId.Seer, crewmates);
- if (crewmates.Count > 0 && (rnd.Next(1, 101) <= BonusRolesPlugin.spySpawnChance.GetValue()))
- setRoleToRandomPlayer((byte)RoleId.Spy, crewmates);
- if (crewmates.Count > 0 && (rnd.Next(1, 101) <= BonusRolesPlugin.childSpawnChance.GetValue()))
- setRoleToRandomPlayer((byte)RoleId.Child, crewmates);
+ List<byte> crewTickets = new List<byte>();
+ List<byte> impTickets = new List<byte>();
+
+ foreach (KeyValuePair<byte, int> entry in crewSettings) {
+ if (entry.Value == 0) { // Never
+ } else if (entry.Value == 10) { // Always
+ if (crewmates.Count > 0 && maxCrewmateRoles > 0) {
+ setRoleToRandomPlayer(entry.Key, crewmates);
+ maxCrewmateRoles--;
+ }
+ } else { // Other
+ for (int i = 0; i < entry.Value; i++) crewTickets.Add(entry.Key);
+ }
+ }
+
+ foreach (KeyValuePair<byte, int> entry in impSettings) {
+ if (entry.Value == 0) { // Never
+ } else if (entry.Value == 10) { // Always
+ if (impostors.Count > 0 && maxImpostorRoles > 0) {
+ setRoleToRandomPlayer(entry.Key, impostors);
+ maxImpostorRoles--;
+ }
+ } else { // Other
+ for (int i = 0; i < entry.Value; i++) impTickets.Add(entry.Key);
+ }
+ }
+
+ // Set solo player roles
+
+ for (int i = 0; i < maxCrewmateRoles; i++) {
+ if (crewTickets.Count > 0 && crewmates.Count > 0) {
+ var index = rnd.Next(0, crewTickets.Count);
+ byte roleId = crewTickets[index];
+ crewTickets.RemoveAll(x => x == roleId);
+ setRoleToRandomPlayer(roleId, crewmates);
+ }
+ }
+
+ for (int i = 0; i < maxImpostorRoles; i++) {
+ if (impTickets.Count > 0 && impostors.Count > 0) {
+ var index = rnd.Next(0, impTickets.Count);
+ byte roleId = impTickets[index];
+ impTickets.RemoveAll(x => x == roleId);
+ setRoleToRandomPlayer(roleId, impostors);
+ }
+ }
+
+ // if (crewmates.Count > 0 && (rnd.Next(1, 101) <= TheOtherRolesPlugin.bountyHunterSpawnRate.GetValue())) {
+ // List<PlayerControl> availableTargets = PlayerControl.AllPlayerControls.ToArray().ToList();
+ // var bountyHunterIndex = rnd.Next(0, crewmates.Count);
+ // byte bountyHunterId = crewmates[bountyHunterIndex].PlayerId;
+
+ // availableTargets.RemoveAll(x => x.Data.IsImpostor || x.PlayerId == bountyHunterId);
+
+ // if (availableTargets.Count > 0) {
+ // byte targetId = availableTargets[rnd.Next(0, availableTargets.Count)].PlayerId;
+ // crewmates.RemoveAt(bountyHunterIndex);
+ // setRoleToPlayer((byte)RoleId.BountyHunter, bountyHunterId);
+ // writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetBountyHunterTarget, Hazel.SendOption.None, -1);
+ // writer.Write(targetId);
+ // AmongUsClient.Instance.FinishRpcImmediately(writer);
+ // RPCProcedure.setBountyHunterTarget(targetId);
+ // }
+ // }
}
}
}
using HarmonyLib;
-using static BonusRoles.BonusRoles;
+using static TheOtherRoles.TheOtherRoles;
-namespace BonusRoles {
+namespace TheOtherRoles {
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.CalculateLightRadius))]
public class ShipStatusPatch {
--- /dev/null
+using System.Net;
+using System.Linq;
+using BepInEx;
+using BepInEx.Configuration;
+using BepInEx.IL2CPP;
+using HarmonyLib;
+using Hazel;
+using Reactor;
+using System;
+using System.Collections.Generic;
+using System.Collections;
+using System.IO;
+using UnityEngine;
+using Reactor.Unstrip;
+using Reactor.Extensions;
+
+namespace TheOtherRoles
+{
+ [HarmonyPatch]
+ public static class TheOtherRoles
+ {
+ public static System.Random rnd = new System.Random((int)DateTime.Now.Ticks);
+
+ public static void clearAndReloadRoles() {
+ Jester.clearAndReload();
+ Mayor.clearAndReload();
+ Engineer.clearAndReload();
+ Sheriff.clearAndReload();
+ Lighter.clearAndReload();
+ Godfather.clearAndReload();
+ Mafioso.clearAndReload();
+ Janitor.clearAndReload();
+ Detective.clearAndReload();
+ TimeMaster.clearAndReload();
+ Medic.clearAndReload();
+ Shifter.clearAndReload();
+ Swapper.clearAndReload();
+ Lovers.clearAndReload();
+ Seer.clearAndReload();
+ Morphling.clearAndReload();
+ Camouflager.clearAndReload();
+ Spy.clearAndReload();
+ Child.clearAndReload();
+ BountyHunter.clearAndReload();
+ Tracker.clearAndReload();
+ Vampire.clearAndReload();
+ Snitch.clearAndReload();
+ }
+
+ public static class Jester {
+ public static PlayerControl jester;
+ public static Color color = new Color(255f / 255f, 84f / 255f, 167f / 255f, 1);
+
+ public static void clearAndReload() {
+ jester = null;
+ }
+ }
+
+ public static class Mayor {
+ public static PlayerControl mayor;
+ public static Color color = new Color(105f / 255f, 58f / 255f, 58f / 255f, 1);
+
+ public static void clearAndReload() {
+ mayor = null;
+ }
+ }
+
+ public static class Engineer {
+ public static PlayerControl engineer;
+ public static Color color = new Color(98f / 255f, 216f / 255f, 240f / 255f, 1);
+ public static bool usedRepair;
+ private static Sprite buttonSprite;
+
+ public static Sprite getButtonSprite() {
+ if (buttonSprite) return buttonSprite;
+ buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.RepairButton.png", 100f);
+ return buttonSprite;
+ }
+
+ public static void clearAndReload() {
+ engineer = null;
+ usedRepair = false;
+ }
+ }
+
+ public static class Godfather {
+ public static PlayerControl godfather;
+ public static Color color = Palette.ImpostorRed;
+
+ public static void clearAndReload() {
+ godfather = null;
+ }
+ }
+
+ public static class Mafioso {
+ public static PlayerControl mafioso;
+ public static Color color = Palette.ImpostorRed;
+
+ public static void clearAndReload() {
+ mafioso = null;
+ }
+ }
+
+
+ public static class Janitor {
+ public static PlayerControl janitor;
+ public static Color color = Palette.ImpostorRed;
+
+ public static float cooldown = float.MaxValue;
+
+ private static Sprite buttonSprite;
+ public static Sprite getButtonSprite() {
+ if (buttonSprite) return buttonSprite;
+ buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.CleanButton.png", 100f);
+ return buttonSprite;
+ }
+
+ public static void clearAndReload() {
+ janitor = null;
+ cooldown = TheOtherRolesPlugin.janitorCooldown.GetValue();
+ }
+ }
+
+ public static class Sheriff {
+ public static PlayerControl sheriff;
+ public static Color color = new Color(255f / 255f, 204f / 255f, 0f / 255f, 1);
+
+ public static float cooldown = float.MaxValue;
+ public static bool jesterCanDieToSheriff = false;
+
+ public static PlayerControl currentTarget;
+
+ public static void clearAndReload() {
+ sheriff = null;
+ currentTarget = null;
+ cooldown = TheOtherRolesPlugin.sheriffCooldown.GetValue();
+ jesterCanDieToSheriff = TheOtherRolesPlugin.jesterCanDieToSheriff.GetValue();
+ }
+ }
+
+ public static class Lighter {
+ public static PlayerControl lighter;
+ public static Color color = new Color(250f / 255f, 204f / 255f, 37f / 255f, 1);
+
+ public static float lighterVision = 2f;
+
+ public static void clearAndReload() {
+ lighter = null;
+ lighterVision = TheOtherRolesPlugin.lighterVision.GetValue();
+ }
+ }
+
+ public static class Detective {
+ public static PlayerControl detective;
+ public static Color color = new Color(2f / 255f, 61f / 255f, 156f / 255f, 1);
+
+ public static float footprintIntervall = 1f;
+ public static float footprintDuration = 1f;
+ public static bool anonymousFootprints = false;
+
+ public static float timer = 1f;
+
+ public static void clearAndReload() {
+ detective = null;
+ anonymousFootprints = TheOtherRolesPlugin.detectiveAnonymousFootprints.GetValue();
+ footprintIntervall = TheOtherRolesPlugin.detectiveFootprintIntervall.GetValue();
+ footprintDuration = TheOtherRolesPlugin.detectiveFootprintDuration.GetValue();
+ timer = footprintIntervall;
+ }
+ }
+ }
+
+ public static class TimeMaster {
+ public static PlayerControl timeMaster;
+ public static Color color = new Color(114f / 255f, 234f / 255f, 247f / 255f, 1);
+
+ public static bool reviveDuringRewind = false;
+ public static float rewindTime = 3f;
+ public static float cooldown = float.MaxValue;
+
+ public static bool isRewinding = false;
+
+ private static Sprite buttonSprite;
+ public static Sprite getButtonSprite() {
+ if (buttonSprite) return buttonSprite;
+ buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.RewindButton.png", 100f);
+ return buttonSprite;
+ }
+
+ public static void clearAndReload() {
+ timeMaster = null;
+ isRewinding = false;
+ reviveDuringRewind = TheOtherRolesPlugin.timeMasterReviveDuringRewind.GetValue();
+ rewindTime = TheOtherRolesPlugin.timeMasterRewindTime.GetValue();
+ cooldown = TheOtherRolesPlugin.timeMasterCooldown.GetValue();
+ }
+ }
+
+ public static class Medic {
+ public static PlayerControl medic;
+ public static PlayerControl shielded;
+ public static Color color = new Color(0f / 255f, 80f / 255f, 105f / 255f, 1);
+ public static bool usedShield;
+
+ public static float reportNameDuration = 10f;
+ public static float reportColorDuration = 20f;
+ public static int showShielded = 0;
+ public static bool showAttemptToShielded = false;
+
+ public static Color shieldedColor = new Color(0f / 255f, 221f / 255f, 255f / 255f, 1);
+ public static PlayerControl currentTarget;
+
+ private static Sprite buttonSprite;
+ public static Sprite getButtonSprite() {
+ if (buttonSprite) return buttonSprite;
+ buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.ShieldButton.png", 100f);
+ return buttonSprite;
+ }
+
+ public static void clearAndReload() {
+ medic = null;
+ shielded = null;
+ currentTarget = null;
+ usedShield = false;
+ shieldedColor = new Color(0f / 255f, 221f / 255f, 255f / 255f, 1);
+ reportNameDuration = TheOtherRolesPlugin.medicReportNameDuration.GetValue();
+ reportColorDuration = TheOtherRolesPlugin.medicReportColorDuration.GetValue();
+ showShielded = TheOtherRolesPlugin.medicShowShielded.GetValue();
+ showAttemptToShielded = TheOtherRolesPlugin.medicShowAttemptToShielded.GetValue();
+ }
+ }
+
+ public static class Shifter {
+ public static PlayerControl shifter;
+ public static Color color = new Color(90f / 255f, 90f / 255f, 90f / 255f, 1);
+
+ public static float cooldown = float.MaxValue;
+
+ public static PlayerControl currentTarget;
+
+ private static Sprite buttonSprite;
+ public static Sprite getButtonSprite() {
+ if (buttonSprite) return buttonSprite;
+ buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.ShiftButton.png", 100f);
+ return buttonSprite;
+ }
+
+ public static void clearAndReload() {
+ shifter = null;
+ currentTarget = null;
+ cooldown = TheOtherRolesPlugin.shifterCooldown.GetValue();
+ }
+ }
+
+ public static class Swapper {
+ public static PlayerControl swapper;
+ public static Color color = new Color(240f / 255f, 128f / 255f, 72f / 255f, 1);
+ private static Sprite spriteCheck;
+
+ public static byte playerId1 = Byte.MaxValue;
+ public static byte playerId2 = Byte.MaxValue;
+
+ public static Sprite getCheckSprite() {
+ if (spriteCheck) return spriteCheck;
+ spriteCheck = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.SwapperCheck.png", 150f);
+ return spriteCheck;
+ }
+
+ public static void clearAndReload() {
+ swapper = null;
+ playerId1 = Byte.MaxValue;
+ playerId2 = Byte.MaxValue;
+ }
+ }
+
+ public static class Lovers {
+ public static PlayerControl lover1;
+ public static PlayerControl lover2;
+ public static Color color = new Color(252f / 255f, 3f / 255f, 190f / 255f, 1);
+
+ public static bool bothDie = true;
+ // Lovers save if next to be exiled is a lover, because RPC of ending game comes before RPC of exiled
+ public static bool notAckedExiledIsLover = false;
+
+ public static bool existingAndAlive() {
+ return lover1 != null && lover2 != null && !lover1.Data.IsDead && !lover2.Data.IsDead && !notAckedExiledIsLover; // ADD NOT ACKED IS LOVER
+ }
+
+ public static bool existingWithImpLover() {
+ return lover1 != null && lover2 != null && (lover1.Data.IsImpostor || lover2.Data.IsImpostor);
+ }
+
+ public static void clearAndReload() {
+ lover1 = null;
+ lover2 = null;
+ notAckedExiledIsLover = false;
+ bothDie = TheOtherRolesPlugin.loversBothDie.GetValue();
+ }
+ }
+
+ public static class Seer {
+ public static PlayerControl seer;
+ public static Color color = new Color(60f / 255f, 181f / 255f, 100f / 255f, 1);
+ public static Dictionary<PlayerControl, PlayerControl> revealedPlayers = new Dictionary<PlayerControl, PlayerControl>();
+
+ public static float cooldown = float.MaxValue;
+ public static int kindOfInfo = 0;
+ public static int playersWithNotification = 0;
+ public static float chanceOfSeeingRight = 100;
+
+ public static PlayerControl currentTarget;
+
+ private static Sprite buttonSprite;
+ public static Sprite getButtonSprite() {
+ if (buttonSprite) return buttonSprite;
+ buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.SeerButton.png", 100f);
+ return buttonSprite;
+ }
+
+ public static void clearAndReload() {
+ seer = null;
+ revealedPlayers = new Dictionary<PlayerControl, PlayerControl>();
+ cooldown = TheOtherRolesPlugin.seerCooldown.GetValue();
+ kindOfInfo = TheOtherRolesPlugin.seerKindOfInfo.GetValue();
+ playersWithNotification = TheOtherRolesPlugin.seerPlayersWithNotification.GetValue();
+ chanceOfSeeingRight = TheOtherRolesPlugin.seerChanceOfSeeingRight.GetValue();
+ }
+ }
+
+ public static class Morphling {
+ public static PlayerControl morphling;
+ public static Color color = Palette.ImpostorRed;
+ private static Sprite sampleSprite;
+ private static Sprite morphSprite;
+
+ public static float cooldown = float.MaxValue;
+
+ public static PlayerControl currentTarget;
+ public static PlayerControl sampledTarget;
+ public static PlayerControl morphTarget;
+ public static float morphTimer = 0f;
+
+
+ public static void clearAndReload() {
+ morphling = null;
+ currentTarget = null;
+ sampledTarget = null;
+ morphTarget = null;
+ morphTimer = 0f;
+ cooldown = TheOtherRolesPlugin.morphlingCooldown.GetValue();
+ }
+
+ public static Sprite getSampleSprite() {
+ if (sampleSprite) return sampleSprite;
+ sampleSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.SampleButton.png", 100f);
+ return sampleSprite;
+ }
+
+ public static Sprite getMorphSprite() {
+ if (morphSprite) return morphSprite;
+ morphSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.MorphButton.png", 100f);
+ return morphSprite;
+ }
+ }
+
+ public static class Camouflager {
+ public static PlayerControl camouflager;
+ public static Color color = Palette.ImpostorRed;
+
+ public static float cooldown = float.MaxValue;
+ public static float camouflageTimer = 0f;
+
+ private static Sprite buttonSprite;
+ public static Sprite getButtonSprite() {
+ if (buttonSprite) return buttonSprite;
+ buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.CamoButton.png", 100f);
+ return buttonSprite;
+ }
+
+ public static void clearAndReload() {
+ camouflager = null;
+ camouflageTimer = 0f;
+ cooldown = TheOtherRolesPlugin.camouflagerCooldown.GetValue();
+ }
+ }
+
+ public static class Spy {
+ public static PlayerControl spy;
+ private static Sprite adminTableIcon;
+ public static Color color = new Color(252f / 255f, 90f / 255f, 30f / 255f, 1);
+
+ public static float cooldown = float.MaxValue;
+ public static float duration = 10f;
+
+ public static float spyTimer = 0f;
+
+ public static Sprite getAdminTableIconSprite() {
+ if (adminTableIcon) return adminTableIcon;
+ adminTableIcon = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.AdminTableIcon.png", 350f);
+ return adminTableIcon;
+ }
+
+ private static Sprite buttonSprite;
+ public static Sprite getButtonSprite() {
+ if (buttonSprite) return buttonSprite;
+ buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.SpyButton.png", 100f);
+ return buttonSprite;
+ }
+
+ public static void clearAndReload() {
+ spy = null;
+ spyTimer = 0f;
+ cooldown = TheOtherRolesPlugin.spyCooldown.GetValue();
+ duration = TheOtherRolesPlugin.spySpyingDuration.GetValue();
+ }
+ }
+
+ public static class Child {
+ public static PlayerControl child;
+ public static Color color = Color.white;
+
+ public static float growingUpDuration = float.MaxValue;
+ public static DateTime timeOfGrowthStart = DateTime.UtcNow;
+
+ public static void clearAndReload() {
+ child = null;
+ growingUpDuration = TheOtherRolesPlugin.childGrowingUpDuration.GetValue();
+ timeOfGrowthStart = DateTime.UtcNow;
+ }
+
+ public static float growingProgress() {
+ if (timeOfGrowthStart == null) return 0f;
+
+ float timeSinceStart = (float)(DateTime.UtcNow - timeOfGrowthStart).TotalMilliseconds;
+ return Mathf.Clamp(timeSinceStart/(growingUpDuration*1000), 0f, 1f);
+ }
+
+ public static bool isGrownUp() {
+ return growingProgress() == 1f;
+ }
+ }
+
+ public static class BountyHunter {
+ public static PlayerControl bountyHunter;
+ public static Color color = new Color(237f / 255f, 101f / 255f, 59f / 255f, 1);
+
+ public static bool notifyBounty = true;
+ public static PlayerControl target;
+
+ public static void clearAndReload() {
+ bountyHunter = null;
+ target = null;
+ // notifyBounty = TheOtherRolesPlugin.bountyHunterNotifyBounty.GetValue();
+ }
+ }
+
+ public static class Tracker {
+ public static PlayerControl tracker;
+ public static Color color = new Color(117f / 255f, 209f / 255f, 255f / 255f, 1);
+
+ public static float updateIntervall = 5f;
+
+ public static PlayerControl currentTarget;
+ public static PlayerControl tracked;
+ public static bool usedTracker = false;
+ public static float timeUntilUpdate = 0f;
+ public static Arrow arrow = new Arrow(Color.blue);
+
+ private static Sprite buttonSprite;
+ public static Sprite getButtonSprite() {
+ if (buttonSprite) return buttonSprite;
+ buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.TrackerButton.png", 100f);
+ return buttonSprite;
+ }
+
+ public static void clearAndReload() {
+ tracker = null;
+ currentTarget = null;
+ tracked = null;
+ usedTracker = false;
+ timeUntilUpdate = 0f;
+ updateIntervall = TheOtherRolesPlugin.trackerUpdateIntervall.GetValue();
+ arrow = new Arrow(Color.blue);
+ if (arrow.arrow != null) arrow.arrow.SetActive(false);
+ }
+ }
+
+ public static class Vampire {
+ public static PlayerControl vampire;
+ public static Color color = Palette.ImpostorRed;
+
+ public static float delay = 10f;
+ public static bool localPlacedGarlic = false;
+ public static bool garlicsActive = true;
+
+ public static PlayerControl currentTarget;
+ public static PlayerControl bitten;
+ public static bool targetNearGarlic = false;
+
+ private static Sprite buttonSprite;
+ public static Sprite getButtonSprite() {
+ if (buttonSprite) return buttonSprite;
+ buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.VampireButton.png", 100f);
+ return buttonSprite;
+ }
+
+ private static Sprite garlicButtonSprite;
+ public static Sprite getGarlicButtonSprite() {
+ if (garlicButtonSprite) return garlicButtonSprite;
+ garlicButtonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.GarlicButton.png", 100f);
+ return garlicButtonSprite;
+ }
+
+ public static IEnumerator killWithDelay() {
+ yield return new WaitForSeconds(delay);
+ MessageWriter killWriter = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.VampireTryKill, Hazel.SendOption.None, -1);
+ AmongUsClient.Instance.FinishRpcImmediately(killWriter);
+ RPCProcedure.vampireTryKill();
+ }
+
+ public static void clearAndReload() {
+ vampire = null;
+ bitten = null;
+ targetNearGarlic = false;
+ localPlacedGarlic = false;
+ currentTarget = null;
+ garlicsActive = TheOtherRolesPlugin.vampireSpawnRate.GetValue() > 0;
+ delay = TheOtherRolesPlugin.vampireKillDelay.GetValue();
+ }
+ }
+
+ public static class Snitch {
+ public static PlayerControl snitch;
+ public static Color color = new Color(227f / 255f, 251f / 255f, 47f / 255f, 1);
+
+ public static List<Arrow> localArrows = new List<Arrow>();
+ public static int taskCountForImpostors = 1;
+
+ public static void clearAndReload() {
+ localArrows = new List<Arrow>();
+ taskCountForImpostors = Mathf.RoundToInt(TheOtherRolesPlugin.snitchLeftTasksForImpostors.GetValue());
+ snitch = null;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <TargetFramework>netstandard2.1</TargetFramework>
+ <Version>1.0.0</Version>
+ <Mappings>NuclearPowered/Mappings:0.2.0</Mappings>
+
+ <Description>TheOtherRoles</Description>
+ <Authors>Eibison</Authors>
+ </PropertyGroup>
+
+ <PropertyGroup Condition="'$(GamePlatform)' == 'Steam'">
+ <GameVersion>2021.3.5s</GameVersion>
+ <DefineConstants>$(DefineConstants);STEAM</DefineConstants>
+ </PropertyGroup>
+
+ <PropertyGroup Condition="'$(GamePlatform)' == 'Itch'">
+ <GameVersion>2021.3.5i</GameVersion>
+ <DefineConstants>$(DefineConstants);ITCH</DefineConstants>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Deobfuscate Include="$(AmongUs)\BepInEx\plugins\Reactor-$(GameVersion).dll" />
+
+ <PackageReference Include="Reactor.OxygenFilter.MSBuild" Version="0.2.9" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <Reference Include="Essentials">
+ <HintPath>$(AmongUs)\BepInEx\plugins\Essentials-$(GameVersion).dll</HintPath>
+ </Reference>
+ </ItemGroup>
+
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\RepairButton.png"/>
+ <EmbeddedResource Include="Resources\CleanButton.png"/>
+ <EmbeddedResource Include="Resources\RewindButton.png"/>
+ <EmbeddedResource Include="Resources\ShieldButton.png"/>
+ <EmbeddedResource Include="Resources\ShiftButton.png"/>
+ <EmbeddedResource Include="Resources\SeerButton.png"/>
+ <EmbeddedResource Include="Resources\MorphButton.png"/>
+ <EmbeddedResource Include="Resources\SampleButton.png"/>
+ <EmbeddedResource Include="Resources\CamoButton.png"/>
+ <EmbeddedResource Include="Resources\SpyButton.png"/>
+ <EmbeddedResource Include="Resources\TrackerButton.png"/>
+ <EmbeddedResource Include="Resources\VampireButton.png"/>
+ <EmbeddedResource Include="Resources\GarlicButton.png"/>
+ <EmbeddedResource Include="Resources\Arrow.png"/>
+ <EmbeddedResource Include="Resources\Garlic.png"/>
+ <EmbeddedResource Include="Resources\GarlicBackground.png"/>
+ <EmbeddedResource Include="Resources\Footprint.png"/>
+ <EmbeddedResource Include="Resources\AdminTableIcon.png"/>
+ <EmbeddedResource Include="Resources\SwapperCheck.png"/>
+ </ItemGroup>
+
+ <Target Name="Copy" AfterTargets="Reobfuscate">
+ <Copy SourceFiles="$(OutputPath)reobfuscated/$(AssemblyName)-$(GameVersion).dll" DestinationFolder="$(AmongUs)/BepInEx/plugins/" Condition="'$(Configuration)' == 'Debug'" />
+ </Target>
+</Project>
\ No newline at end of file
using System.IO;
using System.Net.Http;
using UnityEngine;
-using static BonusRoles.BonusRoles;
+using static TheOtherRoles.TheOtherRoles;
using Reactor.Extensions;
using System.Collections.Generic;
using System.Linq;
-namespace BonusRoles
+namespace TheOtherRoles
{
[HarmonyPatch(typeof(HudManager), nameof(HudManager.Update))]
class HudManagerUpdatePatch
setPlayerNameColor(Seer.seer, Seer.color);
else if (Spy.spy != null && Spy.spy == PlayerControl.LocalPlayer)
setPlayerNameColor(Spy.spy, Spy.color);
+ else if (BountyHunter.bountyHunter != null && BountyHunter.target != null && BountyHunter.bountyHunter == PlayerControl.LocalPlayer) {
+ setPlayerNameColor(BountyHunter.bountyHunter, BountyHunter.color);
+ setPlayerNameColor(BountyHunter.target, BountyHunter.color);
+ }
+ else if (Tracker.tracker != null && Tracker.tracker == PlayerControl.LocalPlayer)
+ setPlayerNameColor(Tracker.tracker, Tracker.color);
+ else if (Snitch.snitch != null && Snitch.snitch == PlayerControl.LocalPlayer)
+ setPlayerNameColor(Snitch.snitch, Snitch.color);
// Crewmate roles with no changes: Child
- // Impostor roles with no changes: Morphling, Camouflager, Godfather, Janitor and Mafioso
+ // Impostor roles with no changes: Morphling, Camouflager, Vampire, Godfather, Janitor and Mafioso
}
static void setMafiaNameTags() {
}
}
+ public static void bountyHunterUpdate() {
+ if (BountyHunter.bountyHunter == null || BountyHunter.target == null) return;
+
+ if (BountyHunter.notifyBounty && PlayerControl.LocalPlayer == BountyHunter.target) {
+ string suffix = "[AD653BFF] (Bounty)[FFFFFFFF]";
+ PlayerControl.LocalPlayer.nameText.Text += suffix;
+ if (MeetingHud.Instance != null)
+ foreach (PlayerVoteArea player in MeetingHud.Instance.playerStates)
+ if (player.NameText != null && PlayerControl.LocalPlayer.PlayerId == player.TargetPlayerId)
+ player.NameText.Text += suffix;
+ }
+ }
+
+ static void vampireDeactivateKillButton(HudManager __instance) {
+ if (Vampire.vampire != null && Vampire.vampire == PlayerControl.LocalPlayer) {
+ __instance.KillButton.gameObject.SetActive(false);
+ __instance.KillButton.renderer.enabled = false;
+ __instance.KillButton.isActive = false;
+ __instance.KillButton.enabled = false;
+ }
+ }
+
+ static void snitchUpdate() {
+ if (Snitch.snitch == null) return;
+
+ foreach (Arrow arrow in Snitch.localArrows) arrow.arrow.SetActive(false);
+ if (Snitch.snitch.Data.IsDead) return;
+
+ int numberOfTasks = 0;
+ foreach (PlayerTask t in Snitch.snitch.myTasks) {
+ if (t.TaskType != TaskTypes.FixComms && t.TaskType != TaskTypes.FixLights && t.TaskType != TaskTypes.ResetReactor && t.TaskType != TaskTypes.ResetSeismic && t.TaskType != TaskTypes.RestoreOxy)
+ if (!t.IsComplete) numberOfTasks++;
+ }
+
+ if (PlayerControl.LocalPlayer.Data.IsImpostor && numberOfTasks <= Snitch.taskCountForImpostors) {
+ if (Snitch.localArrows.Count == 0) Snitch.localArrows.Add(new Arrow(Color.blue));
+ if (Snitch.localArrows.Count != 0 && Snitch.localArrows[0] != null) {
+ Snitch.localArrows[0].arrow.SetActive(true);
+ Snitch.localArrows[0].Update(Snitch.snitch.transform.position);
+ }
+ } else if (PlayerControl.LocalPlayer == Snitch.snitch && numberOfTasks == 0) {
+ int arrowIndex = 0;
+ foreach (PlayerControl p in PlayerControl.AllPlayerControls) {
+ if (p.Data.IsImpostor && !p.Data.IsDead) {
+ if (arrowIndex >= Snitch.localArrows.Count) Snitch.localArrows.Add(new Arrow(Color.blue));
+ if (arrowIndex < Snitch.localArrows.Count && Snitch.localArrows[arrowIndex] != null) {
+ Snitch.localArrows[arrowIndex].arrow.SetActive(true);
+ Snitch.localArrows[arrowIndex].Update(p.transform.position);
+ }
+ arrowIndex++;
+ }
+ }
+ }
+ }
+
static void Postfix(HudManager __instance)
{
if (AmongUsClient.Instance.GameState != InnerNet.InnerNetClient.GameStates.Started) return;
seerUpdate();
// Spy update();
spyUpdate();
-
+ // Camouflager and Morphling
camouflageAndMorphActions();
+ // Child
childUpdate();
+ // Bounty Hunter
+ bountyHunterUpdate();
+ // Vampire
+ vampireDeactivateKillButton(__instance);
+ // Snitch
+ snitchUpdate();
}
}
}
\ No newline at end of file
using System.Net.Http;
using UnityEngine;
using System.Linq;
-using static BonusRoles.BonusRoles;
-using static BonusRoles.GameHistory;
+using static TheOtherRoles.TheOtherRoles;
+using static TheOtherRoles.GameHistory;
using Reactor.Extensions;
using System.Collections.Generic;
-namespace BonusRoles
+namespace TheOtherRoles
{
[HarmonyPatch(typeof(Vent), "CanUse")]