]> git.deb.at Git - rhonda/theotherroles.git/commitdiff
v3.2.2
authorEisbison <eisbison.creator@gmail.com>
Sat, 27 Nov 2021 17:50:38 +0000 (18:50 +0100)
committerEisbison <eisbison.creator@gmail.com>
Sat, 27 Nov 2021 17:50:38 +0000 (18:50 +0100)
13 files changed:
README.md
TheOtherRoles/Buttons.cs
TheOtherRoles/CustomOptionHolder.cs
TheOtherRoles/Main.cs
TheOtherRoles/Modules/CustomOptions.cs
TheOtherRoles/Patches/EndGamePatch.cs
TheOtherRoles/Patches/ExileControllerPatch.cs
TheOtherRoles/Patches/GameStartManagerPatch.cs
TheOtherRoles/Patches/PlayerControlPatch.cs
TheOtherRoles/RPC.cs
TheOtherRoles/RoleInfo.cs
TheOtherRoles/TheOtherRoles.cs
TheOtherRoles/TheOtherRoles.csproj

index f33e5b3b2886854b3ce4c2ff0f3a3e5a86001f25..395e97619491a44535142d512f387f9153e58b05 100644 (file)
--- a/README.md
+++ b/README.md
@@ -38,6 +38,7 @@ The [Role Assignment](#role-assignment) sections explains how the roles are bein
 # Releases
 | Among Us - Version| Mod Version | Link |
 |----------|-------------|-----------------|
+| 2021.11.9.5s| v3.2.2| [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v3.2.2/TheOtherRoles.zip)
 | 2021.11.9.5s| v3.2.1| [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v3.2.1/TheOtherRoles.zip)
 | 2021.11.9.5s| v3.2.0| [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v3.2.0/TheOtherRoles.zip)
 | 2021.11.9.5s| v3.1.2| [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v3.1.2/TheOtherRoles.zip)
@@ -85,8 +86,17 @@ The [Role Assignment](#role-assignment) sections explains how the roles are bein
 <details>
   <summary>Click to show the Changelog</summary>
 
+**Version 3.2.2**
+- Add new option "Play On A Random Map" created by [Alex2911](https://github.com/Alex2911)
+- Add Witch option "Voting The Witch Saves All The Targets"
+- We changed the win conditions of the [Lawyer](#lawyer), to make it more viable
+- Bug fix: The Medium now shows the roles of players in the rigth format
+- The name and the role of all winners is now being displayed on the end screen
+- We changed the way settings are being shared among the players (which caused some people to be unable to join the lobby). This might resolve the problem or make it even worse... we'll see.
+
 **Version 3.2.1**
 - Hotfix for 3.2.0
+- Bug fix: The Warlock is again able to kill with the curse abilty
 
 **Version 3.2.0**
 - **New Role:** [Witch](#witch) created by [Alex2911](https://github.com/Alex2911)
@@ -754,9 +764,14 @@ Depending on the options, there'll be an arrow pointing towards the current targ
 The Witch is an Impostor who has the ability to cast a spell on other players.\
 During the next meeting, the spellbound player will be highlighted and he'll die right after the meeting.\
 There are multiple options listed down below with which you can configure to fit your taste.\
+Similar to the Vampire, shields and blanks will be checked twice (at the end of casting the spell on the player and at the end of the meeting, when the spell will be activated).\
+This can result in players being marked as spelled during the meeting, but not dying in the end (when they get a shield or the Witch gets blanked after they were spelled by the Witch).\
+If the Witch dies before the meeting starts or if the Witch is being guessed during the meeting, the spellbound players will be highlighted but they'll survive in any case.\
+Depending on the options you can choose whether voting the Witch out will save all the spellbound players or not.\
+
 \
 **NOTE:**
-- Similar to the Vampire, shields and blanks will be checked twice (at the end of casting the spell on the player and at the end of the meeting, when the spell will be activated). This can result in players being marked as spelled during the meeting, but not dying in the end (when they get a shield or the Witch gets blanked after they were spelled by the Witch).
+- The spellbound players will die before the voted player dies (which might trigger e.g. trigger an Impostor win condition, even if the Witch is the one being voted)
 
 \
 ### Game Options
@@ -768,6 +783,7 @@ There are multiple options listed down below with which you can configure to fit
 | Witch Can Spell Everyone | If set to false, the witch can't spell the Spy and other Impostors
 | Witch Spell Casting Duration | The time that you need to stay next to the target in order to cast a spell on it
 | Trigger Both Cooldowns | If set to true, casting a spell will also trigger cooldown of the kill button and vice versa (but the two cooldowns may vary)
+| Voting The Witch Saves All The Targets | If set to true, all the cursed targets will survive at the end of the meeting
 -----------------------
 
 
@@ -1286,13 +1302,13 @@ Depending on the options, when a player dies, the Vulture gets an arrow pointing
 ### **Team: Neutral**
 The Lawyer is a neutral role that has a client.
 The client might be an Impostor, Jackal or Sidekick which is no Lover.
-The Lawyer needs to keep his client alive in order to win as a Lawyer.
+The Lawyer needs his client to win in order to win the game.
 If his client dies or gets voted out, the Lawyer gets changes his role and becomes the [Pursuer](#pursuer), which has a different goal to win the game.
 The main goal of the Lawyer is to win as Lawyer, he is not allowed to betray his client.
 
 The Lawyer can win in multiple ways:
-- Lawyer dead and client alive: The Lawyer wins together with the winning team because he kept his client alive
-- Lawyer alive and client alive: The Lawyer wins with the winning team because he kept his client alive. The client **doesn't** win (even if his Impostor/Team Jackal mate wins). Hence the client should keep the Lawyer alive for some time, to get some help during the meetings, but has to eliminate him soon enough to not get his win stolen.
+- Lawyer dead, client alive and client team won: The Lawyer wins together with the team of his client
+- Lawyer and client alive and client team won: The Lawyer wins with the team of his client. The client **doesn't** win (even if his Impostor/Team Jackal mate wins), the Lawyer steals his win. Hence the client should keep the Lawyer alive for some time, to get some help during the meetings, but has to eliminate him soon enough to not get his win stolen.
 
 **NOTE:**
 - If the client disconnects, the Lawyer will also turn into the Pursuer
index 828ba05cdfc9dcf1d0cc1333a3b8c0d6ce887c8e..4beb5862930238e4bb0a617f8725e48695fcf392 100644 (file)
@@ -682,7 +682,7 @@ namespace TheOtherRoles
 
                         if (murder == MurderAttemptResult.PerformKill) {
                             MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.WarlockCurseKill, Hazel.SendOption.Reliable, -1);
-                            writer.Write(Warlock.curseKillTarget.PlayerId);
+                            writer.Write(Warlock.curseVictimTarget.PlayerId);
                             AmongUsClient.Instance.FinishRpcImmediately(writer);
                             RPCProcedure.warlockCurseKill(Warlock.curseVictimTarget.PlayerId);
 
@@ -894,10 +894,10 @@ namespace TheOtherRoles
                     string name = " (" + Medium.target.player.Data.PlayerName + ")";
 
 
-                    if (randomNumber == 0) msg = "What is your role? My role is " + RoleInfo.GetRole(Medium.target.player) + name;
+                    if (randomNumber == 0) msg = "What is your role? My role is " + RoleInfo.GetRolesString(Medium.target.player, false) + name;
                     else if (randomNumber == 1) msg = "What is your killer`s color type? My killer is a " + typeOfColor + " color" + name;
                     else if (randomNumber == 2) msg = "When did you die? I have died " + Math.Round(timeSinceDeath / 1000) + "s before meeting started" + name;
-                    else msg = "What is your killer`s role? My killer is " + RoleInfo.GetRole(Medium.target.killerIfExisting) + name; //exlude mini 
+                    else msg = "What is your killer`s role? My killer is " + RoleInfo.GetRolesString(Medium.target.killerIfExisting, false) + name; //exlude mini 
 
                     DestroyableSingleton<HudManager>.Instance.Chat.AddChat(PlayerControl.LocalPlayer, $"{msg}");
 
index 4f94cefb3ea2d3628c9794b9229c844461e46ad6..49213babee9559d52564f51e03235f46cb40fd5c 100644 (file)
@@ -90,6 +90,7 @@ namespace TheOtherRoles {
         public static CustomOption witchCanSpellAnyone;
         public static CustomOption witchSpellCastingDuration;
         public static CustomOption witchTriggerBothCooldowns;
+        public static CustomOption witchVoteSavesTargets;
 
         public static CustomOption shifterSpawnRate;
         public static CustomOption shifterShiftsModifiers;
@@ -199,6 +200,7 @@ namespace TheOtherRoles {
         public static CustomOption lawyerWinsAfterMeetings;
         public static CustomOption lawyerNeededMeetings;
         public static CustomOption lawyerVision;
+        public static CustomOption lawyerKnowsRole;
         public static CustomOption pursuerCooldown;
         public static CustomOption pursuerBlanksNumber;
 
@@ -207,6 +209,7 @@ namespace TheOtherRoles {
         public static CustomOption noVoteIsSelfVote;
         public static CustomOption hidePlayerNames;
         public static CustomOption allowParallelMedBayScans;
+        public static CustomOption dynamicMap;
 
 
         internal static Dictionary<byte, byte[]> blockedRolePairings = new Dictionary<byte, byte[]>();
@@ -279,7 +282,7 @@ namespace TheOtherRoles {
             witchCanSpellAnyone = CustomOption.Create(373, "Witch Can Spell Anyone", false, witchSpawnRate);
             witchSpellCastingDuration = CustomOption.Create(374, "Spell Casting Duration", 1f, 0f, 10f, 1f, witchSpawnRate);
             witchTriggerBothCooldowns = CustomOption.Create(375, "Trigger Both Cooldowns", true, witchSpawnRate);
-
+            witchVoteSavesTargets = CustomOption.Create(376, "Voting The Witch Saves All The Targets", true, witchSpawnRate);
 
             miniSpawnRate = CustomOption.Create(180, cs(Mini.color, "Mini"), rates, null, true);
             miniGrowingUpDuration = CustomOption.Create(181, "Mini Growing Up Duration", 400f, 100f, 1500f, 100f, miniSpawnRate);
@@ -326,8 +329,9 @@ namespace TheOtherRoles {
             lawyerWinsAfterMeetings = CustomOption.Create(352, "Lawyer Wins After Meetings", false, lawyerSpawnRate);
             lawyerNeededMeetings = CustomOption.Create(353, "Lawyer Needed Meetings To Win", 5f, 1f, 15f, 1f, lawyerWinsAfterMeetings);
             lawyerVision = CustomOption.Create(354, "Lawyer Vision", 1f, 0.25f, 3f, 0.25f, lawyerSpawnRate);
-            pursuerCooldown = CustomOption.Create(355, "Pursuer Blank Cooldown", 30f, 5f, 60f, 2.5f, lawyerSpawnRate);
-            pursuerBlanksNumber = CustomOption.Create(356, "Pursuer Number Of Blanks", 5f, 0f, 20f, 1f, lawyerSpawnRate);
+            lawyerKnowsRole = CustomOption.Create(355, "Lawyer Knows Target Role", false, lawyerSpawnRate);
+            pursuerCooldown = CustomOption.Create(356, "Pursuer Blank Cooldown", 30f, 5f, 60f, 2.5f, lawyerSpawnRate);
+            pursuerBlanksNumber = CustomOption.Create(357, "Pursuer Number Of Blanks", 5f, 0f, 20f, 1f, lawyerSpawnRate);
 
             shifterSpawnRate = CustomOption.Create(70, cs(Shifter.color, "Shifter"), rates, null, true);
             shifterShiftsModifiers = CustomOption.Create(71, "Shifter Shifts Modifiers", false, shifterSpawnRate);
@@ -420,6 +424,7 @@ namespace TheOtherRoles {
             noVoteIsSelfVote = CustomOption.Create(5, "No Vote Is Self Vote", false, blockSkippingInEmergencyMeetings);
             hidePlayerNames = CustomOption.Create(6, "Hide Player Names", false);
             allowParallelMedBayScans = CustomOption.Create(7, "Allow Parallel MedBay Scans", false);
+            dynamicMap = CustomOption.Create(8, "Play On A Random Map", false, null, false);
 
             blockedRolePairings.Add((byte)RoleId.Vampire, new [] { (byte)RoleId.Warlock});
             blockedRolePairings.Add((byte)RoleId.Warlock, new [] { (byte)RoleId.Vampire});
index 9175bf98051eecbc01639113c2c9d22f7be69026..3dc088604a82a5cf9ce4792d10f6528461451e8d 100644 (file)
@@ -21,7 +21,7 @@ namespace TheOtherRoles
     public class TheOtherRolesPlugin : BasePlugin
     {
         public const string Id = "me.eisbison.theotherroles";
-        public const string VersionString = "3.2.1";
+        public const string VersionString = "3.2.2";
         public static System.Version Version = System.Version.Parse(VersionString);
         internal static BepInEx.Logging.ManualLogSource Logger;
 
index fb6748b6de467c9f3e2606b76e1e3f185bee539c..c18c9c4ae5c28d1e4d60756cf6cca1b2a80815bd 100644 (file)
@@ -76,12 +76,14 @@ namespace TheOtherRoles {
 
         public static void ShareOptionSelections() {
             if (PlayerControl.AllPlayerControls.Count <= 1 || AmongUsClient.Instance?.AmHost == false && PlayerControl.LocalPlayer == null) return;
+            
+            MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ShareOptions, Hazel.SendOption.Reliable);
+            messageWriter.WritePacked((uint)CustomOption.options.Count);
             foreach (CustomOption option in CustomOption.options) {
-                MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ShareOptionSelection, Hazel.SendOption.Reliable);
                 messageWriter.WritePacked((uint)option.id);
                 messageWriter.WritePacked((uint)Convert.ToUInt32(option.selection));
-                messageWriter.EndMessage();
             }
+            messageWriter.EndMessage();
         }
 
         // Getter
@@ -370,7 +372,7 @@ namespace TheOtherRoles {
             var hudString = sb.ToString();
 
             int defaultSettingsLines = 23;
-            int roleSettingsLines = defaultSettingsLines + 39;
+            int roleSettingsLines = defaultSettingsLines + 40;
             int detailedSettingsP1 = roleSettingsLines + 40;
             int detailedSettingsP2 = detailedSettingsP1 + 42;
             int detailedSettingsP3 = detailedSettingsP2 + 42;
index faefbfb04453162ca0576e95cd0fea142bb2cccb..100a5c1fc33afaa55b829ebb347566058bf75f0c 100644 (file)
@@ -180,7 +180,7 @@ namespace TheOtherRoles.Patches {
                 }
             }
 
-            // Lawyer solo win
+            // Lawyer solo win 
             else if (lawyerSoloWin) {
                 TempData.winners = new Il2CppSystem.Collections.Generic.List<WinningPlayerData>();
                 WinningPlayerData wpd = new WinningPlayerData(Lawyer.lawyer.Data);
@@ -190,20 +190,21 @@ namespace TheOtherRoles.Patches {
 
             // Possible Additional winner: Lawyer
             if (!lawyerSoloWin && Lawyer.lawyer != null && Lawyer.target != null && !Lawyer.target.Data.IsDead) {
-                if (!TempData.winners.ToArray().Any(x => x.PlayerName == Lawyer.lawyer.Data.PlayerName))
-                    TempData.winners.Add(new WinningPlayerData(Lawyer.lawyer.Data));
-                WinningPlayerData client = null;
+                WinningPlayerData winningClient = null;
                 foreach (WinningPlayerData winner in TempData.winners) {
                     if (winner.PlayerName == Lawyer.target.Data.PlayerName)
-                        client = winner;
-                }
-
-                if (!Lawyer.lawyer.Data.IsDead && client != null) { // Lawyer wins with the winning team but steals the win from his client
-                    TempData.winners.Remove(client);
-                    AdditionalTempData.additionalWinConditions.Add(WinCondition.AdditionalLawyerStolenWin);
-                } else {
-                    AdditionalTempData.additionalWinConditions.Add(WinCondition.AdditionalLawyerBonusWin);
+                        winningClient = winner;
                 }
+                if (winningClient != null) { // The Lawyer wins if the client is winning (and alive, but if he wasn't the Lawyer shouldn't exist anymore)
+                    if (!TempData.winners.ToArray().Any(x => x.PlayerName == Lawyer.lawyer.Data.PlayerName))
+                        TempData.winners.Add(new WinningPlayerData(Lawyer.lawyer.Data));
+                    if (!Lawyer.lawyer.Data.IsDead) { // The Lawyer steals the clients win
+                        TempData.winners.Remove(winningClient);
+                        AdditionalTempData.additionalWinConditions.Add(WinCondition.AdditionalLawyerStolenWin);
+                    } else { // The Lawyer wins together with the client
+                        AdditionalTempData.additionalWinConditions.Add(WinCondition.AdditionalLawyerBonusWin);
+                    }
+                } 
             }
 
             // Possible Additional winner: Pursuer
@@ -221,6 +222,52 @@ namespace TheOtherRoles.Patches {
     [HarmonyPatch(typeof(EndGameManager), nameof(EndGameManager.SetEverythingUp))]
     public class EndGameManagerSetUpPatch {
         public static void Postfix(EndGameManager __instance) {
+            // Delete and readd PoolablePlayers always showing the name and role of the player
+            foreach (PoolablePlayer pb in __instance.transform.GetComponentsInChildren<PoolablePlayer>()) {
+                UnityEngine.Object.Destroy(pb.gameObject);
+            }
+            int num = Mathf.CeilToInt(7.5f);
+            List<WinningPlayerData> list = TempData.winners.ToArray().ToList().OrderBy(delegate(WinningPlayerData b)
+            {
+                if (!b.IsYou)
+                {
+                    return 0;
+                }
+                return -1;
+            }).ToList<WinningPlayerData>();
+            for (int i = 0; i < list.Count; i++) {
+                WinningPlayerData winningPlayerData2 = list[i];
+                int num2 = (i % 2 == 0) ? -1 : 1;
+                int num3 = (i + 1) / 2;
+                float num4 = (float)num3 / (float)num;
+                float num5 = Mathf.Lerp(1f, 0.75f, num4);
+                float num6 = (float)((i == 0) ? -8 : -1);
+                PoolablePlayer poolablePlayer = UnityEngine.Object.Instantiate<PoolablePlayer>(__instance.PlayerPrefab, __instance.transform);
+                poolablePlayer.transform.localPosition = new Vector3(1f * (float)num2 * (float)num3 * num5, FloatRange.SpreadToEdges(-1.125f, 0f, num3, num), num6 + (float)num3 * 0.01f) * 0.9f;
+                float num7 = Mathf.Lerp(1f, 0.65f, num4) * 0.9f;
+                Vector3 vector = new Vector3(num7, num7, 1f);
+                poolablePlayer.transform.localScale = vector;
+                poolablePlayer.UpdateFromPlayerOutfit(winningPlayerData2, winningPlayerData2.IsDead);
+                if (winningPlayerData2.IsDead) {
+                    poolablePlayer.Body.sprite = __instance.GhostSprite;
+                    poolablePlayer.SetDeadFlipX(i % 2 == 0);
+                } else {
+                    poolablePlayer.SetFlipX(i % 2 == 0);
+                }
+
+                poolablePlayer.NameText.color = Color.white;
+                poolablePlayer.NameText.transform.localScale = new Vector3(1f / vector.x, 1f / vector.y, 1f / vector.z);
+                poolablePlayer.NameText.transform.localPosition = new Vector3(poolablePlayer.NameText.transform.localPosition.x, poolablePlayer.NameText.transform.localPosition.y, -15f);
+                poolablePlayer.NameText.text = winningPlayerData2.PlayerName;
+
+                foreach(var data in AdditionalTempData.playerRoles) {
+                    if (data.PlayerName != winningPlayerData2.PlayerName) continue;
+                    var roles = 
+                    poolablePlayer.NameText.text += $"\n{string.Join("\n", data.Roles.Select(x => Helpers.cs(x.color, x.name)))}";
+                }
+            }
+
+            // Additional code
             GameObject bonusText = UnityEngine.Object.Instantiate(__instance.WinText.gameObject);
             bonusText.transform.position = new Vector3(__instance.WinText.transform.position.x, __instance.WinText.transform.position.y - 0.5f, __instance.WinText.transform.position.z);
             bonusText.transform.localScale = new Vector3(0.7f, 0.7f, 1f);
@@ -264,11 +311,11 @@ namespace TheOtherRoles.Patches {
 
             foreach (WinCondition cond in AdditionalTempData.additionalWinConditions) {
                 if (cond == WinCondition.AdditionalLawyerStolenWin) {
-                    textRenderer.text += $"\n{Helpers.cs(Lawyer.color, "Lawyer stole the win of the client")}";
+                    textRenderer.text += $"\n{Helpers.cs(Lawyer.color, "The Lawyer stole the win from the client")}";
                 } else if (cond == WinCondition.AdditionalLawyerBonusWin) {
-                    textRenderer.text += $"\n{Helpers.cs(Lawyer.color, "Lawyer kept the client alive")}";
+                    textRenderer.text += $"\n{Helpers.cs(Lawyer.color, "The Lawyer wins with the client")}";
                 } else if (cond == WinCondition.AdditionalAlivePursuerWin) {
-                    textRenderer.text += $"\n{Helpers.cs(Pursuer.color, "Pursuer survived")}";
+                    textRenderer.text += $"\n{Helpers.cs(Pursuer.color, "The Pursuer survived")}";
                 }
             }
 
index 0f4b1ade0c284fbc1e62baff827965a187cfc67a..3f6a2c4998c8d12bf82d0e9fb99c7daf099a08d8 100644 (file)
@@ -13,7 +13,7 @@ using UnityEngine;
 using System.Reflection;
 
 namespace TheOtherRoles.Patches {
-    [HarmonyPatch(typeof(ExileController), "Begin")]
+    [HarmonyPatch(typeof(ExileController), nameof(ExileController.Begin))]
     class ExileControllerBeginPatch {
         public static void Prefix(ExileController __instance, [HarmonyArgument(0)]ref GameData.PlayerInfo exiled, [HarmonyArgument(1)]bool tie) {
             // Medic shield
@@ -51,21 +51,21 @@ namespace TheOtherRoles.Patches {
                 JackInTheBox.convertToVents();
             }
 
-
             // Witch execute casted spells
             if (Witch.witch != null && Witch.futureSpelled != null && AmongUsClient.Instance.AmHost) {
-                foreach (PlayerControl target in Witch.futureSpelled) {
-                    if (target != null && !target.Data.IsDead && Helpers.checkMuderAttempt(Witch.witch, target, true) == MurderAttemptResult.PerformKill) {
-                        MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.UncheckedExilePlayer, Hazel.SendOption.Reliable, -1);
-                        writer.Write(target.PlayerId);
-                        AmongUsClient.Instance.FinishRpcImmediately(writer);
-                        RPCProcedure.uncheckedExilePlayer(target.PlayerId);
+                if (!Witch.witchVoteSavesTargets || exiled == null || exiled.PlayerId != Witch.witch.PlayerId) {
+                    foreach (PlayerControl target in Witch.futureSpelled) {
+                        if (target != null && !target.Data.IsDead && Helpers.checkMuderAttempt(Witch.witch, target, true) == MurderAttemptResult.PerformKill) {
+                            MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.UncheckedExilePlayer, Hazel.SendOption.Reliable, -1);
+                            writer.Write(target.PlayerId);
+                            AmongUsClient.Instance.FinishRpcImmediately(writer);
+                            RPCProcedure.uncheckedExilePlayer(target.PlayerId);
+                        }
                     }
                 }
             }
             Witch.futureSpelled = new List<PlayerControl>();
 
-
             // SecurityGuard vents and cameras
             var allCameras = ShipStatus.Instance.AllCameras.ToList();
             MapOptions.camerasToAdd.ForEach(camera => {
index 8375a9fc1760b9f4f99c6f79154d0381b3a06a4e..0f895fb95d21f1d60a2b2bab0834b1bb4cfc7c3c 100644 (file)
@@ -159,6 +159,17 @@ namespace TheOtherRoles.Patches {
                         }
                     }
                 }
+
+                if (CustomOptionHolder.dynamicMap.getBool()) {
+                    // 0 = Skeld
+                    // 1 = Mira HQ
+                    // 2 = Polus
+                    // 3 = Dleks - deactivated
+                    // 4 = Airship
+                    List<byte> possibleMaps = new List<byte>(){0, 1, 2, 4};
+                    PlayerControl.GameOptions.MapId = possibleMaps[TheOtherRoles.rnd.Next(possibleMaps.Count)];
+                }
+
                 return continueStart;
             }
         }
index 1fc1dedccf3c9b5e20317371722bccab6ec59235..53371b827549e95736bd06b21c6db942e7d8d4b2 100644 (file)
@@ -371,58 +371,58 @@ namespace TheOtherRoles.Patches {
         }
 
         public static void updatePlayerInfo() {
-            foreach (PlayerControl p in PlayerControl.AllPlayerControls) {
-                if (p != PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead) continue;
-
-                Transform playerInfoTransform = p.nameText.transform.parent.FindChild("Info");
-                TMPro.TextMeshPro playerInfo = playerInfoTransform != null ? playerInfoTransform.GetComponent<TMPro.TextMeshPro>() : null;
-                if (playerInfo == null) {
-                    playerInfo = UnityEngine.Object.Instantiate(p.nameText, p.nameText.transform.parent);
-                    playerInfo.transform.localPosition += Vector3.up * 0.5f;
-                    playerInfo.fontSize *= 0.75f;
-                    playerInfo.gameObject.name = "Info";
-                }
-
-                PlayerVoteArea playerVoteArea = MeetingHud.Instance?.playerStates?.FirstOrDefault(x => x.TargetPlayerId == p.PlayerId);
-                Transform meetingInfoTransform = playerVoteArea != null ? playerVoteArea.NameText.transform.parent.FindChild("Info") : null;
-                TMPro.TextMeshPro meetingInfo = meetingInfoTransform != null ? meetingInfoTransform.GetComponent<TMPro.TextMeshPro>() : null;
-                if (meetingInfo == null && playerVoteArea != null) {
-                    meetingInfo = UnityEngine.Object.Instantiate(playerVoteArea.NameText, playerVoteArea.NameText.transform.parent);
-                    meetingInfo.transform.localPosition += Vector3.down * 0.20f;
-                    meetingInfo.fontSize *= 0.75f;
-                    meetingInfo.gameObject.name = "Info";
-                }
-
-                var (tasksCompleted, tasksTotal) = TasksHandler.taskInfo(p.Data);
-                string roleNames = RoleInfo.GetRole(p);
-                string taskInfo = tasksTotal > 0 ? $"<color=#FAD934FF>({tasksCompleted}/{tasksTotal})</color>" : "";
-
-                string playerInfoText = "";
-                string meetingInfoText = "";
-                if (p == PlayerControl.LocalPlayer) {
-                    playerInfoText = $"{roleNames}";
-                    if (DestroyableSingleton<TaskPanelBehaviour>.InstanceExists) {
-                        TMPro.TextMeshPro tabText = DestroyableSingleton<TaskPanelBehaviour>.Instance.tab.transform.FindChild("TabText_TMP").GetComponent<TMPro.TextMeshPro>();
-                        tabText.SetText($"Tasks {taskInfo}");
+            foreach (PlayerControl p in PlayerControl.AllPlayerControls) {         
+                if ((Lawyer.lawyerKnowsRole && PlayerControl.LocalPlayer == Lawyer.lawyer && p == Lawyer.target) || p == PlayerControl.LocalPlayer || PlayerControl.LocalPlayer.Data.IsDead) {
+                    Transform playerInfoTransform = p.nameText.transform.parent.FindChild("Info");
+                    TMPro.TextMeshPro playerInfo = playerInfoTransform != null ? playerInfoTransform.GetComponent<TMPro.TextMeshPro>() : null;
+                    if (playerInfo == null) {
+                        playerInfo = UnityEngine.Object.Instantiate(p.nameText, p.nameText.transform.parent);
+                        playerInfo.transform.localPosition += Vector3.up * 0.5f;
+                        playerInfo.fontSize *= 0.75f;
+                        playerInfo.gameObject.name = "Info";
+                    }
+
+                    PlayerVoteArea playerVoteArea = MeetingHud.Instance?.playerStates?.FirstOrDefault(x => x.TargetPlayerId == p.PlayerId);
+                    Transform meetingInfoTransform = playerVoteArea != null ? playerVoteArea.NameText.transform.parent.FindChild("Info") : null;
+                    TMPro.TextMeshPro meetingInfo = meetingInfoTransform != null ? meetingInfoTransform.GetComponent<TMPro.TextMeshPro>() : null;
+                    if (meetingInfo == null && playerVoteArea != null) {
+                        meetingInfo = UnityEngine.Object.Instantiate(playerVoteArea.NameText, playerVoteArea.NameText.transform.parent);
+                        meetingInfo.transform.localPosition += Vector3.down * 0.20f;
+                        meetingInfo.fontSize *= 0.75f;
+                        meetingInfo.gameObject.name = "Info";
+                    }
+
+                    var (tasksCompleted, tasksTotal) = TasksHandler.taskInfo(p.Data);
+                    string roleNames = RoleInfo.GetRolesString(p, true);
+                    string taskInfo = tasksTotal > 0 ? $"<color=#FAD934FF>({tasksCompleted}/{tasksTotal})</color>" : "";
+
+                    string playerInfoText = "";
+                    string meetingInfoText = "";
+                    if (p == PlayerControl.LocalPlayer) {
+                        playerInfoText = $"{roleNames}";
+                        if (DestroyableSingleton<TaskPanelBehaviour>.InstanceExists) {
+                            TMPro.TextMeshPro tabText = DestroyableSingleton<TaskPanelBehaviour>.Instance.tab.transform.FindChild("TabText_TMP").GetComponent<TMPro.TextMeshPro>();
+                            tabText.SetText($"Tasks {taskInfo}");
+                        }
+                        meetingInfoText = $"{roleNames} {taskInfo}".Trim();
+                    }
+                    else if (MapOptions.ghostsSeeRoles && MapOptions.ghostsSeeTasks) {
+                        playerInfoText = $"{roleNames} {taskInfo}".Trim();
+                        meetingInfoText = playerInfoText;
+                    }
+                    else if (MapOptions.ghostsSeeTasks) {
+                        playerInfoText = $"{taskInfo}".Trim();
+                        meetingInfoText = playerInfoText;
+                    }
+                    else if (MapOptions.ghostsSeeRoles || (Lawyer.lawyerKnowsRole && PlayerControl.LocalPlayer == Lawyer.lawyer && p == Lawyer.target)) {
+                        playerInfoText = $"{roleNames}";
+                        meetingInfoText = playerInfoText;
                     }
-                    meetingInfoText = $"{roleNames} {taskInfo}".Trim();
-                }
-                else if (MapOptions.ghostsSeeRoles && MapOptions.ghostsSeeTasks) {
-                    playerInfoText = $"{roleNames} {taskInfo}".Trim();
-                    meetingInfoText = playerInfoText;
-                }
-                else if (MapOptions.ghostsSeeTasks) {
-                    playerInfoText = $"{taskInfo}".Trim();
-                    meetingInfoText = playerInfoText;
-                }
-                else if (MapOptions.ghostsSeeRoles) {
-                    playerInfoText = $"{roleNames}";
-                    meetingInfoText = playerInfoText;
-                }
 
-                playerInfo.text = playerInfoText;
-                playerInfo.gameObject.SetActive(p.Visible);
-                if (meetingInfo != null) meetingInfo.text = MeetingHud.Instance.state == MeetingHud.VoteStates.Results ? "" : meetingInfoText;
+                    playerInfo.text = playerInfoText;
+                    playerInfo.gameObject.SetActive(p.Visible);
+                    if (meetingInfo != null) meetingInfo.text = MeetingHud.Instance.state == MeetingHud.VoteStates.Results ? "" : meetingInfoText;
+                }                
             }
         }
 
index f24490ba46c9312082e770c3308bdc7d7f6f4c09..b028ff848dcd5df59187ca44e92ad3da568e9982 100644 (file)
@@ -62,7 +62,7 @@ namespace TheOtherRoles
         // Main Controls
 
         ResetVaribles = 60,
-        ShareOptionSelection,
+        ShareOptions,
         ForceEnd,
         SetRole,
         VersionHandshake,
@@ -121,9 +121,17 @@ namespace TheOtherRoles
             setCustomButtonCooldowns();
         }
 
-        public static void shareOptionSelection(uint id, uint selection) {
-            CustomOption option = CustomOption.options.FirstOrDefault(option => option.id == (int)id);
-            option.updateSelection((int)selection);
+        public static void ShareOptions(int numberOfOptions, MessageReader reader) {            
+            try {
+                for (int i = 0; i < numberOfOptions; i++) {
+                    uint optionId = reader.ReadPackedUInt32();
+                    uint selection = reader.ReadPackedUInt32();
+                    CustomOption option = CustomOption.options.FirstOrDefault(option => option.id == (int)optionId);
+                    option.updateSelection((int)selection);
+                }
+            } catch (Exception e) {
+                TheOtherRolesPlugin.Logger.LogError("Error while deserializing options: " + e.Message);
+            }
         }
 
         public static void forceEnd() {
@@ -770,10 +778,8 @@ namespace TheOtherRoles
                 case (byte)CustomRPC.ResetVaribles:
                     RPCProcedure.resetVariables();
                     break;
-                case (byte)CustomRPC.ShareOptionSelection:
-                    uint id = reader.ReadPackedUInt32();
-                    uint selection = reader.ReadPackedUInt32();
-                    RPCProcedure.shareOptionSelection(id, selection);
+                case (byte)CustomRPC.ShareOptions:
+                    RPCProcedure.ShareOptions((int)reader.ReadPackedUInt32(), reader);
                     break;
                 case (byte)CustomRPC.ForceEnd:
                     RPCProcedure.forceEnd();
index 813ee4df7cc0394d02cf5140e17db4bd41562fbf..3e4196b1d2b1c183a4927f73f97a098362ddf015 100644 (file)
@@ -168,11 +168,10 @@ namespace TheOtherRoles
             return infos;
         }
 
-        public static String GetRole(PlayerControl p) {
+        public static String GetRolesString(PlayerControl p, bool useColors) {
             string roleName;
-            roleName = String.Join("", getRoleInfoForPlayer(p).Select(x => Helpers.cs(x.color, x.name)).ToArray());
-            if (roleName.Contains("Lover")) roleName.Replace("Lover", Helpers.cs(Lovers.color, " Lover"));
-            if (Lawyer.target != null && p.PlayerId == Lawyer.target.PlayerId && PlayerControl.LocalPlayer != Lawyer.target) roleName += Helpers.cs(Pursuer.color, " §");
+            roleName = String.Join(" ", getRoleInfoForPlayer(p).Select(x => useColors ? Helpers.cs(x.color, x.name) : x.name).ToArray());
+            if (Lawyer.target != null && p.PlayerId == Lawyer.target.PlayerId && PlayerControl.LocalPlayer != Lawyer.target) roleName += (useColors ? Helpers.cs(Pursuer.color, " §") : " §");
             return roleName;
         }
     }
index db069c14d1af39ab53351c6d0fadfe5cd40705ab..7daa584a68c318b3b832496cc39affa0b7fee809 100644 (file)
@@ -1142,6 +1142,7 @@ namespace TheOtherRoles
         public static float vision = 1f;
         public static bool winsAfterMeetings = false;
         public static int neededMeetings = 4;
+        public static bool lawyerKnowsRole = false;
 
         public static Sprite getTargetSprite() {
             if (targetSprite) return targetSprite;
@@ -1159,6 +1160,7 @@ namespace TheOtherRoles
             winsAfterMeetings = CustomOptionHolder.lawyerWinsAfterMeetings.getBool();
             neededMeetings = Mathf.RoundToInt(CustomOptionHolder.lawyerNeededMeetings.getFloat());
             vision = CustomOptionHolder.lawyerVision.getFloat();
+            lawyerKnowsRole = CustomOptionHolder.lawyerKnowsRole.getBool();
         }
     }
 
@@ -1203,6 +1205,7 @@ namespace TheOtherRoles
         public static float currentCooldownAddition = 0f;
         public static bool canSpellAnyone = false;
         public static bool triggerBothCooldowns = true;
+        public static bool witchVoteSavesTargets = true;
 
         private static Sprite buttonSprite;
         public static Sprite getButtonSprite() {
@@ -1229,6 +1232,7 @@ namespace TheOtherRoles
             canSpellAnyone = CustomOptionHolder.witchCanSpellAnyone.getBool();
             spellCastingDuration = CustomOptionHolder.witchSpellCastingDuration.getFloat();
             triggerBothCooldowns = CustomOptionHolder.witchTriggerBothCooldowns.getBool();
+            witchVoteSavesTargets = CustomOptionHolder.witchVoteSavesTargets.getBool();
         }
     }
 }
\ No newline at end of file
index 920751d69c9583fa96f50706582edbc4658ea572..fa3ebc8626478855e9b6a562b3980c4b0af6af3e 100644 (file)
@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
     <PropertyGroup>
         <TargetFramework>netstandard2.1</TargetFramework>
-        <Version>3.2.1</Version>
+        <Version>3.2.2</Version>
         <Description>TheOtherRoles</Description>
         <Authors>Eisbison</Authors>
     </PropertyGroup>