From: Mallöris <|||||@||.||> Date: Mon, 11 Jul 2022 16:43:16 +0000 (+0200) Subject: Update 4.1.6 X-Git-Url: https://git.deb.at/?a=commitdiff_plain;h=5829cb380e670f8e3ed0d9bd14eb9544ff6b5b10;p=rhonda%2Ftheotherroles.git Update 4.1.6 --- diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..945b5f9 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,38 @@ +name: AutoBuild .NET + +on: + push: + branches: + - main + +jobs: + build: + runs-on: ubuntu-20.04 + + steps: + - uses: actions/cache@v2 + with: + path: | + ~/.nuget/packages + ~/.cache/bepinex + key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }} + restore-keys: | + ${{ runner.os }}-nuget- + + - uses: actions/checkout@v2 + with: + submodules: true + + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 6.x + + - name: Build + run: dotnet build TheOtherRoles/TheOtherRoles.csproj --configuration Release + + - name: Upload TheOtherRoles + uses: actions/upload-artifact@v2 + with: + name: TheOtherRoles.dll + path: TheOtherRoles/bin/Release/netstandard2.1/TheOtherRoles.dll \ No newline at end of file diff --git a/README.md b/README.md index 1df8c68..94c9e58 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ The [Role Assignment](#role-assignment) sections explains how the roles are bein # Releases | Among Us - Version| Mod Version | Link | |----------|-------------|-----------------| +| 2022.6.21| v4.1.6| [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v4.1.6/TheOtherRoles.zip) | 2022.6.21| v4.1.5| [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v4.1.5/TheOtherRoles.zip) | 2022.3.29| v4.1.4| [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v4.1.4/TheOtherRoles.zip) | 2022.3.29| v4.1.3| [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v4.1.3/TheOtherRoles.zip) @@ -107,6 +108,24 @@ The [Role Assignment](#role-assignment) sections explains how the roles are bein
Click to show the Changelog +**Version 4.1.6** +- Added Sound Effects: Most buttons / role funcionalities now have a sound! +- Added a mod option: Enable Sound Effects +- Added an option: Hide After Death Modifiers: Modifiers which will have an effect after your death will be hidden while the player is alive so they cant be claimed / called +- Added lobby timer sync, so that each player can see when the lobby will close on Vanilla Servers +- Added a credits screen to the main menu +- Re-Added the player's last position to the map in meetings +- Changed the custom region ui +- Fixed a bug where the Spy's Name appearing in white to the impostors in the intro cutscene +- Fixed a bug where the zoom function for ghosts would zoom in too far +- Fixed a bug where custom color names did not work (TOR is now compatible with colorblind mode) +- Fixed a bug where the ninjas color name did not become invisible in colorblind mode +- Fixed a bug where Morphling & Camouflager did not work correctly for skins with adaptive color +- Fixed a bug where the first kill shield was given to the wrong lover +- Fixed a bug where Pursuer appeared in the GuesserUI even when Lawyer was disabled +- Fixed a bug where a guessed Guesser could still guess if they had the guesser ui open +- Fixed a bug where the role assignment did not work properly (fingers crossed) + **Version 4.1.5** - Updated to Among Us version 2022.6.21 - Added Custom servers (Modded EU & Modded NA). Thanks to [miniduikboot](https://github.com/miniduikboot) & GD @@ -1219,12 +1238,12 @@ Because of the vents the Engineer might not be able to start some tasks using th ## Sheriff ### **Team: Crewmates** -The Sheriff has the ability to kill Impostors.\ +The Sheriff has the ability to kill Impostors or Neutral roles if enabled.\ If they try to kill a Crewmate, they die instead.\ \ **NOTE:** - If the Sheriff shoots the person the Medic shielded, the Sheriff and the shielded person **both remain unharmed**. -- If the Sheriff shoots a Mini Impostor, the Sheriff dies if the Mini is still growing up. If it's 18, the Mini Impostor dies. +- If the Sheriff shoots a Mini Impostor while growing up, nothing happens. If it's fully grown, the Mini Impostor dies. ### Game Options | Name | Description | diff --git a/TheOtherRoles.sln b/TheOtherRoles.sln index 3de367d..3c00efe 100644 --- a/TheOtherRoles.sln +++ b/TheOtherRoles.sln @@ -2,6 +2,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TheOtherRoles", "TheOtherRoles\TheOtherRoles.csproj", "{11FBC798-BAF5-4EE5-9511-BE6DB0592F99}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TheOtherUpdater", "TheOtherUpdater\TheOtherUpdater.vcxproj", "{73A5662B-9C59-4C97-95C5-F5B2A8BBDDCA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -12,5 +14,9 @@ Global {11FBC798-BAF5-4EE5-9511-BE6DB0592F99}.Debug|Any CPU.Build.0 = Debug|Any CPU {11FBC798-BAF5-4EE5-9511-BE6DB0592F99}.Release|Any CPU.ActiveCfg = Release|Any CPU {11FBC798-BAF5-4EE5-9511-BE6DB0592F99}.Release|Any CPU.Build.0 = Release|Any CPU + {73A5662B-9C59-4C97-95C5-F5B2A8BBDDCA}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {73A5662B-9C59-4C97-95C5-F5B2A8BBDDCA}.Debug|Any CPU.Build.0 = Debug|Win32 + {73A5662B-9C59-4C97-95C5-F5B2A8BBDDCA}.Release|Any CPU.ActiveCfg = Release|Win32 + {73A5662B-9C59-4C97-95C5-F5B2A8BBDDCA}.Release|Any CPU.Build.0 = Release|Win32 EndGlobalSection EndGlobal diff --git a/TheOtherRoles/Buttons.cs b/TheOtherRoles/Buttons.cs index e47eb88..26ee68c 100644 --- a/TheOtherRoles/Buttons.cs +++ b/TheOtherRoles/Buttons.cs @@ -53,8 +53,6 @@ namespace TheOtherRoles public static CustomButton zoomOutButton; public static Dictionary> deputyHandcuffedButtons = null; - - public static bool zoomOutStatus = false; public static PoolablePlayer morphTargetDisplay; public static TMPro.TMP_Text securityGuardButtonScrewsText; @@ -125,6 +123,7 @@ namespace TheOtherRoles timeMasterShieldButton.Timer = timeMasterShieldButton.MaxTimer; timeMasterShieldButton.isEffectActive = false; timeMasterShieldButton.actionButton.cooldownTimerText.color = Palette.EnabledColor; + SoundEffectsManager.stop("timemasterShield"); } private static void addReplacementHandcuffedButton(CustomButton button, Vector3? positionOffset = null, Func couldUse = null) @@ -203,7 +202,7 @@ namespace TheOtherRoles MessageWriter usedRepairWriter = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.EngineerUsedRepair, Hazel.SendOption.Reliable, -1); AmongUsClient.Instance.FinishRpcImmediately(usedRepairWriter); RPCProcedure.engineerUsedRepair(); - + SoundEffectsManager.play("engineerRepair"); foreach (PlayerTask task in CachedPlayer.LocalPlayer.PlayerControl.myTasks.GetFastEnumerator()) { if (task.TaskType == TaskTypes.FixLights) { MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.EngineerFixLights, Hazel.SendOption.Reliable, -1); @@ -266,6 +265,7 @@ namespace TheOtherRoles AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.cleanBody(playerInfo.PlayerId); janitorCleanButton.Timer = janitorCleanButton.MaxTimer; + SoundEffectsManager.play("cleanerClean"); break; } @@ -332,6 +332,8 @@ namespace TheOtherRoles RPCProcedure.deputyUsedHandcuffs(targetId); Deputy.currentTarget = null; deputyHandcuffButton.Timer = deputyHandcuffButton.MaxTimer; + + SoundEffectsManager.play("deputyHandcuff"); }, () => { return (Deputy.deputy != null && Deputy.deputy == CachedPlayer.LocalPlayer.PlayerControl || Sheriff.sheriff != null && Sheriff.sheriff == CachedPlayer.LocalPlayer.PlayerControl && Sheriff.sheriff == Sheriff.formerDeputy && Deputy.keepsHandcuffsOnPromotion) && !CachedPlayer.LocalPlayer.Data.IsDead; }, () => { @@ -357,6 +359,7 @@ namespace TheOtherRoles MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.TimeMasterShield, Hazel.SendOption.Reliable, -1); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.timeMasterShield(); + SoundEffectsManager.play("timemasterShield"); }, () => { return TimeMaster.timeMaster != null && TimeMaster.timeMaster == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead; }, () => { return CachedPlayer.LocalPlayer.PlayerControl.CanMove; }, @@ -371,7 +374,11 @@ namespace TheOtherRoles KeyCode.F, true, TimeMaster.shieldDuration, - () => { timeMasterShieldButton.Timer = timeMasterShieldButton.MaxTimer; } + () => { + timeMasterShieldButton.Timer = timeMasterShieldButton.MaxTimer; + SoundEffectsManager.stop("timemasterShield"); + + } ); // Medic Shield @@ -387,6 +394,8 @@ namespace TheOtherRoles else RPCProcedure.medicSetShielded(Medic.currentTarget.PlayerId); Medic.meetingAfterShielding = false; + + SoundEffectsManager.play("medicShield"); }, () => { return Medic.medic != null && Medic.medic == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead; }, () => { return !Medic.usedShield && Medic.currentTarget && CachedPlayer.LocalPlayer.PlayerControl.CanMove; }, @@ -405,6 +414,7 @@ namespace TheOtherRoles writer.Write(Shifter.currentTarget.PlayerId); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.setFutureShifted(Shifter.currentTarget.PlayerId); + SoundEffectsManager.play("shifterShift"); }, () => { return Shifter.shifter != null && Shifter.shifter == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead; }, () => { return Shifter.currentTarget && Shifter.futureShift == null && CachedPlayer.LocalPlayer.PlayerControl.CanMove; }, @@ -426,11 +436,12 @@ namespace TheOtherRoles RPCProcedure.morphlingMorph(Morphling.sampledTarget.PlayerId); Morphling.sampledTarget = null; morphlingButton.EffectDuration = Morphling.duration; - + SoundEffectsManager.play("morphlingMorph"); } else if (Morphling.currentTarget != null) { Morphling.sampledTarget = Morphling.currentTarget; morphlingButton.Sprite = Morphling.getMorphSprite(); morphlingButton.EffectDuration = 1f; + SoundEffectsManager.play("morphlingSample"); // Add poolable player to the button so that the target outfit is shown morphlingButton.actionButton.cooldownTimerText.transform.localPosition = new Vector3(0, 0, -1f); // Before the poolable player @@ -471,6 +482,7 @@ namespace TheOtherRoles if (Morphling.sampledTarget == null) { morphlingButton.Timer = morphlingButton.MaxTimer; morphlingButton.Sprite = Morphling.getSampleSprite(); + SoundEffectsManager.play("morphlingMorph"); // Reset the poolable player morphTargetDisplay.gameObject.SetActive(false); @@ -486,6 +498,7 @@ namespace TheOtherRoles MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.CamouflagerCamouflage, Hazel.SendOption.Reliable, -1); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.camouflagerCamouflage(); + SoundEffectsManager.play("morphlingMorph"); }, () => { return Camouflager.camouflager != null && Camouflager.camouflager == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead; }, () => { return CachedPlayer.LocalPlayer.PlayerControl.CanMove; }, @@ -500,13 +513,17 @@ namespace TheOtherRoles KeyCode.F, true, Camouflager.duration, - () => { camouflagerButton.Timer = camouflagerButton.MaxTimer; } + () => { + camouflagerButton.Timer = camouflagerButton.MaxTimer; + SoundEffectsManager.play("morphlingMorph"); + } ); // Hacker button hackerButton = new CustomButton( () => { Hacker.hackerTimer = Hacker.duration; + SoundEffectsManager.play("hackerHack"); }, () => { return Hacker.hacker != null && Hacker.hacker == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead; }, () => { return true; }, @@ -636,6 +653,7 @@ namespace TheOtherRoles writer.Write(Tracker.currentTarget.PlayerId); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.trackerUsedTracker(Tracker.currentTarget.PlayerId); + SoundEffectsManager.play("trackerTrackPlayer"); }, () => { return Tracker.tracker != null && Tracker.tracker == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead; }, () => { return CachedPlayer.LocalPlayer.PlayerControl.CanMove && Tracker.currentTarget != null && !Tracker.usedTracker; }, @@ -647,7 +665,8 @@ namespace TheOtherRoles ); trackerTrackCorpsesButton = new CustomButton( - () => { Tracker.corpsesTrackingTimer = Tracker.corpsesTrackingDuration; }, + () => { Tracker.corpsesTrackingTimer = Tracker.corpsesTrackingDuration; + SoundEffectsManager.play("trackerTrackCorpses"); }, () => { return Tracker.tracker != null && Tracker.tracker == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead && Tracker.canTrackCorpses; }, () => { return CachedPlayer.LocalPlayer.PlayerControl.CanMove; }, () => { @@ -700,6 +719,7 @@ namespace TheOtherRoles RPCProcedure.vampireSetBitten(byte.MaxValue, byte.MaxValue); } }))); + SoundEffectsManager.play("vampireBite"); vampireKillButton.HasEffect = true; // Trigger effect on this click } @@ -749,7 +769,8 @@ namespace TheOtherRoles MessageWriter writer = AmongUsClient.Instance.StartRpc(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.PlaceGarlic, Hazel.SendOption.Reliable); writer.WriteBytesAndSize(buff); writer.EndMessage(); - RPCProcedure.placeGarlic(buff); + RPCProcedure.placeGarlic(buff); + SoundEffectsManager.play("garlic"); }, () => { return !Vampire.localPlacedGarlic && !CachedPlayer.LocalPlayer.Data.IsDead && Vampire.garlicsActive; }, () => { return CachedPlayer.LocalPlayer.PlayerControl.CanMove && !Vampire.localPlacedGarlic; }, @@ -774,6 +795,7 @@ namespace TheOtherRoles writer.WriteBytesAndSize(buff); writer.EndMessage(); RPCProcedure.placePortal(buff); + SoundEffectsManager.play("tricksterPlaceBox"); }, () => { return Portalmaker.portalmaker != null && Portalmaker.portalmaker == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead && Portal.secondPortal == null; }, () => { return CachedPlayer.LocalPlayer.PlayerControl.CanMove && Portal.secondPortal == null; }, @@ -798,6 +820,7 @@ namespace TheOtherRoles } RPCProcedure.usePortal(CachedPlayer.LocalPlayer.PlayerId); usePortalButton.Timer = usePortalButton.MaxTimer; + SoundEffectsManager.play("portalUse"); FastDestroyableSingleton.Instance.StartCoroutine(Effects.Lerp(Portal.teleportDuration, new Action((p) => { // Delayed action CachedPlayer.LocalPlayer.PlayerControl.moveable = false; CachedPlayer.LocalPlayer.NetTransform.Halt(); @@ -830,6 +853,7 @@ namespace TheOtherRoles writer.Write(Jackal.currentTarget.PlayerId); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.jackalCreatesSidekick(Jackal.currentTarget.PlayerId); + SoundEffectsManager.play("jackalSidekick"); }, () => { return Jackal.canCreateSidekick && Jackal.jackal != null && Jackal.jackal == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead; }, () => { return Jackal.canCreateSidekick && Jackal.currentTarget != null && CachedPlayer.LocalPlayer.PlayerControl.CanMove; }, @@ -877,6 +901,7 @@ namespace TheOtherRoles lighterButton = new CustomButton( () => { Lighter.lighterTimer = Lighter.duration; + SoundEffectsManager.play("lighterLight"); }, () => { return Lighter.lighter != null && Lighter.lighter == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead; }, () => { return CachedPlayer.LocalPlayer.PlayerControl.CanMove; }, @@ -891,7 +916,10 @@ namespace TheOtherRoles KeyCode.F, true, Lighter.duration, - () => { lighterButton.Timer = lighterButton.MaxTimer; } + () => { + lighterButton.Timer = lighterButton.MaxTimer; + SoundEffectsManager.play("lighterLight"); + } ); // Eraser erase button @@ -904,6 +932,7 @@ namespace TheOtherRoles writer.Write(Eraser.currentTarget.PlayerId); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.setFutureErased(Eraser.currentTarget.PlayerId); + SoundEffectsManager.play("eraserErase"); }, () => { return Eraser.eraser != null && Eraser.eraser == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead; }, () => { return CachedPlayer.LocalPlayer.PlayerControl.CanMove && Eraser.currentTarget != null; }, @@ -926,7 +955,8 @@ namespace TheOtherRoles MessageWriter writer = AmongUsClient.Instance.StartRpc(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.PlaceJackInTheBox, Hazel.SendOption.Reliable); writer.WriteBytesAndSize(buff); writer.EndMessage(); - RPCProcedure.placeJackInTheBox(buff); + RPCProcedure.placeJackInTheBox(buff); + SoundEffectsManager.play("tricksterPlaceBox"); }, () => { return Trickster.trickster != null && Trickster.trickster == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead && !JackInTheBox.hasJackInTheBoxLimitReached(); }, () => { return CachedPlayer.LocalPlayer.PlayerControl.CanMove && !JackInTheBox.hasJackInTheBoxLimitReached(); }, @@ -941,7 +971,8 @@ namespace TheOtherRoles () => { MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.LightsOut, Hazel.SendOption.Reliable, -1); AmongUsClient.Instance.FinishRpcImmediately(writer); - RPCProcedure.lightsOut(); + RPCProcedure.lightsOut(); + SoundEffectsManager.play("lighterLight"); }, () => { return Trickster.trickster != null && Trickster.trickster == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead && JackInTheBox.hasJackInTheBoxLimitReached() && JackInTheBox.boxesConvertedToVents; }, () => { return CachedPlayer.LocalPlayer.PlayerControl.CanMove && JackInTheBox.hasJackInTheBoxLimitReached() && JackInTheBox.boxesConvertedToVents; }, @@ -956,7 +987,10 @@ namespace TheOtherRoles KeyCode.F, true, Trickster.lightsOutDuration, - () => { lightsOutButton.Timer = lightsOutButton.MaxTimer; } + () => { + lightsOutButton.Timer = lightsOutButton.MaxTimer; + SoundEffectsManager.play("lighterLight"); + } ); // Cleaner Clean @@ -980,6 +1014,7 @@ namespace TheOtherRoles RPCProcedure.cleanBody(playerInfo.PlayerId); Cleaner.cleaner.killTimer = cleanerCleanButton.Timer = cleanerCleanButton.MaxTimer; + SoundEffectsManager.play("cleanerClean"); break; } } @@ -1003,6 +1038,7 @@ namespace TheOtherRoles Warlock.curseVictim = Warlock.currentTarget; warlockCurseButton.Sprite = Warlock.getCurseKillButtonSprite(); warlockCurseButton.Timer = 1f; + SoundEffectsManager.play("warlockCurse"); } else if (Warlock.curseVictim != null && Warlock.curseVictimTarget != null) { MurderAttemptResult murder = Helpers.checkMuderAttemptAndKill(Warlock.warlock, Warlock.curseVictimTarget, showAnimation: false); if (murder == MurderAttemptResult.SuppressKill) return; @@ -1061,6 +1097,7 @@ namespace TheOtherRoles writer.EndMessage(); RPCProcedure.placeCamera(buff); } + SoundEffectsManager.play("securityGuardPlaceCam"); // Same sound used for both types (cam or vent)! securityGuardButton.Timer = securityGuardButton.MaxTimer; }, () => { return SecurityGuard.securityGuard != null && SecurityGuard.securityGuard == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead && SecurityGuard.remainingScrews >= Mathf.Min(SecurityGuard.ventPrice, SecurityGuard.camPrice); }, @@ -1163,7 +1200,8 @@ namespace TheOtherRoles arsonistButton.HasEffect = false; } else if (Arsonist.currentTarget != null) { Arsonist.douseTarget = Arsonist.currentTarget; - arsonistButton.HasEffect = true; + arsonistButton.HasEffect = true; + SoundEffectsManager.play("arsonistDouse"); } }, () => { return Arsonist.arsonist != null && Arsonist.arsonist == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead; }, @@ -1222,6 +1260,7 @@ namespace TheOtherRoles Vulture.cooldown = vultureEatButton.Timer = vultureEatButton.MaxTimer; Vulture.eatenBodies++; + SoundEffectsManager.play("vultureEat"); break; } } @@ -1249,6 +1288,7 @@ namespace TheOtherRoles if (Medium.target != null) { Medium.soulTarget = Medium.target; mediumButton.HasEffect = true; + SoundEffectsManager.play("mediumAsk"); } }, () => { return Medium.medium != null && Medium.medium == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead; }, @@ -1321,6 +1361,7 @@ namespace TheOtherRoles Medium.souls.Remove(target); } + SoundEffectsManager.stop("mediumAsk"); } ); @@ -1338,6 +1379,7 @@ namespace TheOtherRoles Pursuer.blanks++; pursuerButton.Timer = pursuerButton.MaxTimer; + SoundEffectsManager.play("pursuerBlank"); } }, @@ -1367,6 +1409,7 @@ namespace TheOtherRoles () => { if (Witch.currentTarget != null) { Witch.spellCastingTarget = Witch.currentTarget; + SoundEffectsManager.play("witchSpell"); } }, () => { return Witch.witch != null && Witch.witch == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead; }, @@ -1473,6 +1516,7 @@ namespace TheOtherRoles if (Ninja.currentTarget != null) { Ninja.ninjaMarked = Ninja.currentTarget; ninjaButton.Timer = 5f; + SoundEffectsManager.play("warlockCurse"); } }, () => { return Ninja.ninja != null && Ninja.ninja == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead; }, diff --git a/TheOtherRoles/CustomOptionHolder.cs b/TheOtherRoles/CustomOptionHolder.cs index 6571201..5cb322f 100644 --- a/TheOtherRoles/CustomOptionHolder.cs +++ b/TheOtherRoles/CustomOptionHolder.cs @@ -225,6 +225,8 @@ namespace TheOtherRoles { public static CustomOption pursuerCooldown; public static CustomOption pursuerBlanksNumber; + public static CustomOption modifiersAreHidden; + public static CustomOption modifierBait; public static CustomOption modifierBaitQuantity; public static CustomOption modifierBaitReportDelayMin; @@ -510,6 +512,8 @@ namespace TheOtherRoles { mediumOneTimeUse = CustomOption.Create(363, Types.Crewmate, "Each Soul Can Only Be Questioned Once", false, mediumSpawnRate); // Modifier + modifiersAreHidden = CustomOption.Create(1009, Types.Modifier, cs(Color.yellow, "Hide After Death Modifiers"), true, null, true); + modifierBloody = CustomOption.Create(1000, Types.Modifier, cs(Color.yellow, "Bloody"), rates, null, true); modifierBloodyQuantity = CustomOption.Create(1001, Types.Modifier, cs(Color.yellow, "Bloody Quantity"), ratesModifier, modifierBloody); modifierBloodyDuration = CustomOption.Create(1002, Types.Modifier, "Trail Duration", 10f, 3f, 60f, 1f, modifierBloody); diff --git a/TheOtherRoles/Helpers.cs b/TheOtherRoles/Helpers.cs index 1f78ae7..8c57aeb 100644 --- a/TheOtherRoles/Helpers.cs +++ b/TheOtherRoles/Helpers.cs @@ -67,6 +67,34 @@ namespace TheOtherRoles { return null; } + public static AudioClip loadAudioClipFromResources(string path, string clipName = "UNNAMED_TOR_AUDIO_CLIP") { + // must be "raw (headerless) 2-channel signed 32 bit pcm (le)" (can e.g. use Audacity® to export) + try { + Assembly assembly = Assembly.GetExecutingAssembly(); + Stream stream = assembly.GetManifestResourceStream(path); + var byteAudio = new byte[stream.Length]; + _ = stream.Read(byteAudio, 0, (int)stream.Length); + float[] samples = new float[byteAudio.Length / 4]; // 4 bytes per sample + int offset; + for (int i = 0; i < samples.Length; i++) { + offset = i * 4; + samples[i] = (float)BitConverter.ToInt32(byteAudio, offset) / Int32.MaxValue; + } + int channels = 2; + int sampleRate = 48000; + AudioClip audioClip = AudioClip.Create(clipName, samples.Length, channels, sampleRate, false); + audioClip.SetData(samples, 0); + return audioClip; + } catch { + System.Console.WriteLine("Error loading AudioClip from resources: " + path); + } + return null; + + /* Usage example: + AudioClip exampleClip = Helpers.loadAudioClipFromResources("TheOtherRoles.Resources.exampleClip.raw"); + if (Constants.ShouldPlaySfx()) SoundManager.Instance.PlaySound(exampleClip, false, 0.8f); + */ + } public static PlayerControl playerById(byte id) { foreach (PlayerControl player in CachedPlayer.AllPlayers) @@ -250,8 +278,8 @@ namespace TheOtherRoles { else clip = nextSkin.IdleAnim; float progress = playerPhysics.Animator.m_animator.GetCurrentAnimatorStateInfo(0).normalizedTime; playerPhysics.myPlayer.cosmetics.skin.skin = nextSkin; - if (playerPhysics.myPlayer.cosmetics.skin.layer.material == FastDestroyableSingleton.Instance.PlayerMaterial) - target.SetPlayerMaterialColors(playerPhysics.myPlayer.cosmetics.skin.layer); + playerPhysics.myPlayer.cosmetics.skin.UpdateMaterial(); + spriteAnim.Play(clip, 1f); spriteAnim.m_animator.Play("a", 0, progress % 1); spriteAnim.m_animator.Update(0f); @@ -330,6 +358,7 @@ namespace TheOtherRoles { MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(killer.NetId, (byte)CustomRPC.ShieldedMurderAttempt, Hazel.SendOption.Reliable, -1); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.shieldedMurderAttempt(); + SoundEffectsManager.play("fail"); return MurderAttemptResult.SuppressKill; } @@ -371,6 +400,7 @@ namespace TheOtherRoles { writer.Write((byte)TheOtherRolesPlugin.Version.Major); writer.Write((byte)TheOtherRolesPlugin.Version.Minor); writer.Write((byte)TheOtherRolesPlugin.Version.Build); + writer.Write(AmongUsClient.Instance.AmHost ? Patches.GameStartManagerPatch.timer : -1f); writer.WritePacked(AmongUsClient.Instance.ClientId); writer.Write((byte)(TheOtherRolesPlugin.Version.Revision < 0 ? 0xFF : TheOtherRolesPlugin.Version.Revision)); writer.Write(Assembly.GetExecutingAssembly().ManifestModule.ModuleVersionId.ToByteArray()); @@ -390,19 +420,19 @@ namespace TheOtherRoles { } + public static bool zoomOutStatus = false; public static void toggleZoom(bool reset=false) { - float zoomFactor = 4f; - if (HudManagerStartPatch.zoomOutStatus) - zoomFactor = 1 / zoomFactor; - else if (reset) return; // Dont zoom out if meant to reset. - HudManagerStartPatch.zoomOutStatus = !HudManagerStartPatch.zoomOutStatus; - Camera.main.orthographicSize *= zoomFactor; + TheOtherRolesPlugin.Logger.LogMessage(Camera.main.orthographicSize); + float orthographicSize = reset || zoomOutStatus ? 3f : 12f; + + zoomOutStatus = !zoomOutStatus && !reset; + Camera.main.orthographicSize = orthographicSize; foreach (var cam in Camera.allCameras) { - if (cam != null && cam.gameObject.name == "UI Camera") cam.orthographicSize *= zoomFactor; // The UI is scaled too, else we cant click the buttons. Downside: map is super small. + if (cam != null && cam.gameObject.name == "UI Camera") cam.orthographicSize = orthographicSize; // The UI is scaled too, else we cant click the buttons. Downside: map is super small. } - HudManagerStartPatch.zoomOutButton.Sprite = HudManagerStartPatch.zoomOutStatus ? Helpers.loadSpriteFromResources("TheOtherRoles.Resources.PlusButton.png", 150f / zoomFactor * 2) : Helpers.loadSpriteFromResources("TheOtherRoles.Resources.MinusButton.png", 150f); - HudManagerStartPatch.zoomOutButton.PositionOffset = HudManagerStartPatch.zoomOutStatus ? new Vector3(0f, 3f, 0) : new Vector3(0.4f, 2.8f, 0); + HudManagerStartPatch.zoomOutButton.Sprite = zoomOutStatus ? Helpers.loadSpriteFromResources("TheOtherRoles.Resources.PlusButton.png", 75f) : Helpers.loadSpriteFromResources("TheOtherRoles.Resources.MinusButton.png", 150f); + HudManagerStartPatch.zoomOutButton.PositionOffset = zoomOutStatus ? new Vector3(0f, 3f, 0) : new Vector3(0.4f, 2.8f, 0); ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height); // This will move button positions to the correct position. } diff --git a/TheOtherRoles/Main.cs b/TheOtherRoles/Main.cs index db449b6..4aad1be 100644 --- a/TheOtherRoles/Main.cs +++ b/TheOtherRoles/Main.cs @@ -23,7 +23,7 @@ namespace TheOtherRoles public class TheOtherRolesPlugin : BasePlugin { public const string Id = "me.eisbison.theotherroles"; - public const string VersionString = "4.1.5"; + public const string VersionString = "4.1.6"; public static Version Version = Version.Parse(VersionString); internal static BepInEx.Logging.ManualLogSource Logger; @@ -40,6 +40,7 @@ namespace TheOtherRoles public static ConfigEntry GhostsSeeVotes{ get; set; } public static ConfigEntry ShowRoleSummary { get; set; } public static ConfigEntry ShowLighterDarker { get; set; } + public static ConfigEntry EnableSoundEffects { get; set; } public static ConfigEntry EnableHorseMode { get; set; } public static ConfigEntry Ip { get; set; } public static ConfigEntry Port { get; set; } @@ -54,9 +55,9 @@ namespace TheOtherRoles public static void UpdateRegions() { ServerManager serverManager = FastDestroyableSingleton.Instance; var regions = new IRegionInfo[] { - new DnsRegionInfo(Ip.Value, "Custom", StringNames.NoTranslation, Ip.Value, Port.Value, false).CastFast(), new DnsRegionInfo("mods.hopto.org", "Modded NA (MNA)", StringNames.NoTranslation, "mods.hopto.org", 443, false).CastFast(), - new DnsRegionInfo("au-eu.duikbo.at", "Modded EU (MEU)", StringNames.NoTranslation, "au-eu.duikbo.at", 22023, false).CastFast() + new DnsRegionInfo("au-eu.duikbo.at", "Modded EU (MEU)", StringNames.NoTranslation, "au-eu.duikbo.at", 22023, false).CastFast(), + new DnsRegionInfo(Ip.Value, "Custom", StringNames.NoTranslation, Ip.Value, Port.Value, false).CastFast() }; IRegionInfo ? currentRegion = serverManager.CurrentRegion; @@ -89,6 +90,7 @@ namespace TheOtherRoles GhostsSeeVotes = Config.Bind("Custom", "Ghosts See Votes", true); ShowRoleSummary = Config.Bind("Custom", "Show Role Summary", true); ShowLighterDarker = Config.Bind("Custom", "Show Lighter / Darker", true); + EnableSoundEffects = Config.Bind("Custom", "Enable Sound Effects", true); EnableHorseMode = Config.Bind("Custom", "Enable Horse Mode", false); ShowPopUpVersion = Config.Bind("Custom", "Show PopUp", "0"); diff --git a/TheOtherRoles/MapOptions.cs b/TheOtherRoles/MapOptions.cs index 06339ba..2ecb05d 100644 --- a/TheOtherRoles/MapOptions.cs +++ b/TheOtherRoles/MapOptions.cs @@ -15,6 +15,7 @@ namespace TheOtherRoles{ public static bool showRoleSummary = true; public static bool allowParallelMedBayScans = false; public static bool showLighterDarker = true; + public static bool enableSoundEffects = true; public static bool enableHorseMode = false; public static bool shieldFirstKill = false; @@ -48,6 +49,7 @@ namespace TheOtherRoles{ ghostsSeeVotes = TheOtherRolesPlugin.GhostsSeeVotes.Value; showRoleSummary = TheOtherRolesPlugin.ShowRoleSummary.Value; showLighterDarker = TheOtherRolesPlugin.ShowLighterDarker.Value; + enableSoundEffects = TheOtherRolesPlugin.EnableSoundEffects.Value; enableHorseMode = TheOtherRolesPlugin.EnableHorseMode.Value; Patches.ShouldAlwaysHorseAround.isHorseMode = TheOtherRolesPlugin.EnableHorseMode.Value; } diff --git a/TheOtherRoles/Modules/CustomColors.cs b/TheOtherRoles/Modules/CustomColors.cs index 11919d6..1c21486 100644 --- a/TheOtherRoles/Modules/CustomColors.cs +++ b/TheOtherRoles/Modules/CustomColors.cs @@ -73,7 +73,7 @@ namespace TheOtherRoles.Modules { color = new Color32(0xDB, 0xFD, 0x2F, byte.MaxValue), shadow = new Color32(0x74, 0xE5, 0x10, byte.MaxValue), isLighterColor = true }); - colors.Add(new CustomColor { longname = "Signal Orange", + colors.Add(new CustomColor { longname = "Signal\nOrange", color = new Color32(0xF7, 0x44, 0x17, byte.MaxValue), shadow = new Color32(0x9B, 0x2E, 0x0F, byte.MaxValue), isLighterColor = true }); @@ -131,6 +131,7 @@ namespace TheOtherRoles.Modules { typeof(Il2CppReferenceArray) })] private class ColorStringPatch { + [HarmonyPriority(Priority.Last)] public static bool Prefix(ref string __result, [HarmonyArgument(0)] StringNames name) { if ((int)name >= 50000) { string text = CustomColors.ColorStrings[(int)name]; diff --git a/TheOtherRoles/Patches/ClientOptionsPatch.cs b/TheOtherRoles/Patches/ClientOptionsPatch.cs index 57ab847..8aa21ed 100644 --- a/TheOtherRoles/Patches/ClientOptionsPatch.cs +++ b/TheOtherRoles/Patches/ClientOptionsPatch.cs @@ -20,6 +20,7 @@ namespace TheOtherRoles.Patches new SelectionBehaviour("Ghosts Can Additionally See Modifier", () => MapOptions.ghostsSeeModifier = TheOtherRolesPlugin.GhostsSeeModifier.Value = !TheOtherRolesPlugin.GhostsSeeModifier.Value, TheOtherRolesPlugin.GhostsSeeModifier.Value), new SelectionBehaviour("Show Role Summary", () => MapOptions.showRoleSummary = TheOtherRolesPlugin.ShowRoleSummary.Value = !TheOtherRolesPlugin.ShowRoleSummary.Value, TheOtherRolesPlugin.ShowRoleSummary.Value), new SelectionBehaviour("Show Lighter / Darker", () => MapOptions.showLighterDarker = TheOtherRolesPlugin.ShowLighterDarker.Value = !TheOtherRolesPlugin.ShowLighterDarker.Value, TheOtherRolesPlugin.ShowLighterDarker.Value), + new SelectionBehaviour("Enable Sound Effects", () => MapOptions.enableSoundEffects = TheOtherRolesPlugin.EnableSoundEffects.Value = !TheOtherRolesPlugin.EnableSoundEffects.Value, TheOtherRolesPlugin.EnableSoundEffects.Value), }; private static GameObject popUp; diff --git a/TheOtherRoles/Patches/CredentialsPatch.cs b/TheOtherRoles/Patches/CredentialsPatch.cs index 7f61b07..4f59346 100644 --- a/TheOtherRoles/Patches/CredentialsPatch.cs +++ b/TheOtherRoles/Patches/CredentialsPatch.cs @@ -18,8 +18,7 @@ $@"Modded by Eisbison, Thunderstorm584 Design by Bavari"; public static string contributorsCredentials = -$@" Special thanks to K3ndo & Smeggy -GitHub Contributors: Gendelo, Alex2911, amsyarasyiq, MaximeGillot, Psynomit, probablyadnf, JustASysAdmin"; +$@" Special thanks to K3ndo & Smeggy"; [HarmonyPatch(typeof(VersionShower), nameof(VersionShower.Start))] private static class VersionShowerPatch diff --git a/TheOtherRoles/Patches/GameStartManagerPatch.cs b/TheOtherRoles/Patches/GameStartManagerPatch.cs index c2e0a54..91e2818 100644 --- a/TheOtherRoles/Patches/GameStartManagerPatch.cs +++ b/TheOtherRoles/Patches/GameStartManagerPatch.cs @@ -11,7 +11,7 @@ using TheOtherRoles.Utilities; namespace TheOtherRoles.Patches { public class GameStartManagerPatch { public static Dictionary playerVersions = new Dictionary(); - private static float timer = 600f; + public static float timer = 600f; private static float kickingTimer = 0f; private static bool versionSent = false; private static string lobbyCodeText = ""; @@ -47,7 +47,7 @@ namespace TheOtherRoles.Patches { private static string currentText = ""; public static void Prefix(GameStartManager __instance) { - if (!AmongUsClient.Instance.AmHost || !GameData.Instance ) return; // Not host or no instance + if (!GameData.Instance ) return; // No instance update = GameData.Instance.PlayerCount != __instance.LastPlayerCount; } @@ -122,7 +122,7 @@ namespace TheOtherRoles.Patches { } // Lobby timer - if (!AmongUsClient.Instance.AmHost || !GameData.Instance) return; // Not host or no instance + if (!GameData.Instance) return; // No instance if (update) currentText = __instance.PlayerCounter.text; diff --git a/TheOtherRoles/Patches/IntroPatch.cs b/TheOtherRoles/Patches/IntroPatch.cs index 4e22ada..bc47d42 100644 --- a/TheOtherRoles/Patches/IntroPatch.cs +++ b/TheOtherRoles/Patches/IntroPatch.cs @@ -55,7 +55,10 @@ namespace TheOtherRoles.Patches { BountyHunter.cooldownText.transform.localPosition = bottomLeft + new Vector3(0f, -1f, -1f); BountyHunter.cooldownText.gameObject.SetActive(true); } - } + } + + // Force Reload of SoundEffectHolder + SoundEffectsManager.Load(); // First kill if (AmongUsClient.Instance.AmHost && MapOptions.shieldFirstKill && MapOptions.firstKillName != "") { @@ -115,6 +118,14 @@ namespace TheOtherRoles.Patches { } + [HarmonyPatch(typeof(IntroCutscene), nameof(IntroCutscene.CreatePlayer))] + class CreatePlayerPatch { + public static void Postfix(IntroCutscene __instance, bool impostorPositioning, ref PoolablePlayer __result) { + if (impostorPositioning) __result.SetNameColor(Palette.ImpostorRed); + } + } + + [HarmonyPatch(typeof(IntroCutscene), nameof(IntroCutscene.ShowRole))] class SetUpRoleTextPatch { static public void SetRoleTexts(IntroCutscene __instance) { diff --git a/TheOtherRoles/Patches/LightSourcePatch.cs b/TheOtherRoles/Patches/LightSourcePatch.cs deleted file mode 100644 index a388421..0000000 --- a/TheOtherRoles/Patches/LightSourcePatch.cs +++ /dev/null @@ -1,15 +0,0 @@ -using HarmonyLib; -using UnityEngine; - - -namespace TheOtherRoles.Patches { - - [HarmonyPatch(typeof(LightSource), nameof(LightSource.Start))] - - class LightSourceStartPatch { - static void Postfix(LightSource __instance) { - __instance.transform.position += Vector3.down * 0.095f; // Fixes Polus Rock / Garbage / Boxes reducing vision to 0 - return; - } - } -} \ No newline at end of file diff --git a/TheOtherRoles/Patches/MainMenuPatch.cs b/TheOtherRoles/Patches/MainMenuPatch.cs index 7418c95..4fbe205 100644 --- a/TheOtherRoles/Patches/MainMenuPatch.cs +++ b/TheOtherRoles/Patches/MainMenuPatch.cs @@ -1,4 +1,6 @@ -using HarmonyLib; +using System; +using System.Collections.Generic; +using HarmonyLib; using UnityEngine; using UnityEngine.UI; using static UnityEngine.UI.Button; @@ -11,6 +13,8 @@ namespace TheOtherRoles.Modules { private static bool horseButtonState = MapOptions.enableHorseMode; private static Sprite horseModeOffSprite = null; private static Sprite horseModeOnSprite = null; + private static GameObject bottomTemplate; + private static AnnouncementPopUp popUp; private static void Prefix(MainMenuManager __instance) { CustomHatLoader.LaunchHatFetcher(); @@ -41,7 +45,7 @@ namespace TheOtherRoles.Modules { // Horse mode stuff var horseModeSelectionBehavior = new ClientOptionsPatch.SelectionBehaviour("Enable Horse Mode", () => MapOptions.enableHorseMode = TheOtherRolesPlugin.EnableHorseMode.Value = !TheOtherRolesPlugin.EnableHorseMode.Value, TheOtherRolesPlugin.EnableHorseMode.Value); - var bottomTemplate = GameObject.Find("InventoryButton"); + bottomTemplate = GameObject.Find("InventoryButton"); if (bottomTemplate == null) return; var horseButton = Object.Instantiate(bottomTemplate, bottomTemplate.transform.parent); var passiveHorseButton = horseButton.GetComponent(); @@ -59,19 +63,83 @@ namespace TheOtherRoles.Modules { if (horseButtonState) { if (horseModeOnSprite == null) horseModeOnSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.HorseModeButtonOn.png", 75f); spriteHorseButton.sprite = horseModeOnSprite; - } - else { + } else { if (horseModeOffSprite == null) horseModeOffSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.HorseModeButtonOff.png", 75f); spriteHorseButton.sprite = horseModeOffSprite; } CredentialsPatch.LogoPatch.updateSprite(); // Avoid wrong Player Particles floating around in the background - var particles = GameObject.FindObjectOfType(); + var particles = GameObject.FindObjectOfType(); if (particles != null) { particles.pool.ReclaimAll(); particles.Start(); } }); + + // TOR credits button + if (bottomTemplate == null) return; + var creditsButton = Object.Instantiate(bottomTemplate, bottomTemplate.transform.parent); + var passiveCreditsButton = creditsButton.GetComponent(); + var spriteCreditsButton = creditsButton.GetComponent(); + + spriteCreditsButton.sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.CreditsButton.png", 75f); + + passiveCreditsButton.OnClick = new ButtonClickedEvent(); + + passiveCreditsButton.OnClick.AddListener((System.Action)delegate { + // do stuff + if (popUp != null) Object.Destroy(popUp); + popUp = Object.Instantiate(Object.FindObjectOfType(true)); + popUp.gameObject.SetActive(true); + popUp.Init(); + //SelectableHyperLinkHelper.DestroyGOs(popUp.selectableHyperLinks, "test"); + string creditsString = @$"Github Contributors: +Gendelo +Alex2911 amsyarasyiq MaximeGillot +Psynomit probablyadnf JustASysAdmin + +"; + creditsString += $@" Other Credits & Resources: +OxygenFilter - For all the version v2.3.0 to v2.6.1, we were using the OxygenFilter for automatic deobfuscation +Reactor - The framework used for all version before v2.0.0 +BepInEx - Used to hook game functions +Essentials - Custom game options by DorCoMaNdO: + +Before v1.6: We used the default Essentials release +v1.6-v1.8: We slightly changed the default Essentials. The changes can be found on this branch of our fork. +v2.0.0 and later: As we're not using Reactor anymore, we are using our own implementation, inspired by the one from DorCoMaNdO +Jackal and Sidekick - Original idea for the Jackal and Sidekick comes from Dhalucard +Among-Us-Love-Couple-Mod - Idea for the Lovers role comes from Woodi-dev +Jester - Idea for the Jester role comes from Maartii +ExtraRolesAmongUs - Idea for the Engineer and Medic role comes from NotHunter101. Also some code snippets come of the implementation were used. +Among-Us-Sheriff-Mod - Idea for the Sheriff role comes from Woodi-dev +TooManyRolesMods - Idea for the Detective and Time Master roles comes from Hardel-DW. Also some code snippets of the implementation were used. +TownOfUs - Idea for the Swapper, Shifter, Arsonist and a similar Mayor role come from Slushiegoose +Ottomated - Idea for the Morphling, Snitch and Camouflager role come from Ottomated +Crowded-Mod - Our implementation for 10+ player lobbies is inspired by the one from the Crowded Mod Team +Goose-Goose-Duck - Idea for the Vulture role come from Slushygoose"; + creditsString += ""; + popUp.AnnounceTextMeshPro.text = creditsString; + __instance.StartCoroutine(Effects.Lerp(0.01f, new Action((p) => { + if (p == 1) { + var titleText = GameObject.Find("Title_Text").GetComponent(); + if (titleText != null) titleText.text = "Credits and Contributors"; + } + }))); + }); + + } + + public static void Postfix(MainMenuManager __instance) { + __instance.StartCoroutine(Effects.Lerp(0.01f, new Action((p) => { + if (p == 1) { + bottomTemplate = GameObject.Find("InventoryButton"); + foreach (Transform tf in bottomTemplate.transform.parent.GetComponentsInChildren()) { + tf.localPosition = new Vector2(tf.localPosition.x * 0.8f, tf.localPosition.y); + } + } + }))); + } } diff --git a/TheOtherRoles/Patches/MapBehaviourPatch.cs b/TheOtherRoles/Patches/MapBehaviourPatch.cs index 70fb5b7..47ac6c6 100644 --- a/TheOtherRoles/Patches/MapBehaviourPatch.cs +++ b/TheOtherRoles/Patches/MapBehaviourPatch.cs @@ -1,11 +1,11 @@ -using HarmonyLib; +using HarmonyLib; using TheOtherRoles.Players; using TheOtherRoles.Utilities; using UnityEngine; namespace TheOtherRoles.Patches { - + [HarmonyPatch(typeof(MapBehaviour))] class MapBehaviourPatch { @@ -15,26 +15,14 @@ namespace TheOtherRoles.Patches { if (!MapUtilities.CachedShipStatus) { return false; } - Vector3 vector = AntiTeleport.position != null? AntiTeleport.position : CachedPlayer.LocalPlayer.transform.position; + Vector3 vector = AntiTeleport.position != null ? AntiTeleport.position : CachedPlayer.LocalPlayer.transform.position; vector /= MapUtilities.CachedShipStatus.MapScale; vector.x *= Mathf.Sign(MapUtilities.CachedShipStatus.transform.localScale.x); vector.z = -1f; __instance.HerePoint.transform.localPosition = vector; CachedPlayer.LocalPlayer.PlayerControl.SetPlayerMaterialColors(__instance.HerePoint); - return false; - } - [HarmonyPrefix] - [HarmonyPatch(typeof(MapBehaviour), nameof(MapBehaviour.ShowNormalMap))] - static bool Prefix3(MapBehaviour __instance) { - if (!MeetingHud.Instance || __instance.IsOpen) return true; // Only run in meetings and when the map is closed - - CachedPlayer.LocalPlayer.PlayerControl.SetPlayerMaterialColors(__instance.HerePoint); - __instance.GenericShow(); - __instance.taskOverlay.Show(); - __instance.ColorControl.SetColor(new Color(0.05f, 0.2f, 1f, 1f)); - FastDestroyableSingleton.Instance.SetHudActive(false); return false; } } -} \ No newline at end of file +} diff --git a/TheOtherRoles/Patches/MeetingPatch.cs b/TheOtherRoles/Patches/MeetingPatch.cs index 5e7d401..3c95bb8 100644 --- a/TheOtherRoles/Patches/MeetingPatch.cs +++ b/TheOtherRoles/Patches/MeetingPatch.cs @@ -274,7 +274,8 @@ namespace TheOtherRoles.Patches { } } - private static GameObject guesserUI; + public static GameObject guesserUI; + public static PassiveButton guesserUIExitButton; static void guesserOnClick(int buttonTarget, MeetingHud __instance) { if (guesserUI != null || !(__instance.state == MeetingHud.VoteStates.Voted || __instance.state == MeetingHud.VoteStates.NotVoted)) return; __instance.playerStates.ToList().ForEach(x => x.gameObject.SetActive(false)); @@ -296,9 +297,13 @@ namespace TheOtherRoles.Patches { exitButton.gameObject.GetComponent().sprite = smallButtonTemplate.GetComponent().sprite; exitButtonParent.transform.localPosition = new Vector3(2.725f, 2.1f, -5); exitButtonParent.transform.localScale = new Vector3(0.217f, 0.9f, 1); - exitButton.GetComponent().OnClick.RemoveAllListeners(); - exitButton.GetComponent().OnClick.AddListener((System.Action)(() => { - __instance.playerStates.ToList().ForEach(x => x.gameObject.SetActive(true)); + guesserUIExitButton = exitButton.GetComponent(); + guesserUIExitButton.OnClick.RemoveAllListeners(); + guesserUIExitButton.OnClick.AddListener((System.Action)(() => { + __instance.playerStates.ToList().ForEach(x => { + x.gameObject.SetActive(true); + if (CachedPlayer.LocalPlayer.Data.IsDead && x.transform.FindChild("ShootButton") != null) UnityEngine.Object.Destroy(x.transform.FindChild("ShootButton").gameObject); + }); UnityEngine.Object.Destroy(container.gameObject); })); @@ -316,6 +321,7 @@ namespace TheOtherRoles.Patches { else if (new List() { RoleId.Janitor, RoleId.Godfather, RoleId.Mafioso }.Contains(roleInfo.roleId) && CustomOptionHolder.mafiaSpawnRate.getSelection() == 0) continue; else if (roleInfo.roleId == RoleId.Sidekick && (!CustomOptionHolder.jackalCanCreateSidekick.getBool() || CustomOptionHolder.jackalSpawnRate.getSelection() == 0)) continue; if (roleInfo.roleId == RoleId.Deputy && (CustomOptionHolder.deputySpawnRate.getSelection() == 0 || CustomOptionHolder.sheriffSpawnRate.getSelection() == 0)) continue; + if (roleInfo.roleId == RoleId.Pursuer && CustomOptionHolder.lawyerSpawnRate.getSelection() == 0) continue; if (roleInfo.roleId == RoleId.Spy && roleData.impostors.Count <= 1) continue; if (Guesser.guesserCantGuessSnitch && Snitch.snitch != null) { @@ -356,6 +362,7 @@ namespace TheOtherRoles.Patches { MessageWriter murderAttemptWriter = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.ShieldedMurderAttempt, Hazel.SendOption.Reliable, -1); AmongUsClient.Instance.FinishRpcImmediately(murderAttemptWriter); RPCProcedure.shieldedMurderAttempt(); + SoundEffectsManager.play("fail"); return; } @@ -559,6 +566,9 @@ namespace TheOtherRoles.Patches { // Reset zoomed out ghosts Helpers.toggleZoom(reset: true); + + // Stop all playing sounds + SoundEffectsManager.stopAll(); } } diff --git a/TheOtherRoles/Patches/PlayerControlPatch.cs b/TheOtherRoles/Patches/PlayerControlPatch.cs index 5835a4d..f71a800 100644 --- a/TheOtherRoles/Patches/PlayerControlPatch.cs +++ b/TheOtherRoles/Patches/PlayerControlPatch.cs @@ -1028,6 +1028,9 @@ namespace TheOtherRoles.Patches { if (target.hasFakeTasks()) target.clearAllTasks(); + // First kill (set before lover suicide) + if (MapOptions.firstKillName == "") MapOptions.firstKillName = target.Data.PlayerName; + // Lover suicide trigger on murder if ((Lovers.lover1 != null && target == Lovers.lover1) || (Lovers.lover2 != null && target == Lovers.lover2)) { PlayerControl otherLover = target == Lovers.lover1 ? Lovers.lover2 : Lovers.lover1; @@ -1127,9 +1130,6 @@ namespace TheOtherRoles.Patches { } Helpers.showFlash(color, 1.5f); } - - // First kill - if (MapOptions.firstKillName == "") MapOptions.firstKillName = target.Data.PlayerName; } } diff --git a/TheOtherRoles/Patches/RegionMenuPatch.cs b/TheOtherRoles/Patches/RegionMenuPatch.cs index bfa7be8..1dfd714 100644 --- a/TheOtherRoles/Patches/RegionMenuPatch.cs +++ b/TheOtherRoles/Patches/RegionMenuPatch.cs @@ -39,6 +39,28 @@ namespace TheOtherRoles.Patches { public static void Postfix(RegionMenu __instance) { if (!__instance.TryCast()) return; + bool isCustomRegion = FastDestroyableSingleton.Instance.CurrentRegion.Name == "Custom"; + if (!isCustomRegion) + { + if (ipField != null && ipField.gameObject != null) { + ipField.gameObject.SetActive(false); + + } + if (portField != null && portField.gameObject != null) { + portField.gameObject.SetActive(false); + } + } else + { + if (ipField != null && ipField.gameObject != null) + { + ipField.gameObject.SetActive(true); + + } + if (portField != null && portField.gameObject != null) + { + portField.gameObject.SetActive(true); + } + } var template = FastDestroyableSingleton.Instance; var joinGameButtons = GameObject.FindObjectsOfType(); foreach (var t in joinGameButtons) { // The correct button has a background, the other 2 dont @@ -71,6 +93,7 @@ namespace TheOtherRoles.Patches { ipField.OnFocusLost = new Button.ButtonClickedEvent(); ipField.OnChange.AddListener((UnityAction)onEnterOrIpChange); ipField.OnFocusLost.AddListener((UnityAction)onFocusLost); + ipField.gameObject.SetActive(isCustomRegion); void onEnterOrIpChange() { TheOtherRolesPlugin.Ip.Value = ipField.text; @@ -103,6 +126,7 @@ namespace TheOtherRoles.Patches { portField.OnFocusLost = new Button.ButtonClickedEvent(); portField.OnChange.AddListener((UnityAction)onEnterOrPortFieldChange); portField.OnFocusLost.AddListener((UnityAction)onFocusLost); + portField.gameObject.SetActive(isCustomRegion); void onEnterOrPortFieldChange() { ushort port = 0; diff --git a/TheOtherRoles/Patches/RoleAssignmentPatch.cs b/TheOtherRoles/Patches/RoleAssignmentPatch.cs index 0f82bef..f870b43 100644 --- a/TheOtherRoles/Patches/RoleAssignmentPatch.cs +++ b/TheOtherRoles/Patches/RoleAssignmentPatch.cs @@ -21,6 +21,7 @@ namespace TheOtherRoles.Patches { private static int crewValues; private static int impValues; private static bool isEvilGuesser; + private static List> playerRoleMap = new List>(); public static void Postfix() { MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.ResetVaribles, Hazel.SendOption.Reliable, -1); AmongUsClient.Instance.FinishRpcImmediately(writer); @@ -39,6 +40,7 @@ namespace TheOtherRoles.Patches { assignChanceRoles(data); // Assign roles that may or may not be in the game last assignRoleTargets(data); assignModifiers(); + setRolesAgain(); } public static RoleAssignmentData getRoleAssignmentData() { @@ -421,6 +423,8 @@ namespace TheOtherRoles.Patches { byte playerId = playerList[index].PlayerId; if (removePlayer) playerList.RemoveAt(index); + playerRoleMap.Add(new Tuple(playerId, roleId)); + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.SetRole, Hazel.SendOption.Reliable, -1); writer.Write(roleId); writer.Write(playerId); @@ -510,6 +514,25 @@ namespace TheOtherRoles.Patches { return selection; } + private static void setRolesAgain() + { + + while (playerRoleMap.Any()) + { + byte amount = (byte)Math.Min(playerRoleMap.Count, 20); + var writer = AmongUsClient.Instance!.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.WorkaroundSetRoles, SendOption.Reliable, -1); + writer.Write(amount); + for (int i = 0; i < amount; i++) + { + var option = playerRoleMap[0]; + playerRoleMap.RemoveAt(0); + writer.WritePacked((uint)option.Item1); + writer.WritePacked((uint)option.Item2); + } + AmongUsClient.Instance.FinishRpcImmediately(writer); + } + } + public class RoleAssignmentData { public List crewmates {get;set;} diff --git a/TheOtherRoles/Patches/UsablesPatch.cs b/TheOtherRoles/Patches/UsablesPatch.cs index 0970d13..9314eae 100644 --- a/TheOtherRoles/Patches/UsablesPatch.cs +++ b/TheOtherRoles/Patches/UsablesPatch.cs @@ -116,6 +116,7 @@ namespace TheOtherRoles.Patches { writer.Write(isEnter ? byte.MaxValue : (byte)0); writer.EndMessage(); RPCProcedure.useUncheckedVent(__instance.Id, CachedPlayer.LocalPlayer.PlayerId, isEnter ? byte.MaxValue : (byte)0); + SoundEffectsManager.play("tricksterUseBoxVent"); return false; } diff --git a/TheOtherRoles/RPC.cs b/TheOtherRoles/RPC.cs index a56ee34..9f0246d 100644 --- a/TheOtherRoles/RPC.cs +++ b/TheOtherRoles/RPC.cs @@ -77,6 +77,7 @@ namespace TheOtherRoles ResetVaribles = 60, ShareOptions, ForceEnd, + WorkaroundSetRoles, SetRole, SetModifier, VersionHandshake, @@ -147,6 +148,7 @@ namespace TheOtherRoles clearAndReloadRoles(); clearGameHistory(); setCustomButtonCooldowns(); + Helpers.toggleZoom(reset : true); } public static void HandleShareOptions(byte numberOfOptions, MessageReader reader) { @@ -174,6 +176,21 @@ namespace TheOtherRoles } } + public static void workaroundSetRoles(byte numberOfRoles, MessageReader reader) + { + for (int i = 0; i < numberOfRoles; i++) + { + byte playerId = (byte) reader.ReadPackedUInt32(); + byte roleId = (byte) reader.ReadPackedUInt32(); + try { + setRole(roleId, playerId); + } catch (Exception e) { + TheOtherRolesPlugin.Logger.LogError("Error while deserializing roles: " + e.Message); + } + } + + } + public static void setRole(byte roleId, byte playerId) { foreach (PlayerControl player in CachedPlayer.AllPlayers) if (player.PlayerId == playerId) { @@ -410,6 +427,7 @@ namespace TheOtherRoles public static void timeMasterRewindTime() { TimeMaster.shieldActive = false; // Shield is no longer active when rewinding + SoundEffectsManager.stop("timemasterShield"); // Shield sound stopped when rewinding if(TimeMaster.timeMaster != null && TimeMaster.timeMaster == CachedPlayer.LocalPlayer.PlayerControl) { resetTimeMasterButton(); } @@ -622,6 +640,7 @@ namespace TheOtherRoles if (wasSpy || wasImpostor) Sidekick.wasTeamRed = true; Sidekick.wasSpy = wasSpy; Sidekick.wasImpostor = wasImpostor; + if (player == CachedPlayer.LocalPlayer.PlayerControl) SoundEffectsManager.play("jackalSidekick"); } Jackal.canCreateSidekick = false; } @@ -748,6 +767,7 @@ namespace TheOtherRoles if (flag == byte.MaxValue) { target.cosmetics.currentBodySprite.BodySprite.color = Color.white; + target.cosmetics.colorBlindText.gameObject.SetActive(SaveManager.colorblindMode); if (Camouflager.camouflageTimer <= 0) target.setDefaultLook(); Ninja.isInvisble = false; return; @@ -757,6 +777,7 @@ namespace TheOtherRoles Color color = Color.clear; if (CachedPlayer.LocalPlayer.Data.Role.IsImpostor || CachedPlayer.LocalPlayer.Data.IsDead) color.a = 0.1f; target.cosmetics.currentBodySprite.BodySprite.color = color; + target.cosmetics.colorBlindText.gameObject.SetActive(false); Ninja.invisibleTimer = Ninja.invisibleDuration; Ninja.isInvisble = true; } @@ -905,10 +926,13 @@ namespace TheOtherRoles } PlayerControl guesser = Helpers.playerById(killerId); if (FastDestroyableSingleton.Instance != null && guesser != null) - if (CachedPlayer.LocalPlayer.PlayerControl == dyingTarget) + if (CachedPlayer.LocalPlayer.PlayerControl == dyingTarget) { FastDestroyableSingleton.Instance.KillOverlay.ShowKillAnimation(guesser.Data, dyingTarget.Data); - else if (dyingLoverPartner != null && CachedPlayer.LocalPlayer.PlayerControl == dyingLoverPartner) + if (MeetingHudPatch.guesserUI != null) MeetingHudPatch.guesserUIExitButton.OnClick.Invoke(); + } else if (dyingLoverPartner != null && CachedPlayer.LocalPlayer.PlayerControl == dyingLoverPartner) { FastDestroyableSingleton.Instance.KillOverlay.ShowKillAnimation(dyingLoverPartner.Data, dyingLoverPartner.Data); + if (MeetingHudPatch.guesserUI != null) MeetingHudPatch.guesserUIExitButton.OnClick.Invoke(); + } PlayerControl guessedTarget = Helpers.playerById(guessedTargetId); if (Guesser.showInfoInGhostChat && CachedPlayer.LocalPlayer.Data.IsDead && guessedTarget != null) { @@ -965,6 +989,9 @@ namespace TheOtherRoles case (byte)CustomRPC.ForceEnd: RPCProcedure.forceEnd(); break; + case (byte)CustomRPC.WorkaroundSetRoles: + RPCProcedure.workaroundSetRoles(reader.ReadByte(), reader); + break; case (byte)CustomRPC.SetRole: byte roleId = reader.ReadByte(); byte playerId = reader.ReadByte(); @@ -980,6 +1007,8 @@ namespace TheOtherRoles byte major = reader.ReadByte(); byte minor = reader.ReadByte(); byte patch = reader.ReadByte(); + float timer = reader.ReadSingle(); + if (!AmongUsClient.Instance.AmHost && timer >= 0f) GameStartManagerPatch.timer = timer; int versionOwnerId = reader.ReadPackedInt32(); byte revision = 0xFF; Guid guid; diff --git a/TheOtherRoles/Resources/CreditsButton.png b/TheOtherRoles/Resources/CreditsButton.png new file mode 100644 index 0000000..dd8f59f Binary files /dev/null and b/TheOtherRoles/Resources/CreditsButton.png differ diff --git a/TheOtherRoles/Resources/SoundEffects/SoundEffectSourcesAndLicenses.md b/TheOtherRoles/Resources/SoundEffects/SoundEffectSourcesAndLicenses.md new file mode 100644 index 0000000..5cc3a56 --- /dev/null +++ b/TheOtherRoles/Resources/SoundEffects/SoundEffectSourcesAndLicenses.md @@ -0,0 +1,41 @@ +#### Custom Button Sound credits, sources and licenses: + +| Name | Comment | Url | License | +|---|---|---|---| +|engineerRepair| | [Repair_metal.wav](https://freesound.org/people/zbig77/sounds/244985/ ) | CC0 1.0| +|janitorClean + cleanerClean | combined, shortened + fade out | [Vacuum cleaner.wav](https://freesound.org/people/Accorman/sounds/573797/ ) + [Windowcleaner Spray](https://freesound.org/people/Rudmer_Rotteveel/sounds/536409/ )| CC0 1.0 both| +|sheriffKill | (already has a sound) |-|-| +|deputyHandcuff | | [Ratchet close long.wav](https://freesound.org/people/jameswrowles/sounds/437230/ ) | CC0 1.0| +|timeMasterShield | | [Mechanical alarm clock is ticking (SLAVA).wav](https://freesound.org/people/ST303/sounds/171043/ ) | CC0 1.0| +|medicShield | | [energy](https://freesound.org/people/Leszek_Szary/sounds/146727/ )| CC0 1.0 | +|shifterShift | recorded by gendelo3 | - | GPLv3 | +|morphlingSample |Combined and cut |[Scanner 03.wav](https://freesound.org/people/Glitchedtones/sounds/375942/ ) + [ scanner epson V600](https://freesound.org/people/gecop/sounds/521298/ )| CC0 1.0 both| +|morphlingMorph | | [Whoosh](https://freesound.org/people/qubodup/sounds/60013/) | CC0 1.0 | +|camouflagerCamo | same as morphlingMorph | - | - | +|hackerHack | recorded by gendelo3 | - | GPLv3 | +|hackerVitals | (already has a sound) |-|-| +|hackerAdmin | (already has a sound) |-|-| +|trackerTrackPlayer | | [CASHIER-REGISTER-KEYBOARD-BEEP-CALC.wav](https://freesound.org/people/newagesoup/sounds/348240/ ) | CC0 1.0 | +|trackerTrackCorpses |sniffing sound|[Male_Breath_Sniff_Stereo_NT4.wav](https://freesound.org/people/Nox_Sound/sounds/554905/ ) | CC0 1.0 | +|vampireKill |combined |[Gore Rend](https://freesound.org/people/magnuswaker/sounds/563491/ ) + [R15-53-Blood Sucking.wav](https://freesound.org/people/craigsmith/sounds/487070/ ) | CC0 1.0 both| +|garlic | | [Garlic cloves](https://freesound.org/people/Aemyn/sounds/512453/ )| CC0 1.0 | +|jackalKill | (already has a sound) |-|-| +|jackalSidekick | | [Snare - Nice.wav]( https://freesound.org/people/molodiaz/sounds/593550/ )| CC0 1.0 | +|lighterLight | |[Torch Click 2](https://freesound.org/people/BenjaminNelan/sounds/410360/ ) | CC0 1.0 | +|eraserErase | | [Pencil Eraser Erasing](https://freesound.org/people/deleted_user_7146007/sounds/383861/ ) | CC0 1.0 | +|tricksterPlaceBox | |[Carton_impact_5.wav](https://freesound.org/people/andresix/sounds/245617/ ) | CC0 1.0 | +|tricksterLight | same as lighterLight |-|-| +|tricksterUseBoxVent | |[rubber duck -CsG-.wav](https://freesound.org/people/csaszi/sounds/350917/) | CC0 1.0 | +|warlockCurse | | [Buffer Spell](https://freesound.org/people/deleted_user_3277771/sounds/176741/ ) | CC0 1.0 | +|warlockKill | (already has a sound) |-|-| +|securityGuardPlaceCam | combined | [drilling a screw into wood.wav](https://freesound.org/people/chewiesmissus/sounds/244242/ ) + [hammer v3.wav](https://freesound.org/people/blukotek/sounds/337814/ ) | CC0 1.0 both| +|securityGuardSealVent | same as securityGuardPlaceCam |-|-| +|securityGuardCam | (already has a sound) |-|-| +|arsonistDouse | | [Water Pouring Out of Bucket](https://freesound.org/people/Breviceps/sounds/508178/ )| CC0 1.0 | +|vultureEat | combined | [Vulture](https://freesound.org/people/AntumDeluge/sounds/188041/ ) + [Eating Crisps](https://freesound.org/people/Sethroph/sounds/334209/ )| CC0 1.0 both| | +|mediumAsk| |[ghost_sounds.wav](https://freesound.org/people/fishwithfeathers/sounds/177768/ )| CC0 1.0| +|pursuerBlank | | [gun load.wav](https://freesound.org/people/Shelby_Wideman/sounds/178141/ )| CC0 1.0 | +|witchSpell | | [witch's laugh](https://freesound.org/people/Yogoorth/sounds/589144/ ) | CC0 1.0 | +|portalmakerPlacePortal | same as tricksterPlaceBox| - | - | +|portalUse | | [Static electronic noise - Xbox 360](https://freesound.org/people/scenes/sounds/431654/ ) + [Teleport Slurp](https://freesound.org/people/GameAudio/sounds/220163/ ) | CC0 1.0 both | +|fail | | [twitch: SmeggyTV: Mein Auge](https://www.twitch.tv/smeggytv/clip/KindQuaintEndiveDancingBanana-Zoc-bXUnqNCoqQD5 ) | License granted for use in TOR | \ No newline at end of file diff --git a/TheOtherRoles/Resources/SoundEffects/arsonistDouse.raw b/TheOtherRoles/Resources/SoundEffects/arsonistDouse.raw new file mode 100644 index 0000000..297efad Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/arsonistDouse.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/cleanerClean.raw b/TheOtherRoles/Resources/SoundEffects/cleanerClean.raw new file mode 100644 index 0000000..70bfed1 Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/cleanerClean.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/deputyHandcuff.raw b/TheOtherRoles/Resources/SoundEffects/deputyHandcuff.raw new file mode 100644 index 0000000..5af1a9d Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/deputyHandcuff.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/engineerRepair.raw b/TheOtherRoles/Resources/SoundEffects/engineerRepair.raw new file mode 100644 index 0000000..e4f5ace Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/engineerRepair.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/eraserErase.raw b/TheOtherRoles/Resources/SoundEffects/eraserErase.raw new file mode 100644 index 0000000..bf95d80 Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/eraserErase.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/fail.raw b/TheOtherRoles/Resources/SoundEffects/fail.raw new file mode 100644 index 0000000..514c79b Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/fail.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/garlic.raw b/TheOtherRoles/Resources/SoundEffects/garlic.raw new file mode 100644 index 0000000..d907a38 Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/garlic.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/hackerHack.raw b/TheOtherRoles/Resources/SoundEffects/hackerHack.raw new file mode 100644 index 0000000..93684f5 Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/hackerHack.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/jackalSidekick.raw b/TheOtherRoles/Resources/SoundEffects/jackalSidekick.raw new file mode 100644 index 0000000..e4ec042 Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/jackalSidekick.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/lighterLight.raw b/TheOtherRoles/Resources/SoundEffects/lighterLight.raw new file mode 100644 index 0000000..8bb44c3 Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/lighterLight.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/medicShield.raw b/TheOtherRoles/Resources/SoundEffects/medicShield.raw new file mode 100644 index 0000000..16a93bb Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/medicShield.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/mediumAsk.raw b/TheOtherRoles/Resources/SoundEffects/mediumAsk.raw new file mode 100644 index 0000000..12fe798 Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/mediumAsk.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/morphlingMorph.raw b/TheOtherRoles/Resources/SoundEffects/morphlingMorph.raw new file mode 100644 index 0000000..7fff361 Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/morphlingMorph.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/morphlingSample.raw b/TheOtherRoles/Resources/SoundEffects/morphlingSample.raw new file mode 100644 index 0000000..fe77442 Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/morphlingSample.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/portalUse.raw b/TheOtherRoles/Resources/SoundEffects/portalUse.raw new file mode 100644 index 0000000..a5fdcdb Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/portalUse.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/pursuerBlank.raw b/TheOtherRoles/Resources/SoundEffects/pursuerBlank.raw new file mode 100644 index 0000000..c94e197 Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/pursuerBlank.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/securityGuardPlaceCam.raw b/TheOtherRoles/Resources/SoundEffects/securityGuardPlaceCam.raw new file mode 100644 index 0000000..8be0b1a Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/securityGuardPlaceCam.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/shifterShift.raw b/TheOtherRoles/Resources/SoundEffects/shifterShift.raw new file mode 100644 index 0000000..58d2097 Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/shifterShift.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/timemasterShield.raw b/TheOtherRoles/Resources/SoundEffects/timemasterShield.raw new file mode 100644 index 0000000..9322eec Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/timemasterShield.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/trackerTrackCorpses.raw b/TheOtherRoles/Resources/SoundEffects/trackerTrackCorpses.raw new file mode 100644 index 0000000..9bf310c Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/trackerTrackCorpses.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/trackerTrackPlayer.raw b/TheOtherRoles/Resources/SoundEffects/trackerTrackPlayer.raw new file mode 100644 index 0000000..a58eb25 Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/trackerTrackPlayer.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/tricksterPlaceBox.raw b/TheOtherRoles/Resources/SoundEffects/tricksterPlaceBox.raw new file mode 100644 index 0000000..9dfe036 Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/tricksterPlaceBox.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/tricksterUseBoxVent.raw b/TheOtherRoles/Resources/SoundEffects/tricksterUseBoxVent.raw new file mode 100644 index 0000000..1aa46f2 Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/tricksterUseBoxVent.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/vampireBite.raw b/TheOtherRoles/Resources/SoundEffects/vampireBite.raw new file mode 100644 index 0000000..a2c9403 Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/vampireBite.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/vultureEat.raw b/TheOtherRoles/Resources/SoundEffects/vultureEat.raw new file mode 100644 index 0000000..774911a Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/vultureEat.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/warlockCurse.raw b/TheOtherRoles/Resources/SoundEffects/warlockCurse.raw new file mode 100644 index 0000000..04baa45 Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/warlockCurse.raw differ diff --git a/TheOtherRoles/Resources/SoundEffects/witchSpell.raw b/TheOtherRoles/Resources/SoundEffects/witchSpell.raw new file mode 100644 index 0000000..5ac52e9 Binary files /dev/null and b/TheOtherRoles/Resources/SoundEffects/witchSpell.raw differ diff --git a/TheOtherRoles/Resources/ThirdParty/Submerged/Submerged.dll b/TheOtherRoles/Resources/ThirdParty/Submerged/Submerged.dll index dc85f51..4be1225 100644 Binary files a/TheOtherRoles/Resources/ThirdParty/Submerged/Submerged.dll and b/TheOtherRoles/Resources/ThirdParty/Submerged/Submerged.dll differ diff --git a/TheOtherRoles/RoleInfo.cs b/TheOtherRoles/RoleInfo.cs index 6924b6d..827986f 100644 --- a/TheOtherRoles/RoleInfo.cs +++ b/TheOtherRoles/RoleInfo.cs @@ -143,14 +143,18 @@ namespace TheOtherRoles // Modifier if (showModifier) { + // after dead modifier + if (!CustomOptionHolder.modifiersAreHidden.getBool() || PlayerControl.LocalPlayer.Data.IsDead) + { + if (Bait.bait.Any(x => x.PlayerId == p.PlayerId)) infos.Add(bait); + if (Bloody.bloody.Any(x => x.PlayerId == p.PlayerId)) infos.Add(bloody); + if (Vip.vip.Any(x => x.PlayerId == p.PlayerId)) infos.Add(vip); + } if (p == Lovers.lover1 || p == Lovers.lover2) infos.Add(lover); if (p == Tiebreaker.tiebreaker) infos.Add(tiebreaker); - if (Bait.bait.Any(x => x.PlayerId == p.PlayerId)) infos.Add(bait); - if (Bloody.bloody.Any(x => x.PlayerId == p.PlayerId)) infos.Add(bloody); if (AntiTeleport.antiTeleport.Any(x => x.PlayerId == p.PlayerId)) infos.Add(antiTeleport); if (Sunglasses.sunglasses.Any(x => x.PlayerId == p.PlayerId)) infos.Add(sunglasses); if (p == Mini.mini) infos.Add(mini); - if (Vip.vip.Any(x => x.PlayerId == p.PlayerId)) infos.Add(vip); if (Invert.invert.Any(x => x.PlayerId == p.PlayerId)) infos.Add(invert); } diff --git a/TheOtherRoles/SoundEffectsManager.cs b/TheOtherRoles/SoundEffectsManager.cs new file mode 100644 index 0000000..eb047d9 --- /dev/null +++ b/TheOtherRoles/SoundEffectsManager.cs @@ -0,0 +1,58 @@ +using System; +using System.IO; +using System.Reflection; +using System.Collections.Generic; +using System.Text; +using UnityEngine; +using System.Linq; + +namespace TheOtherRoles +{ + // Class to preload all audio/sound effects that are contained in the embedded resources. + // The effects are made available through the soundEffects Dict / the get and the play methods. + public static class SoundEffectsManager + + { + private static Dictionary soundEffects; + + public static void Load() + { + soundEffects = new Dictionary(); + Assembly assembly = Assembly.GetExecutingAssembly(); + string[] resourceNames = assembly.GetManifestResourceNames(); + foreach (string resourceName in resourceNames) + { + if (resourceName.Contains("TheOtherRoles.Resources.SoundEffects.") && resourceName.Contains(".raw")) + { + soundEffects.Add(resourceName, Helpers.loadAudioClipFromResources(resourceName)); + } + } + } + + public static AudioClip get(string path) + { + // Convenience: As as SoundEffects are stored in the same folder, allow using just the name as well + if (!path.Contains(".")) path = "TheOtherRoles.Resources.SoundEffects." + path + ".raw"; + AudioClip returnValue; + return soundEffects.TryGetValue(path, out returnValue) ? returnValue : null; + } + + + public static void play(string path, float volume=0.8f) + { + if (!MapOptions.enableSoundEffects) return; + AudioClip clipToPlay = get(path); + // if (false) clipToPlay = get("exampleClip"); for april fools? + stop(path); + if (Constants.ShouldPlaySfx()) SoundManager.Instance.PlaySound(clipToPlay, false, volume); + } + + public static void stop(string path) { + if (Constants.ShouldPlaySfx()) SoundManager.Instance.StopSound(get(path)); + } + + public static void stopAll() { + foreach (var path in soundEffects.Keys) stop(path); + } + } +} diff --git a/TheOtherRoles/TheOtherRoles.cs b/TheOtherRoles/TheOtherRoles.cs index db9b5ae..7ec73db 100644 --- a/TheOtherRoles/TheOtherRoles.cs +++ b/TheOtherRoles/TheOtherRoles.cs @@ -286,6 +286,7 @@ namespace TheOtherRoles byte localPlayerId = CachedPlayer.LocalPlayer.PlayerId; handcuffedKnows.Add(localPlayerId, handcuffDuration); handcuffedPlayers.RemoveAll(x => x == localPlayerId); + SoundEffectsManager.play("deputyHandcuff"); } HudManagerStartPatch.setAllButtonsHandcuffedStatus(active); diff --git a/TheOtherRoles/TheOtherRoles.csproj b/TheOtherRoles/TheOtherRoles.csproj index 6133669..05ad58b 100644 --- a/TheOtherRoles/TheOtherRoles.csproj +++ b/TheOtherRoles/TheOtherRoles.csproj @@ -1,7 +1,7 @@  netstandard2.1 - 4.1.4 + 4.1.6 TheOtherRoles Eisbison latest