From 9c36355058321e57ad8088f68393673c2009aa05 Mon Sep 17 00:00:00 2001 From: gendelo3 Date: Wed, 15 May 2024 08:26:18 +0200 Subject: [PATCH] Preparation vor Update v4.5.3 --- README.md | 50 +++++- TheOtherRoles/Buttons.cs | 159 +++++++++++++++++- TheOtherRoles/CustomGameModes/PropHunt.cs | 2 +- TheOtherRoles/CustomOptionHolder.cs | 30 +++- TheOtherRoles/Helpers.cs | 20 +++ TheOtherRoles/Main.cs | 2 +- TheOtherRoles/Modules/ChatCommands.cs | 2 +- TheOtherRoles/Modules/CustomOptions.cs | 8 +- TheOtherRoles/Objects/Arrow.cs | 34 ++++ TheOtherRoles/Objects/CustomButton.cs | 2 +- TheOtherRoles/Objects/Silhouette.cs | 82 +++++++++ TheOtherRoles/Objects/Trap.cs | 2 + TheOtherRoles/Patches/CredentialsPatch.cs | 28 +-- TheOtherRoles/Patches/DangerMeterPatch.cs | 21 +++ TheOtherRoles/Patches/ExileControllerPatch.cs | 3 + TheOtherRoles/Patches/MapBehaviourPatch.cs | 28 +++ TheOtherRoles/Patches/MeetingPatch.cs | 32 ++++ TheOtherRoles/Patches/PlayerControlPatch.cs | 18 +- TheOtherRoles/Patches/RoleAssignmentPatch.cs | 1 + TheOtherRoles/Patches/UpdatePatch.cs | 1 + TheOtherRoles/Patches/UsablesPatch.cs | 4 + TheOtherRoles/RPC.cs | 52 ++++++ TheOtherRoles/Resources/Silhouette.png | Bin 0 -> 6525 bytes .../Resources/YoyoBlinkButtonSprite.png | Bin 0 -> 16744 bytes .../Resources/YoyoMarkButtonSprite.png | Bin 0 -> 17641 bytes TheOtherRoles/RoleInfo.cs | 3 + TheOtherRoles/SubmergedCompatibility.cs | 3 - TheOtherRoles/TheOtherRoles.cs | 67 +++++++- TheOtherRoles/TheOtherRoles.csproj | 4 +- TheOtherRoles/packages.lock.json | 71 ++++---- nuget.config | 1 - 31 files changed, 654 insertions(+), 76 deletions(-) create mode 100644 TheOtherRoles/Objects/Silhouette.cs create mode 100644 TheOtherRoles/Patches/DangerMeterPatch.cs create mode 100644 TheOtherRoles/Resources/Silhouette.png create mode 100644 TheOtherRoles/Resources/YoyoBlinkButtonSprite.png create mode 100644 TheOtherRoles/Resources/YoyoMarkButtonSprite.png diff --git a/README.md b/README.md index 4c577fea5..4e04661ad 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,8 @@ Even more roles are coming soon. :) | [Witch](#witch) | [Tracker](#tracker) | | | | [Ninja](#ninja) | [Snitch](#snitch) | | | | [Bomber](#bomber) | [Spy](#spy) | | | -| [Evil Guesser](#guesser) | [Portalmaker](#portalmaker) | | | -| | [Security Guard](#security-guard) | | | +| [Yo-Yo](#yoyo) | [Portalmaker](#portalmaker) | | | +| [Evil Guesser](#guesser) | [Security Guard](#security-guard) | | | | | [Medium](#medium) | | | | | [Trapper](#trapper) | | | | | [Nice Guesser](#guesser) | | | @@ -42,6 +42,7 @@ The [Role Assignment](#role-assignment) section explains how the roles are being # Releases | Among Us - Version| Mod Version | Link | |----------|-------------|-----------------| +| 2024.3.5s| v4.5.3| [Download](https://github.com/TheOtherRolesAU/TheOtherRoles/releases/download/v4.5.3/TheOtherRoles.zip) | 2024.3.5s| v4.5.2| [Download](https://github.com/TheOtherRolesAU/TheOtherRoles/releases/download/v4.5.2/TheOtherRoles.zip) | 2023.11.28s| v4.5.1| [Download](https://github.com/TheOtherRolesAU/TheOtherRoles/releases/download/v4.5.1/TheOtherRoles.zip) @@ -132,6 +133,19 @@ The [Role Assignment](#role-assignment) section explains how the roles are being
Click to show the Changelog +**Version 4.5.3** +- Added a new role: Yo-Yo (Impostor) - Mark and blink to a position, then blink back to the start of the blink! +- Added a new option to Jackal And Sidekick: Jackal / Sidekick can sabotage lights (cooldown syncs with Imp Sabotages) +- Added a new option: Block Dead Impostor From Sabotaging +- Added a new option to the Tracker: Tracking Type: Arrow, Proximity Meter, Both +- Added a new feature: The host is always displayed to all players, in the meeting ui and ping tracker text +- Added a new feature: Ghosts see the icons of all players on their map +- Fixed the chat command to ban a player from the lobby `/ban` +- Fixed an issue where killing in PropHunt crashed the lobby +- Fixed an issue with the very short kill distance in Vanilla HideNSeek +- Changed trapper trap: is now visible with transparency to the trapper while inactive + + **Version 4.5.2** - Updated to Among Us version 2024.3.5s (various small / "long" features and bugfixes) - Updated BepInEx dependency to 688 @@ -1228,6 +1242,31 @@ Crewmates can defuse a bomb depending on the settings. | Bomb Is Active After | ----------------------- +## YoYo +### **Team: Impostors** +The Yo-Yo is an Impostor who has the ability mark a position and later blink (teleport) to this position.\ +After the initial blink, the Yo-Yo has a fixed amount of time (option) to do whatever they want, before automatically blinking back to the starting point of the first blink.\ +Each blink leaves behind a silhouette with configurable transparency. The silhouette is very hard to see.\ +The Yo-Yo may also have access to a mobile admin table, depending on the settings. + +**NOTE:** + +- The marked position for the first jump's target is displayed to the Yo-Yo and ghosts only. +- The silhouette of the first blink stays (almost) until the Yo-Yo returns +- The silhouette of the second blink (return) stays for 5 seconds + +### Game Options +| Name | Description | +|----------|:-------------:| +| Yo-Yo Spawn Chance | - +| Blink Duration | - +| Mark Location Cooldown | - +| Marked Location Stays After Meeting | - +| Has Admin Table | - +| Admin Table Cooldown | - +| Silhouette Visibility | - +----------------------- + ## Guesser ### **Team: Crewmates or Impostors** The Guesser can be a Crewmate or an Impostor (depending on the settings).\ @@ -1321,7 +1360,12 @@ If both Impostors and Jackals are in the game, the game continues even if all Cr | Jackal/Sidekick Kill Cooldown | Kill cooldown | | Jackal Create Sidekick Cooldown | Cooldown before a Sidekick can be created | | Jackal can use vents | Yes/No | +| Jackal can sabotage Lights | Yes/No | | Jackal can create a Sidekick | Yes/No | +| Sidekick gets promoted to Jackal on Jackal Death | Yes/No | +| Sidekick can kill | Yes/No | +| Sidekick can Vent | Yes/No | +| Jackal can sabotage Lights | Yes/No | | Jackals promoted from Sidekick can create a Sidekick | Yes/No (to prevent the Jackal team from growing) | | Jackals can make an Impostor to their Sidekick | Yes/No (to prevent a Jackal from turning an Impostor into a Sidekick, if they use the ability on an Impostor they see the Impostor as Sidekick, but the Impostor isn't converted to Sidekick. If this option is set to "No" Jackal and Sidekick can kill each other.) | | Jackal and Sidekick have Impostor vision | - | @@ -1685,6 +1729,7 @@ While accessing those mobile gadgets, the Hacker is not able to move. The Tracker can select one player to track. Depending on the options the Tracker can track a different person after each meeting or the Tracker tracks the same person for the whole game.\ An arrow points to the last tracked position of the player.\ The arrow updates its position every few seconds (configurable).\ +By an option, the arrow can be replaced or combined with the Proximity Tracker from Hide N Seek.\ Depending on the options, the Tracker has another ability: They can track all corpses on the map for a set amount of time. They will keep tracking corpses, even if they were cleaned or eaten by the Vulture. **NOTE** @@ -1699,6 +1744,7 @@ Depending on the options, the Tracker has another ability: They can track all co | Tracker Can Track Corpses | - | Corpses Tracking Cooldown | - | Corpses Tracking Duration | - +| How Tracker Gets Target Location| - ----------------------- ## Snitch diff --git a/TheOtherRoles/Buttons.cs b/TheOtherRoles/Buttons.cs index c9e3b8544..763bbda98 100644 --- a/TheOtherRoles/Buttons.cs +++ b/TheOtherRoles/Buttons.cs @@ -40,6 +40,7 @@ static class HudManagerStartPatch public static CustomButton jackalKillButton; public static CustomButton sidekickKillButton; private static CustomButton jackalSidekickButton; + public static CustomButton jackalAndSidekickSabotageLightsButton; private static CustomButton eraserButton; private static CustomButton placeJackInTheBoxButton; private static CustomButton lightsOutButton; @@ -57,6 +58,8 @@ static class HudManagerStartPatch public static CustomButton thiefKillButton; public static CustomButton trapperButton; public static CustomButton bomberButton; + public static CustomButton yoyoButton; + public static CustomButton yoyoAdminTableButton; public static CustomButton defuseButton; public static CustomButton zoomOutButton; private static CustomButton hunterLighterButton; @@ -136,6 +139,9 @@ public static void setCustomButtonCooldowns() { mayorMeetingButton.MaxTimer = GameManager.Instance.LogicOptions.GetEmergencyCooldown(); trapperButton.MaxTimer = Trapper.cooldown; bomberButton.MaxTimer = Bomber.bombCooldown; + yoyoButton.MaxTimer = Yoyo.markCooldown; + yoyoAdminTableButton.MaxTimer = Yoyo.adminCooldown; + yoyoAdminTableButton.EffectDuration = 10f; hunterLighterButton.MaxTimer = Hunter.lightCooldown; hunterAdminTableButton.MaxTimer = Hunter.AdminCooldown; hunterArrowButton.MaxTimer = Hunter.ArrowCooldown; @@ -1065,6 +1071,27 @@ public static void createButtonsPostfix(HudManager __instance) { KeyCode.Q ); + jackalAndSidekickSabotageLightsButton = new CustomButton( + () => { + ShipStatus.Instance.RpcUpdateSystem(SystemTypes.Sabotage, (byte)SystemTypes.Electrical); + }, + () => { + return (Jackal.jackal != null && Jackal.jackal == CachedPlayer.LocalPlayer.PlayerControl && Jackal.canSabotageLights || + Sidekick.sidekick != null && Sidekick.sidekick == CachedPlayer.LocalPlayer.PlayerControl && Sidekick.canSabotageLights) && !CachedPlayer.LocalPlayer.Data.IsDead; + }, + () => { + if (Helpers.sabotageTimer() > jackalAndSidekickSabotageLightsButton.Timer || Helpers.sabotageActive()) + jackalAndSidekickSabotageLightsButton.Timer = Helpers.sabotageTimer() + 5f; // this will give imps time to do another sabotage. + return Helpers.canUseSabotage();}, + () => { + jackalAndSidekickSabotageLightsButton.Timer = Helpers.sabotageTimer() + 5f; + }, + Trickster.getLightsOutButtonSprite(), + CustomButton.ButtonPositions.upperRowCenter, + __instance, + KeyCode.G + ); + // Eraser erase button eraserButton = new CustomButton( () => { @@ -1894,10 +1921,140 @@ public static void createButtonsPostfix(HudManager __instance) { trapperChargesText.transform.localScale = Vector3.one * 0.5f; trapperChargesText.transform.localPosition += new Vector3(-0.05f, 0.7f, 0); + + // Yoyo button + yoyoButton = new CustomButton( + () => { + var pos = CachedPlayer.LocalPlayer.transform.position; + byte[] buff = new byte[sizeof(float) * 2]; + Buffer.BlockCopy(BitConverter.GetBytes(pos.x), 0, buff, 0 * sizeof(float), sizeof(float)); + Buffer.BlockCopy(BitConverter.GetBytes(pos.y), 0, buff, 1 * sizeof(float), sizeof(float)); + + if (Yoyo.markedLocation == null) { + TheOtherRolesPlugin.Logger.LogMessage($"marked location is null in button press"); + MessageWriter writer = AmongUsClient.Instance.StartRpc(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.YoyoMarkLocation, Hazel.SendOption.Reliable); + writer.WriteBytesAndSize(buff); + writer.EndMessage(); + RPCProcedure.yoyoMarkLocation(buff); + SoundEffectsManager.play("tricksterPlaceBox"); + yoyoButton.Sprite = Yoyo.getBlinkButtonSprite(); + yoyoButton.Timer = 10f; + yoyoButton.HasEffect = false; + yoyoButton.buttonText = "Blink"; + } else { + TheOtherRolesPlugin.Logger.LogMessage("in else for some reason"); + // Jump to location + TheOtherRolesPlugin.Logger.LogMessage($"trying to blink!"); + var exit = (Vector3)Yoyo.markedLocation; + if (SubmergedCompatibility.IsSubmerged) { + SubmergedCompatibility.ChangeFloor(exit.y > -7); + } + MessageWriter writer = AmongUsClient.Instance.StartRpc(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.YoyoBlink, Hazel.SendOption.Reliable); + writer.Write(Byte.MaxValue); + writer.WriteBytesAndSize(buff); + writer.EndMessage(); + RPCProcedure.yoyoBlink(true, buff); + yoyoButton.EffectDuration = Yoyo.blinkDuration; + yoyoButton.Timer = 10f; + yoyoButton.HasEffect = true; + yoyoButton.buttonText = "Returning..."; + SoundEffectsManager.play("morphlingMorph"); + } + }, + () => { return Yoyo.yoyo != null && Yoyo.yoyo == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead; }, + () => { return CachedPlayer.LocalPlayer.PlayerControl.CanMove; }, + () => { + if (Yoyo.markStaysOverMeeting) { + yoyoButton.Timer = 10f; + } else { + Yoyo.markedLocation = null; + yoyoButton.Timer = yoyoButton.MaxTimer; + yoyoButton.Sprite = Yoyo.getMarkButtonSprite(); + yoyoButton.buttonText = "Mark Location"; + } + }, + Yoyo.getMarkButtonSprite(), + CustomButton.ButtonPositions.upperRowLeft, + __instance, + KeyCode.F, + false, + Yoyo.blinkDuration, + () => { + if (TransportationToolPatches.isUsingTransportation(Yoyo.yoyo)) { + yoyoButton.Timer = 0.5f; + yoyoButton.DeputyTimer = 0.5f; + yoyoButton.isEffectActive = true; + yoyoButton.actionButton.cooldownTimerText.color = new Color(0F, 0.8F, 0F); + return; + } else if (Yoyo.yoyo.inVent) { + __instance.ImpostorVentButton.DoClick(); + } + + // jump back! + var pos = CachedPlayer.LocalPlayer.transform.position; + byte[] buff = new byte[sizeof(float) * 2]; + Buffer.BlockCopy(BitConverter.GetBytes(pos.x), 0, buff, 0 * sizeof(float), sizeof(float)); + Buffer.BlockCopy(BitConverter.GetBytes(pos.y), 0, buff, 1 * sizeof(float), sizeof(float)); + var exit = (Vector3)Yoyo.markedLocation; + if (SubmergedCompatibility.IsSubmerged) { + SubmergedCompatibility.ChangeFloor(exit.y > -7); + } + MessageWriter writer = AmongUsClient.Instance.StartRpc(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.YoyoBlink, Hazel.SendOption.Reliable); + writer.Write((byte)0); + writer.WriteBytesAndSize(buff); + writer.EndMessage(); + RPCProcedure.yoyoBlink(false, buff); + + yoyoButton.Timer = yoyoButton.MaxTimer; + yoyoButton.isEffectActive = false; + yoyoButton.actionButton.cooldownTimerText.color = Palette.EnabledColor; + yoyoButton.HasEffect = false; + yoyoButton.Sprite = Yoyo.getMarkButtonSprite(); + yoyoButton.buttonText = "Mark Location"; + SoundEffectsManager.play("morphlingMorph"); + if (Minigame.Instance) { + Minigame.Instance.Close(); + } + }, + buttonText: "Mark Location" + ); + + yoyoAdminTableButton = new CustomButton( + () => { + if (!MapBehaviour.Instance || !MapBehaviour.Instance.isActiveAndEnabled) { + HudManager __instance = FastDestroyableSingleton.Instance; + __instance.InitMap(); + MapBehaviour.Instance.ShowCountOverlay(allowedToMove: true, showLivePlayerPosition: true, includeDeadBodies: true); + } + }, + () => { return Yoyo.yoyo != null && Yoyo.yoyo == CachedPlayer.LocalPlayer.PlayerControl && Yoyo.hasAdminTable && !CachedPlayer.LocalPlayer.Data.IsDead; }, + () => { + return true; + }, + () => { + yoyoAdminTableButton.Timer = yoyoAdminTableButton.MaxTimer; + yoyoAdminTableButton.isEffectActive = false; + yoyoAdminTableButton.actionButton.cooldownTimerText.color = Palette.EnabledColor; + }, + Hacker.getAdminSprite(), + CustomButton.ButtonPositions.lowerRowCenter, + __instance, + KeyCode.G, + true, + 0f, + () => { + yoyoAdminTableButton.Timer = yoyoAdminTableButton.MaxTimer; + if (MapBehaviour.Instance && MapBehaviour.Instance.isActiveAndEnabled) MapBehaviour.Instance.Close(); + }, + GameOptionsManager.Instance.currentNormalGameOptions.MapId == 3, + "ADMIN" + ); + + zoomOutButton = new CustomButton( () => { Helpers.toggleZoom(); }, - () => { if (CachedPlayer.LocalPlayer.PlayerControl == null || !CachedPlayer.LocalPlayer.Data.IsDead || CachedPlayer.LocalPlayer.Data.Role.IsImpostor) return false; + () => { if (CachedPlayer.LocalPlayer.PlayerControl == null || !CachedPlayer.LocalPlayer.Data.IsDead || (CachedPlayer.LocalPlayer.Data.Role.IsImpostor && !CustomOptionHolder.deadImpsBlockSabotage.getBool())) return false; var (playerCompleted, playerTotal) = TasksHandler.taskInfo(CachedPlayer.LocalPlayer.Data); int numberOfLeftTasks = playerTotal - playerCompleted; return numberOfLeftTasks <= 0 || !CustomOptionHolder.finishTasksBeforeHauntingOrZoomingOut.getBool(); diff --git a/TheOtherRoles/CustomGameModes/PropHunt.cs b/TheOtherRoles/CustomGameModes/PropHunt.cs index 6afac7af3..633e14002 100644 --- a/TheOtherRoles/CustomGameModes/PropHunt.cs +++ b/TheOtherRoles/CustomGameModes/PropHunt.cs @@ -544,7 +544,7 @@ public static bool AdminUsePostfix(MapConsole __instance) { [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.MurderPlayer))] [HarmonyPostfix] public static void MurderPlayerPostfix(PlayerControl __instance, [HarmonyArgument(0)] PlayerControl target) { - if (!PropHunt.isPropHuntGM) return; + if (!PropHunt.isPropHuntGM || target != CachedPlayer.LocalPlayer.PlayerControl) return; try { target.NetTransform.RpcSnapTo(__instance.transform.position); } catch { } diff --git a/TheOtherRoles/CustomOptionHolder.cs b/TheOtherRoles/CustomOptionHolder.cs index 0578dcf30..505590c0e 100644 --- a/TheOtherRoles/CustomOptionHolder.cs +++ b/TheOtherRoles/CustomOptionHolder.cs @@ -23,6 +23,7 @@ public class CustomOptionHolder { public static CustomOption anyPlayerCanStopStart; public static CustomOption enableEventMode; + public static CustomOption deadImpsBlockSabotage; public static CustomOption mafiaSpawnRate; public static CustomOption janitorCooldown; @@ -63,11 +64,13 @@ public class CustomOptionHolder { public static CustomOption jackalSpawnRate; public static CustomOption jackalKillCooldown; public static CustomOption jackalCreateSidekickCooldown; + public static CustomOption jackalCanSabotageLights; public static CustomOption jackalCanUseVents; public static CustomOption jackalCanCreateSidekick; public static CustomOption sidekickPromotesToJackal; public static CustomOption sidekickCanKill; public static CustomOption sidekickCanUseVents; + public static CustomOption sidekickCanSabotageLights; public static CustomOption jackalPromotedFromSidekickCanCreateSidekick; public static CustomOption jackalCanCreateSidekickFromImpostor; public static CustomOption jackalAndSidekickHaveImpostorVision; @@ -174,6 +177,7 @@ public class CustomOptionHolder { public static CustomOption trackerCanTrackCorpses; public static CustomOption trackerCorpsesTrackingCooldown; public static CustomOption trackerCorpsesTrackingDuration; + public static CustomOption trackerTrackingMethod; public static CustomOption snitchSpawnRate; public static CustomOption snitchLeftTasksForReveal; @@ -254,6 +258,16 @@ public class CustomOptionHolder { public static CustomOption bomberBombCooldown; public static CustomOption bomberBombActiveAfter; + public static CustomOption yoyoSpawnRate; + public static CustomOption yoyoBlinkDuration; + public static CustomOption yoyoMarkCooldown; + public static CustomOption yoyoMarkStaysOverMeeting; + public static CustomOption yoyoHasAdminTable; + public static CustomOption yoyoAdminTableCooldown; + public static CustomOption yoyoSilhouetteVisibility; + + + public static CustomOption modifiersAreHidden; public static CustomOption modifierBait; @@ -414,7 +428,7 @@ public static void Load() { presetSelection = CustomOption.Create(0, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Preset"), presets, null, true); activateRoles = CustomOption.Create(1, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Enable Mod Roles And Block Vanilla Roles"), true, null, true); anyPlayerCanStopStart = CustomOption.Create(2, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Any Player Can Stop The Start"), false, null, false); - + if (Utilities.EventUtility.canBeEnabled) enableEventMode = CustomOption.Create(10423, Types.General, cs(Color.green, "Enable Special Mode"), true, null, true); // Using new id's for the options to not break compatibilty with older versions @@ -490,6 +504,16 @@ public static void Load() { bomberBombCooldown = CustomOption.Create(465, Types.Impostor, "Bomb Cooldown", 15f, 2.5f, 30f, 2.5f, bomberSpawnRate); bomberBombActiveAfter = CustomOption.Create(466, Types.Impostor, "Bomb Is Active After", 3f, 0.5f, 15f, 0.5f, bomberSpawnRate); + + yoyoSpawnRate = CustomOption.Create(470, Types.Impostor, cs(Yoyo.color, "Yo-Yo"), rates, null, true); + yoyoBlinkDuration = CustomOption.Create(471, Types.Impostor, "Blink Duration", 20f, 2.5f, 120f, 2.5f, yoyoSpawnRate); + yoyoMarkCooldown = CustomOption.Create(472, Types.Impostor, "Mark Location Cooldown", 20f, 2.5f, 120f, 2.5f, yoyoSpawnRate); + yoyoMarkStaysOverMeeting = CustomOption.Create(473, Types.Impostor, "Marked Location Stays After Meeting", true, yoyoSpawnRate); + yoyoHasAdminTable = CustomOption.Create(474, Types.Impostor, "Has Admin Table", true, yoyoSpawnRate); + yoyoAdminTableCooldown = CustomOption.Create(475, Types.Impostor, "Admin Table Cooldown", 20f, 2.5f, 120f, 2.5f, yoyoHasAdminTable); + yoyoSilhouetteVisibility = CustomOption.Create(476, Types.Impostor, "Silhouette Visibility", new string[] { "0%", "10%", "20%", "30%", "40%", "50%" }, yoyoSpawnRate); + + guesserSpawnRate = CustomOption.Create(310, Types.Neutral, cs(Guesser.color, "Guesser"), rates, null, true); guesserIsImpGuesserRate = CustomOption.Create(311, Types.Neutral, "Chance That The Guesser Is An Impostor", rates, guesserSpawnRate); guesserNumberOfShots = CustomOption.Create(312, Types.Neutral, "Guesser Number Of Shots", 2f, 1f, 15f, 1f, guesserSpawnRate); @@ -511,10 +535,12 @@ public static void Load() { jackalKillCooldown = CustomOption.Create(221, Types.Neutral, "Jackal/Sidekick Kill Cooldown", 30f, 10f, 60f, 2.5f, jackalSpawnRate); jackalCreateSidekickCooldown = CustomOption.Create(222, Types.Neutral, "Jackal Create Sidekick Cooldown", 30f, 10f, 60f, 2.5f, jackalSpawnRate); jackalCanUseVents = CustomOption.Create(223, Types.Neutral, "Jackal Can Use Vents", true, jackalSpawnRate); + jackalCanSabotageLights = CustomOption.Create(431, Types.Neutral, "Jackal Can Sabotage Lights", true, jackalSpawnRate); jackalCanCreateSidekick = CustomOption.Create(224, Types.Neutral, "Jackal Can Create A Sidekick", false, jackalSpawnRate); sidekickPromotesToJackal = CustomOption.Create(225, Types.Neutral, "Sidekick Gets Promoted To Jackal On Jackal Death", false, jackalCanCreateSidekick); sidekickCanKill = CustomOption.Create(226, Types.Neutral, "Sidekick Can Kill", false, jackalCanCreateSidekick); sidekickCanUseVents = CustomOption.Create(227, Types.Neutral, "Sidekick Can Use Vents", true, jackalCanCreateSidekick); + sidekickCanSabotageLights = CustomOption.Create(432, Types.Neutral, "Sidekick Can Sabotage Lights", true, jackalCanCreateSidekick); jackalPromotedFromSidekickCanCreateSidekick = CustomOption.Create(228, Types.Neutral, "Jackals Promoted From Sidekick Can Create A Sidekick", true, sidekickPromotesToJackal); jackalCanCreateSidekickFromImpostor = CustomOption.Create(229, Types.Neutral, "Jackals Can Make An Impostor To His Sidekick", true, jackalCanCreateSidekick); jackalAndSidekickHaveImpostorVision = CustomOption.Create(430, Types.Neutral, "Jackal And Sidekick Have Impostor Vision", false, jackalSpawnRate); @@ -608,6 +634,7 @@ public static void Load() { trackerCanTrackCorpses = CustomOption.Create(203, Types.Crewmate, "Tracker Can Track Corpses", true, trackerSpawnRate); trackerCorpsesTrackingCooldown = CustomOption.Create(204, Types.Crewmate, "Corpses Tracking Cooldown", 30f, 5f, 120f, 5f, trackerCanTrackCorpses); trackerCorpsesTrackingDuration = CustomOption.Create(205, Types.Crewmate, "Corpses Tracking Duration", 5f, 2.5f, 30f, 2.5f, trackerCanTrackCorpses); + trackerTrackingMethod = CustomOption.Create(206, Types.Crewmate, "How Tracker Gets Target Location", new string[] { "Arrow Only", "Proximity Dectector Only", "Arrow + Proximity" }, trackerSpawnRate); snitchSpawnRate = CustomOption.Create(210, Types.Crewmate, cs(Snitch.color, "Snitch"), rates, null, true); snitchLeftTasksForReveal = CustomOption.Create(219, Types.Crewmate, "Task Count Where The Snitch Will Be Revealed", 5f, 0f, 25f, 1f, snitchSpawnRate); @@ -793,6 +820,7 @@ public static void Load() { finishTasksBeforeHauntingOrZoomingOut = CustomOption.Create(9, Types.General, "Finish Tasks Before Haunting Or Zooming Out", true); camsNightVision = CustomOption.Create(11, Types.General, "Cams Switch To Night Vision If Lights Are Off", false, null, true); camsNoNightVisionIfImpVision = CustomOption.Create(12, Types.General, "Impostor Vision Ignores Night Vision Cams", false, camsNightVision, false); + deadImpsBlockSabotage = CustomOption.Create(13, Types.General, cs(Palette.ImpostorRed, "Block Dead Impostor From Sabotaging"), false, null, false); dynamicMap = CustomOption.Create(500, Types.General, "Play On A Random Map", false, null, true); diff --git a/TheOtherRoles/Helpers.cs b/TheOtherRoles/Helpers.cs index d9dc79cb9..3071494f2 100644 --- a/TheOtherRoles/Helpers.cs +++ b/TheOtherRoles/Helpers.cs @@ -277,6 +277,26 @@ public static bool MushroomSabotageActive() { return CachedPlayer.LocalPlayer.PlayerControl.myTasks.ToArray().Any((x) => x.TaskType == TaskTypes.MushroomMixupSabotage); } + + public static bool sabotageActive() { + var sabSystem = ShipStatus.Instance.Systems[SystemTypes.Sabotage].CastFast(); + return sabSystem.AnyActive; + } + + public static float sabotageTimer() { + var sabSystem = ShipStatus.Instance.Systems[SystemTypes.Sabotage].CastFast(); + return sabSystem.Timer; + } + public static bool canUseSabotage() { + var sabSystem = ShipStatus.Instance.Systems[SystemTypes.Sabotage].CastFast(); + ISystemType systemType; + IActivatable doors = null; + if (ShipStatus.Instance.Systems.TryGetValue(SystemTypes.Doors, out systemType)) { + doors = systemType.CastFast(); + } + return GameManager.Instance.SabotagesEnabled() && sabSystem.Timer <= 0f && !sabSystem.AnyActive && !(doors != null && doors.IsActive); + } + public static void setSemiTransparent(this PoolablePlayer player, bool value, float alpha=0.25f) { alpha = value ? alpha : 1f; foreach (SpriteRenderer r in player.gameObject.GetComponentsInChildren()) diff --git a/TheOtherRoles/Main.cs b/TheOtherRoles/Main.cs index 5ccb3c555..bc502cea0 100644 --- a/TheOtherRoles/Main.cs +++ b/TheOtherRoles/Main.cs @@ -33,7 +33,7 @@ namespace TheOtherRoles public class TheOtherRolesPlugin : BasePlugin { public const string Id = "me.eisbison.theotherroles"; - public const string VersionString = "4.5.2"; + public const string VersionString = "4.5.3"; public static uint betaDays = 0; // amount of days for the build to be usable (0 for infinite!) public static Version Version = Version.Parse(VersionString); diff --git a/TheOtherRoles/Modules/ChatCommands.cs b/TheOtherRoles/Modules/ChatCommands.cs index 4b0c2b6c2..4cabe69da 100644 --- a/TheOtherRoles/Modules/ChatCommands.cs +++ b/TheOtherRoles/Modules/ChatCommands.cs @@ -27,7 +27,7 @@ static bool Prefix(ChatController __instance) { } } } else if (text.ToLower().StartsWith("/ban ")) { - string playerName = text.Substring(6); + string playerName = text.Substring(5); PlayerControl target = CachedPlayer.AllPlayers.FirstOrDefault(x => x.Data.PlayerName.Equals(playerName)); if (target != null && AmongUsClient.Instance != null && AmongUsClient.Instance.CanBan()) { var client = AmongUsClient.Instance.GetClient(target.OwnerId); diff --git a/TheOtherRoles/Modules/CustomOptions.cs b/TheOtherRoles/Modules/CustomOptions.cs index 61bf0f3e9..eec9887f9 100644 --- a/TheOtherRoles/Modules/CustomOptions.cs +++ b/TheOtherRoles/Modules/CustomOptions.cs @@ -1188,7 +1188,13 @@ public static void Postfix(StringOption __instance) public static void Prefix(ref StringNames stringName, ref string value) { if (stringName == StringNames.GameKillDistance) { - var index = GameOptionsManager.Instance.currentNormalGameOptions.KillDistance; + int index; + if (GameOptionsManager.Instance.currentGameMode == GameModes.Normal) { + index = GameOptionsManager.Instance.currentNormalGameOptions.KillDistance; + } + else { + index = GameOptionsManager.Instance.currentHideNSeekGameOptions.KillDistance; + } value = GameOptionsData.KillDistanceStrings[index]; } } diff --git a/TheOtherRoles/Objects/Arrow.cs b/TheOtherRoles/Objects/Arrow.cs index e10e8a65d..5b66dbb7e 100644 --- a/TheOtherRoles/Objects/Arrow.cs +++ b/TheOtherRoles/Objects/Arrow.cs @@ -41,5 +41,39 @@ public void Update(Vector3 target, Color? color = null) arrowBehaviour.target = target; arrowBehaviour.Update(); } + + public static void UpdateProximity(Vector3 position) { + if (!GameManager.Instance.GameHasStarted) return; + + if (Tracker.DangerMeterParent == null) { + Tracker.DangerMeterParent = GameObject.Instantiate(GameObject.Find("ImpostorDetector"), HudManager.Instance.transform); + Tracker.Meter = Tracker.DangerMeterParent.transform.GetChild(0).GetComponent(); + Tracker.DangerMeterParent.transform.localPosition = new(3.7f, -1.6f, 0); + var backgroundrend = Tracker.DangerMeterParent.transform.GetChild(0).GetChild(0).GetComponent(); + backgroundrend.color = backgroundrend.color.SetAlpha(0.5f); + } + Tracker.DangerMeterParent.SetActive(MeetingHud.Instance == null && LobbyBehaviour.Instance == null && !Tracker.tracker.Data.IsDead && Tracker.tracked != null); + Tracker.Meter.gameObject.SetActive(MeetingHud.Instance == null && LobbyBehaviour.Instance == null && !Tracker.tracker.Data.IsDead && Tracker.tracked != null); + if (Tracker.tracker.Data.IsDead) return; + if (Tracker.tracked == null) { + Tracker.Meter.SetDangerValue(0, 0); + return; + } + if (Tracker.DangerMeterParent.transform.localPosition.x != 3.7f) Tracker.DangerMeterParent.transform.localPosition = new(3.7f, -1.6f, 0); + float num = float.MaxValue; + float dangerLevel1; + float dangerLevel2; + + float sqrMagnitude = (position - Tracker.tracker.transform.position).sqrMagnitude; + if (sqrMagnitude < (55 * GameOptionsManager.Instance.currentNormalGameOptions.PlayerSpeedMod) && num > sqrMagnitude) + { + num = sqrMagnitude; + } + + dangerLevel1 = Mathf.Clamp01((55 - num) / (55 - 15 * GameOptionsManager.Instance.currentNormalGameOptions.PlayerSpeedMod)); + dangerLevel2 = Mathf.Clamp01((15 - num) / (15 * GameOptionsManager.Instance.currentNormalGameOptions.PlayerSpeedMod)); + + Tracker.Meter.SetDangerValue(dangerLevel1, dangerLevel2); + } } } \ No newline at end of file diff --git a/TheOtherRoles/Objects/CustomButton.cs b/TheOtherRoles/Objects/CustomButton.cs index a086aa15a..525f463a1 100644 --- a/TheOtherRoles/Objects/CustomButton.cs +++ b/TheOtherRoles/Objects/CustomButton.cs @@ -33,7 +33,7 @@ public class CustomButton { public HudManager hudManager; public bool mirror; public KeyCode? hotkey; - private string buttonText; + public string buttonText; public bool isHandcuffed = false; private static readonly int Desat = Shader.PropertyToID("_Desat"); diff --git a/TheOtherRoles/Objects/Silhouette.cs b/TheOtherRoles/Objects/Silhouette.cs new file mode 100644 index 000000000..5d0f09f9e --- /dev/null +++ b/TheOtherRoles/Objects/Silhouette.cs @@ -0,0 +1,82 @@ +using Innersloth.DebugTool; +using LibCpp2IL.Elf; +using Reactor.Utilities.Extensions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TheOtherRoles.Utilities; +using UnityEngine; + +namespace TheOtherRoles.Objects { + public class Silhouette { + public GameObject gameObject; + public float timeRemaining; + public bool permanent = false; + private bool visibleForEveryOne = false; + private SpriteRenderer renderer; + + public static List silhouettes = new List(); + + + private static Sprite SilhouetteSprite; + public static Sprite getSilhouetteSprite() { + if (SilhouetteSprite) return SilhouetteSprite; + SilhouetteSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.Silhouette.png", 225f); + return SilhouetteSprite; + } + + public Silhouette(Vector3 p, float duration = 1f, bool visibleForEveryOne = true) { + if (duration <= 0f) { + TheOtherRolesPlugin.Logger.LogMessage("silhouette: permanent!"); + permanent = true; + } + this.visibleForEveryOne = visibleForEveryOne; + gameObject = new GameObject("Silhouette"); + gameObject.AddSubmergedComponent(SubmergedCompatibility.Classes.ElevatorMover); + //Vector3 position = new Vector3(p.x, p.y, CachedPlayer.LocalPlayer.transform.localPosition.z + 0.001f); // just behind player + Vector3 position = new Vector3(p.x, p.y, p.y / 1000f + 0.01f); + gameObject.transform.position = position; + gameObject.transform.localPosition = position; + + renderer = gameObject.AddComponent(); + renderer.sprite = getSilhouetteSprite(); + + timeRemaining = duration; + + renderer.color = renderer.color.SetAlpha(Yoyo.SilhouetteVisibility); + + bool visible = visibleForEveryOne || PlayerControl.LocalPlayer == Yoyo.yoyo || PlayerControl.LocalPlayer.Data.IsDead; + + gameObject.SetActive(visible); + silhouettes.Add(this); + } + + public static void clearSilhouettes() { + foreach (var sil in silhouettes) + sil.gameObject.Destroy(); + silhouettes = new(); + } + + public static void UpdateAll() { + foreach (Silhouette current in new List(silhouettes)) { + current.timeRemaining -= Time.fixedDeltaTime; + bool visible = current.visibleForEveryOne || PlayerControl.LocalPlayer == Yoyo.yoyo || PlayerControl.LocalPlayer.Data.IsDead; + current.gameObject.SetActive(visible); + + if (visible && current.timeRemaining > 0 && current.timeRemaining < 0.5) { + var alphaRatio = current.timeRemaining / 0.5f; + current.renderer.color = current.renderer.color.SetAlpha(Yoyo.SilhouetteVisibility * alphaRatio); + } + + if (current.timeRemaining < 0 && !current.permanent) { + TheOtherRolesPlugin.Logger.LogMessage($"update: permanent: {current.permanent}, time: {current.timeRemaining}"); + current.gameObject.SetActive(false); + UnityEngine.Object.Destroy(current.gameObject); + silhouettes.Remove(current); + } + } + } + } +} diff --git a/TheOtherRoles/Objects/Trap.cs b/TheOtherRoles/Objects/Trap.cs index 76bdde7e4..e8ce26599 100644 --- a/TheOtherRoles/Objects/Trap.cs +++ b/TheOtherRoles/Objects/Trap.cs @@ -39,6 +39,7 @@ public Trap(Vector2 p) { trapRenderer.sprite = getTrapSprite(); trap.SetActive(false); if (CachedPlayer.LocalPlayer.PlayerId == Trapper.trapper.PlayerId) trap.SetActive(true); + trapRenderer.color = Color.white * new Vector4(1, 1, 1, 0.5f); this.instanceId = ++instanceCounter; traps.Add(this); arrow.Update(position); @@ -46,6 +47,7 @@ public Trap(Vector2 p) { FastDestroyableSingleton.Instance.StartCoroutine(Effects.Lerp(5, new Action((x) => { if (x == 1f) { this.triggerable = true; + trapRenderer.color = Color.white; } }))); } diff --git a/TheOtherRoles/Patches/CredentialsPatch.cs b/TheOtherRoles/Patches/CredentialsPatch.cs index 9f8bcccc4..1f9fbd5e1 100644 --- a/TheOtherRoles/Patches/CredentialsPatch.cs +++ b/TheOtherRoles/Patches/CredentialsPatch.cs @@ -30,22 +30,10 @@ public static class CredentialsPatch { [HarmonyPatch(typeof(PingTracker), nameof(PingTracker.Update))] internal static class PingTrackerPatch { - public static GameObject modStamp; - /*static void Prefix(PingTracker __instance) { - if (modStamp == null) { - modStamp = new GameObject("ModStamp"); - var rend = modStamp.AddComponent(); - rend.sprite = TheOtherRolesPlugin.GetModStamp(); - rend.color = new Color(1, 1, 1, 0.5f); - modStamp.transform.parent = __instance.transform.parent; - modStamp.transform.localScale *= SubmergedCompatibility.Loaded ? 0 : 0.6f; - } - float offset = (AmongUsClient.Instance.GameState == InnerNet.InnerNetClient.GameStates.Started) ? 0.75f : 0f; - modStamp.transform.position = FastDestroyableSingleton.Instance.MapButton.transform.position + Vector3.down * offset; - }*/ static void Postfix(PingTracker __instance){ - __instance.text.alignment = TMPro.TextAlignmentOptions.TopRight; + __instance.text.alignment = TextAlignmentOptions.TopRight; + var position = __instance.GetComponent(); if (AmongUsClient.Instance.GameState == InnerNet.InnerNetClient.GameStates.Started) { string gameModeText = $""; if (HideNSeek.isHideNSeekGM) gameModeText = $"Hide 'N Seek"; @@ -53,11 +41,7 @@ static void Postfix(PingTracker __instance){ else if (PropHunt.isPropHuntGM) gameModeText = "Prop Hunt"; if (gameModeText != "") gameModeText = Helpers.cs(Color.yellow, gameModeText) + "\n"; __instance.text.text = $"TheOtherRoles v{TheOtherRolesPlugin.Version.ToString() + (TheOtherRolesPlugin.betaDays > 0 ? "-BETA" : "")}\n{gameModeText}" + __instance.text.text; - if (CachedPlayer.LocalPlayer.Data.IsDead || (!(CachedPlayer.LocalPlayer.PlayerControl == null) && (CachedPlayer.LocalPlayer.PlayerControl == Lovers.lover1 || CachedPlayer.LocalPlayer.PlayerControl == Lovers.lover2))) { - __instance.transform.localPosition = new Vector3(3.45f, __instance.transform.localPosition.y, __instance.transform.localPosition.z); - } else { - __instance.transform.localPosition = new Vector3(4.2f, __instance.transform.localPosition.y, __instance.transform.localPosition.z); - } + position.DistanceFromEdge = new Vector3(2.25f, 0.11f, 0); } else { string gameModeText = $""; if (TORMapOptions.gameMode == CustomGamemodes.HideNSeek) gameModeText = $"Hide 'N Seek"; @@ -65,9 +49,11 @@ static void Postfix(PingTracker __instance){ else if (TORMapOptions.gameMode == CustomGamemodes.PropHunt) gameModeText = $"Prop Hunt"; if (gameModeText != "") gameModeText = Helpers.cs(Color.yellow, gameModeText) + "\n"; - __instance.text.text = $"{fullCredentialsVersion}\n {gameModeText + fullCredentials}\n {__instance.text.text}"; - __instance.transform.localPosition = new Vector3(3.5f, __instance.transform.localPosition.y, __instance.transform.localPosition.z); + var host = $"Host: {GameData.Instance?.GetHost()?.PlayerName}"; + __instance.text.text = $"{fullCredentialsVersion}\n {gameModeText + fullCredentials}\n {host}\n {__instance.text.text}"; + position.DistanceFromEdge = new Vector3(3.5f, 0.1f, 0); } + position.AdjustPosition(); } } diff --git a/TheOtherRoles/Patches/DangerMeterPatch.cs b/TheOtherRoles/Patches/DangerMeterPatch.cs new file mode 100644 index 000000000..c3f041e7d --- /dev/null +++ b/TheOtherRoles/Patches/DangerMeterPatch.cs @@ -0,0 +1,21 @@ +using HarmonyLib; +using TheOtherRoles.Players; +using UnityEngine; + +namespace TheOtherRoles.Patches { + + [HarmonyPatch] + + public class DangerMeterPatch { + + [HarmonyPatch(typeof(DangerMeter), nameof(DangerMeter.SetFirstNBarColors))] + [HarmonyPrefix] + + public static void Prefix(DangerMeter __instance, ref Color color) { + if (CachedPlayer.LocalPlayer.PlayerControl != Tracker.tracker) return; + if (__instance == HudManager.Instance.DangerMeter) return; + + color = color.SetAlpha(0.5f); + } + } +} \ No newline at end of file diff --git a/TheOtherRoles/Patches/ExileControllerPatch.cs b/TheOtherRoles/Patches/ExileControllerPatch.cs index 63a4ef52a..50e1f831b 100644 --- a/TheOtherRoles/Patches/ExileControllerPatch.cs +++ b/TheOtherRoles/Patches/ExileControllerPatch.cs @@ -271,6 +271,9 @@ static void WrapUpPostfix(GameData.PlayerInfo exiled) { FastDestroyableSingleton.Instance.StartCoroutine(Effects.Lerp(GameOptionsManager.Instance.currentNormalGameOptions.KillCooldown / 2 + 2, new Action((p) => { if (p == 1f) foreach (Trap trap in Trap.traps) trap.triggerable = true; }))); + + if (!Yoyo.markStaysOverMeeting) + Silhouette.clearSilhouettes(); } } diff --git a/TheOtherRoles/Patches/MapBehaviourPatch.cs b/TheOtherRoles/Patches/MapBehaviourPatch.cs index 8456f7d09..76e927222 100644 --- a/TheOtherRoles/Patches/MapBehaviourPatch.cs +++ b/TheOtherRoles/Patches/MapBehaviourPatch.cs @@ -34,6 +34,10 @@ public static void clearAndReload() { [HarmonyPatch(typeof(MapBehaviour), nameof(MapBehaviour.FixedUpdate))] static void Postfix(MapBehaviour __instance) { + if (__instance.infectedOverlay.gameObject.active && PlayerControl.LocalPlayer.Data.IsDead && CustomOptionHolder.deadImpsBlockSabotage.getBool()) { + __instance.Close(); + } + __instance.HerePoint.transform.SetLocalZ(-2.1f); if (Trapper.trapper != null && CachedPlayer.LocalPlayer.PlayerId == Trapper.trapper.PlayerId) { foreach (PlayerControl player in Trapper.playersOnMap) { @@ -91,6 +95,30 @@ static void Postfix(MapBehaviour __instance) { } } + // Show location of all players on the map for ghosts! + if (PlayerControl.LocalPlayer.Data.IsDead && (!PlayerControl.LocalPlayer.Data.Role.IsImpostor || CustomOptionHolder.deadImpsBlockSabotage.getBool())) { + foreach (PlayerControl player in CachedPlayer.AllPlayers) { + if (player == PlayerControl.LocalPlayer) + continue; + var alpha = player.Data.IsDead ? 0.25f : 1f; + Vector3 v = player.transform.position; + v /= MapUtilities.CachedShipStatus.MapScale; + v.x *= Mathf.Sign(MapUtilities.CachedShipStatus.transform.localScale.x); + v.z = -2.1f; + if (herePoints.ContainsKey(player)) { + herePoints[player].transform.localPosition = v; + herePoints[player].color = herePoints[player].color.SetAlpha(alpha); + continue; + } + var herePoint = UnityEngine.Object.Instantiate(__instance.HerePoint, __instance.HerePoint.transform.parent, true); + herePoint.transform.localPosition = v; + herePoint.enabled = true; + + int colorId = player.CurrentOutfit.ColorId; + player.SetPlayerMaterialColors(herePoint); + herePoints.Add(player, herePoint); + } + } foreach (var vent in MapUtilities.CachedShipStatus.AllVents) { if ((vent.name.StartsWith("JackInThe") && !(PlayerControl.LocalPlayer == Trickster.trickster || PlayerControl.LocalPlayer.Data.IsDead))) continue; //for trickster vents diff --git a/TheOtherRoles/Patches/MeetingPatch.cs b/TheOtherRoles/Patches/MeetingPatch.cs index 39b26a854..0a9023d17 100644 --- a/TheOtherRoles/Patches/MeetingPatch.cs +++ b/TheOtherRoles/Patches/MeetingPatch.cs @@ -10,6 +10,7 @@ using TheOtherRoles.Utilities; using UnityEngine; using Innersloth.Assets; +using TMPro; namespace TheOtherRoles.Patches { [HarmonyPatch] @@ -792,5 +793,36 @@ public static void MeetingHudIntroPrefix() { EventUtility.meetingStartsUpdate(); } + [HarmonyPatch] + public class ShowHost { + private static TextMeshPro Text = null; + [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.Start))] + [HarmonyPostfix] + + public static void Setup(MeetingHud __instance) + { + if (AmongUsClient.Instance.NetworkMode != NetworkModes.OnlineGame) return; + + __instance.ProceedButton.gameObject.transform.localPosition = new(-2.5f, 2.2f, 0); + __instance.ProceedButton.gameObject.GetComponent().enabled = false; + __instance.ProceedButton.GetComponent().enabled = false; + __instance.HostIcon.gameObject.SetActive(true); + __instance.ProceedButton.gameObject.SetActive(true); + } + + [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.Update))] + [HarmonyPostfix] + + public static void Postfix(MeetingHud __instance) { + var host = GameData.Instance.GetHost(); + + if (host != null) + { + PlayerMaterial.SetColors(host.DefaultOutfit.ColorId, __instance.HostIcon); + if (Text == null) Text = __instance.ProceedButton.gameObject.GetComponentInChildren(); + Text.text = $"host: {host.PlayerName}"; + } + } + } } } diff --git a/TheOtherRoles/Patches/PlayerControlPatch.cs b/TheOtherRoles/Patches/PlayerControlPatch.cs index 68355cb65..213d1e2f8 100644 --- a/TheOtherRoles/Patches/PlayerControlPatch.cs +++ b/TheOtherRoles/Patches/PlayerControlPatch.cs @@ -398,10 +398,11 @@ static void trackerUpdate() { if (Tracker.arrow?.arrow != null) { if (Tracker.tracker == null || CachedPlayer.LocalPlayer.PlayerControl != Tracker.tracker) { Tracker.arrow.arrow.SetActive(false); + if (Tracker.DangerMeterParent) Tracker.DangerMeterParent.SetActive(false); return; } - if (Tracker.tracker != null && Tracker.tracked != null && CachedPlayer.LocalPlayer.PlayerControl == Tracker.tracker && !Tracker.tracker.Data.IsDead) { + if (Tracker.tracked != null && !Tracker.tracker.Data.IsDead) { Tracker.timeUntilUpdate -= Time.fixedDeltaTime; if (Tracker.timeUntilUpdate <= 0f) { @@ -415,12 +416,19 @@ static void trackerUpdate() { } } - Tracker.arrow.Update(position); - Tracker.arrow.arrow.SetActive(trackedOnMap); + if (Tracker.trackingMode == 1 || Tracker.trackingMode == 2) Arrow.UpdateProximity(position); + if (Tracker.trackingMode == 0 || Tracker.trackingMode == 2) { + Tracker.arrow.Update(position); + Tracker.arrow.arrow.SetActive(trackedOnMap); + } Tracker.timeUntilUpdate = Tracker.updateIntervall; } else { - Tracker.arrow.Update(); + if (Tracker.trackingMode == 0 || Tracker.trackingMode == 2) Tracker.arrow.Update(); } + } + else if (Tracker.tracker.Data.IsDead) { + Tracker.DangerMeterParent?.SetActive(false); + Tracker.Meter?.gameObject.SetActive(false); } } @@ -1072,6 +1080,8 @@ public static void Postfix(PlayerControl __instance) { ninjaUpdate(); // Thief thiefSetTarget(); + // yoyo + Silhouette.UpdateAll(); hackerUpdate(); swapperUpdate(); diff --git a/TheOtherRoles/Patches/RoleAssignmentPatch.cs b/TheOtherRoles/Patches/RoleAssignmentPatch.cs index 43dddd530..31c7855d7 100644 --- a/TheOtherRoles/Patches/RoleAssignmentPatch.cs +++ b/TheOtherRoles/Patches/RoleAssignmentPatch.cs @@ -120,6 +120,7 @@ public static RoleAssignmentData getRoleAssignmentData() { impSettings.Add((byte)RoleId.Witch, CustomOptionHolder.witchSpawnRate.getSelection()); impSettings.Add((byte)RoleId.Ninja, CustomOptionHolder.ninjaSpawnRate.getSelection()); impSettings.Add((byte)RoleId.Bomber, CustomOptionHolder.bomberSpawnRate.getSelection()); + impSettings.Add((byte)RoleId.Yoyo, CustomOptionHolder.yoyoSpawnRate.getSelection()); neutralSettings.Add((byte)RoleId.Jester, CustomOptionHolder.jesterSpawnRate.getSelection()); neutralSettings.Add((byte)RoleId.Arsonist, CustomOptionHolder.arsonistSpawnRate.getSelection()); diff --git a/TheOtherRoles/Patches/UpdatePatch.cs b/TheOtherRoles/Patches/UpdatePatch.cs index 7d2522549..34cf40574 100644 --- a/TheOtherRoles/Patches/UpdatePatch.cs +++ b/TheOtherRoles/Patches/UpdatePatch.cs @@ -324,6 +324,7 @@ static void updateUseButton(HudManager __instance) { static void updateSabotageButton(HudManager __instance) { if (MeetingHud.Instance || TORMapOptions.gameMode == CustomGamemodes.HideNSeek || TORMapOptions.gameMode == CustomGamemodes.PropHunt) __instance.SabotageButton.Hide(); + if (PlayerControl.LocalPlayer.Data.IsDead && CustomOptionHolder.deadImpsBlockSabotage.getBool()) __instance.SabotageButton.Hide(); } static void updateMapButton(HudManager __instance) { diff --git a/TheOtherRoles/Patches/UsablesPatch.cs b/TheOtherRoles/Patches/UsablesPatch.cs index 24b09e80a..6c6569f1e 100644 --- a/TheOtherRoles/Patches/UsablesPatch.cs +++ b/TheOtherRoles/Patches/UsablesPatch.cs @@ -738,6 +738,10 @@ static bool Prefix(MapBehaviour __instance) { if (HideNSeek.isHideNSeekGM) return HideNSeek.canSabotage; if (PropHunt.isPropHuntGM) return false; + if (PlayerControl.LocalPlayer.Data.IsDead && CustomOptionHolder.deadImpsBlockSabotage.getBool()) { + __instance.ShowNormalMap(); + return false; + } return true; } } diff --git a/TheOtherRoles/RPC.cs b/TheOtherRoles/RPC.cs index 6153efdff..8c1166366 100644 --- a/TheOtherRoles/RPC.cs +++ b/TheOtherRoles/RPC.cs @@ -62,6 +62,7 @@ public enum RoleId { Ninja, Thief, Bomber, + Yoyo, Crewmate, Impostor, // Modifier --- @@ -148,6 +149,8 @@ enum CustomRPC PlaceBomb, DefuseBomb, ShareRoom, + YoyoMarkLocation, + YoyoBlink, // Gamemode SetGuesserGm, @@ -172,6 +175,7 @@ public static void resetVariables() { Garlic.clearGarlics(); JackInTheBox.clearJackInTheBoxes(); NinjaTrace.clearTraces(); + Silhouette.clearSilhouettes(); Portal.clearPortals(); Bloodytrail.resetSprites(); Trap.clearTraps(); @@ -379,6 +383,9 @@ public static void setRole(byte roleId, byte playerId) { case RoleId.Bomber: Bomber.bomber = player; break; + case RoleId.Yoyo: + Yoyo.yoyo = player; + break; } if (AmongUsClient.Instance.AmHost && Helpers.roleCanUseVents(player) && !player.Data.Role.IsImpostor) { player.RpcSetRole(RoleTypes.Engineer); @@ -744,6 +751,7 @@ public static void erasePlayerRoles(byte playerId, bool ignoreModifier = true) { if (player == Witch.witch) Witch.clearAndReload(); if (player == Ninja.ninja) Ninja.clearAndReload(); if (player == Bomber.bomber) Bomber.clearAndReload(); + if (player == Yoyo.yoyo) Yoyo.clearAndReload(); // Other roles if (player == Jester.jester) Jester.clearAndReload(); @@ -1102,6 +1110,10 @@ public static void thiefStealsRole(byte playerId) { } if (target == Ninja.ninja) Ninja.ninja = thief; if (target == Bomber.bomber) Bomber.bomber = thief; + if (target == Yoyo.yoyo) { + Yoyo.yoyo = thief; + Yoyo.markedLocation = null; + } if (target.Data.Role.IsImpostor) { RoleManager.Instance.SetRole(Thief.thief, RoleTypes.Impostor); FastDestroyableSingleton.Instance.KillButton.SetCoolDown(Thief.thief.killTimer, GameOptionsManager.Instance.currentNormalGameOptions.KillCooldown); @@ -1288,6 +1300,40 @@ public static void shareRoom(byte playerId, byte roomId) { if (Snitch.playerRoomMap.ContainsKey(playerId)) Snitch.playerRoomMap[playerId] = roomId; else Snitch.playerRoomMap.Add(playerId, roomId); } + + public static void yoyoMarkLocation(byte[] buff) { + if (Yoyo.yoyo == null) return; + Vector3 position = Vector3.zero; + position.x = BitConverter.ToSingle(buff, 0 * sizeof(float)); + position.y = BitConverter.ToSingle(buff, 1 * sizeof(float)); + Yoyo.markLocation(position); + new Silhouette(position, -1, false); + } + + public static void yoyoBlink(bool isFirstJump, byte[] buff) { + TheOtherRolesPlugin.Logger.LogMessage($"blink fistjumpo: {isFirstJump}"); + if (Yoyo.yoyo == null || Yoyo.markedLocation == null) return; + var markedPos = (Vector3)Yoyo.markedLocation; + Yoyo.yoyo.NetTransform.SnapTo(markedPos); + + var markedSilhouette = Silhouette.silhouettes.FirstOrDefault(s => s.gameObject.transform.position.x == markedPos.x && s.gameObject.transform.position.y == markedPos.y); + if (markedSilhouette != null) + markedSilhouette.permanent = false; + + Vector3 position = Vector3.zero; + position.x = BitConverter.ToSingle(buff, 0 * sizeof(float)); + position.y = BitConverter.ToSingle(buff, 1 * sizeof(float)); + // Create Silhoutte At Start Position: + if (isFirstJump) { + Yoyo.markLocation(position); + new Silhouette(position, Yoyo.blinkDuration, true); + } else { + new Silhouette(position, 5, true); + Yoyo.markedLocation = null; + } + if (Chameleon.chameleon.Any(x => x.PlayerId == Yoyo.yoyo.PlayerId)) // Make the Yoyo visible if chameleon! + Chameleon.lastMoved[Yoyo.yoyo.PlayerId] = Time.time; + } } [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.HandleRpc))] @@ -1538,6 +1584,12 @@ static void Postfix([HarmonyArgument(0)]byte callId, [HarmonyArgument(1)]Message case (byte)CustomRPC.StopStart: RPCProcedure.stopStart(reader.ReadByte()); break; + case (byte)CustomRPC.YoyoMarkLocation: + RPCProcedure.yoyoMarkLocation(reader.ReadBytesAndSize()); + break; + case (byte)CustomRPC.YoyoBlink: + RPCProcedure.yoyoBlink(reader.ReadByte() == byte.MaxValue, reader.ReadBytesAndSize()); + break; // Game mode case (byte)CustomRPC.SetGuesserGm: diff --git a/TheOtherRoles/Resources/Silhouette.png b/TheOtherRoles/Resources/Silhouette.png new file mode 100644 index 0000000000000000000000000000000000000000..ca0f93a9d9537292604005a6cc49f5855fbdc1e6 GIT binary patch literal 6525 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 a0bJ-k5FP)G37wSxl8S=5e3dLL&X literal 0 HcmV?d00001 diff --git a/TheOtherRoles/Resources/YoyoBlinkButtonSprite.png b/TheOtherRoles/Resources/YoyoBlinkButtonSprite.png new file mode 100644 index 0000000000000000000000000000000000000000..cb8de34860f0fae3cceb30c09fb5c49f0454c476 GIT binary patch literal 16744 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�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

B)cx!kN75)SY{pmivr9b?w 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 ZgBFm@0mLA1DR?r7@^tlcS?83{1OTW980i22 literal 0 HcmV?d00001 diff --git a/TheOtherRoles/RoleInfo.cs b/TheOtherRoles/RoleInfo.cs index 53b0e3e0a..9fcccd56b 100644 --- a/TheOtherRoles/RoleInfo.cs +++ b/TheOtherRoles/RoleInfo.cs @@ -75,6 +75,7 @@ public RoleInfo(string name, Color color, string introDescription, string shortD public static RoleInfo ninja = new RoleInfo("Ninja", Ninja.color, "Surprise and assassinate your foes", "Surprise and assassinate your foes", RoleId.Ninja); public static RoleInfo thief = new RoleInfo("Thief", Thief.color, "Steal a killers role by killing them", "Steal a killers role", RoleId.Thief, true); public static RoleInfo bomber = new RoleInfo("Bomber", Bomber.color, "Bomb all Crewmates", "Bomb all Crewmates", RoleId.Bomber); + public static RoleInfo yoyo = new RoleInfo("Yo-Yo", Yoyo.color, "Blink to a marked location and Back", "Blink to a location", RoleId.Yoyo); public static RoleInfo hunter = new RoleInfo("Hunter", Palette.ImpostorRed, Helpers.cs(Palette.ImpostorRed, "Seek and kill everyone"), "Seek and kill everyone", RoleId.Impostor); public static RoleInfo hunted = new RoleInfo("Hunted", Color.white, "Hide", "Hide", RoleId.Crewmate); @@ -113,6 +114,7 @@ public RoleInfo(string name, Color color, string introDescription, string shortD witch, ninja, bomber, + yoyo, goodGuesser, badGuesser, lover, @@ -202,6 +204,7 @@ public static List getRoleInfoForPlayer(PlayerControl p, bool showModi if (p == Witch.witch) infos.Add(witch); if (p == Ninja.ninja) infos.Add(ninja); if (p == Bomber.bomber) infos.Add(bomber); + if (p == Yoyo.yoyo) infos.Add(yoyo); if (p == Detective.detective) infos.Add(detective); if (p == TimeMaster.timeMaster) infos.Add(timeMaster); if (p == Medic.medic) infos.Add(medic); diff --git a/TheOtherRoles/SubmergedCompatibility.cs b/TheOtherRoles/SubmergedCompatibility.cs index f3311b66f..fbfa4913f 100644 --- a/TheOtherRoles/SubmergedCompatibility.cs +++ b/TheOtherRoles/SubmergedCompatibility.cs @@ -113,9 +113,6 @@ public static void Initialize() Version = plugin.Metadata.Version.BaseVersion(); Assembly = Plugin!.GetType().Assembly; } - - CredentialsPatch.PingTrackerPatch.modStamp = new GameObject(); - Object.DontDestroyOnLoad(CredentialsPatch.PingTrackerPatch.modStamp); Types = AccessTools.GetTypesFromAssembly(Assembly); diff --git a/TheOtherRoles/TheOtherRoles.cs b/TheOtherRoles/TheOtherRoles.cs index 8281ba995..63aa6be5e 100644 --- a/TheOtherRoles/TheOtherRoles.cs +++ b/TheOtherRoles/TheOtherRoles.cs @@ -10,6 +10,7 @@ using static TheOtherRoles.TheOtherRoles; using AmongUs.Data; using Hazel; +using Reactor.Utilities.Extensions; namespace TheOtherRoles { @@ -61,6 +62,7 @@ public static void clearAndReloadRoles() { Thief.clearAndReload(); Trapper.clearAndReload(); Bomber.clearAndReload(); + Yoyo.clearAndReload(); // Modifier Bait.clearAndReload(); @@ -737,7 +739,7 @@ public static void clearAndReload() { public static class Tracker { public static PlayerControl tracker; public static Color color = new Color32(100, 58, 220, byte.MaxValue); - public static List localArrows = new List(); + public static List localArrows = new(); public static float updateIntervall = 5f; public static bool resetTargetAfterMeeting = false; @@ -745,13 +747,17 @@ public static class Tracker { public static float corpsesTrackingCooldown = 30f; public static float corpsesTrackingDuration = 5f; public static float corpsesTrackingTimer = 0f; - public static List deadBodyPositions = new List(); + public static int trackingMode = 0; + public static List deadBodyPositions = new(); public static PlayerControl currentTarget; public static PlayerControl tracked; public static bool usedTracker = false; public static float timeUntilUpdate = 0f; - public static Arrow arrow = new Arrow(Color.blue); + public static Arrow arrow = new(Color.blue); + + public static GameObject DangerMeterParent; + public static DangerMeter Meter; private static Sprite trackCorpsesButtonSprite; public static Sprite getTrackCorpsesButtonSprite() @@ -792,6 +798,11 @@ public static void clearAndReload() { corpsesTrackingCooldown = CustomOptionHolder.trackerCorpsesTrackingCooldown.getFloat(); corpsesTrackingDuration = CustomOptionHolder.trackerCorpsesTrackingDuration.getFloat(); canTrackCorpses = CustomOptionHolder.trackerCanTrackCorpses.getBool(); + trackingMode = CustomOptionHolder.trackerTrackingMethod.getSelection(); + if (DangerMeterParent) { + Meter.gameObject.Destroy(); + DangerMeterParent.Destroy(); + } } } @@ -889,6 +900,7 @@ public static class Jackal { public static bool wasTeamRed; public static bool wasImpostor; public static bool wasSpy; + public static bool canSabotageLights; public static Sprite getSidekickButtonSprite() { if (buttonSprite) return buttonSprite; @@ -918,6 +930,7 @@ public static void clearAndReload() { formerJackals.Clear(); hasImpostorVision = CustomOptionHolder.jackalAndSidekickHaveImpostorVision.getBool(); wasTeamRed = wasImpostor = wasSpy = false; + canSabotageLights = CustomOptionHolder.jackalCanSabotageLights.getBool(); } } @@ -937,6 +950,7 @@ public static class Sidekick { public static bool canKill = true; public static bool promotesToJackal = true; public static bool hasImpostorVision = false; + public static bool canSabotageLights; public static void clearAndReload() { sidekick = null; @@ -947,6 +961,7 @@ public static void clearAndReload() { promotesToJackal = CustomOptionHolder.sidekickPromotesToJackal.getBool(); hasImpostorVision = CustomOptionHolder.jackalAndSidekickHaveImpostorVision.getBool(); wasTeamRed = wasImpostor = wasSpy = false; + canSabotageLights = CustomOptionHolder.sidekickCanSabotageLights.getBool(); } } @@ -1784,6 +1799,52 @@ public static void clearAndReload() { } } + public static class Yoyo { + public static PlayerControl yoyo = null; + public static Color color = Palette.ImpostorRed; + + public static float blinkDuration = 0; + public static float markCooldown = 0; + public static bool markStaysOverMeeting = false; + public static bool hasAdminTable = false; + public static float adminCooldown = 0; + public static float SilhouetteVisibility => (silhouetteVisibility == 0 && (PlayerControl.LocalPlayer == yoyo || PlayerControl.LocalPlayer.Data.IsDead)) ? 0.1f : silhouetteVisibility; + public static float silhouetteVisibility = 0; + + public static Vector3? markedLocation = null; + + private static Sprite markButtonSprite; + + public static Sprite getMarkButtonSprite() { + if (markButtonSprite) return markButtonSprite; + markButtonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.YoyoMarkButtonSprite.png", 115f); + return markButtonSprite; + } + private static Sprite blinkButtonSprite; + + public static Sprite getBlinkButtonSprite() { + if (blinkButtonSprite) return blinkButtonSprite; + blinkButtonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.YoyoBlinkButtonSprite.png", 115f); + return blinkButtonSprite; + } + + public static void markLocation(Vector3 position) { + markedLocation = position; + } + + public static void clearAndReload() { + blinkDuration = CustomOptionHolder.yoyoBlinkDuration.getFloat(); + markCooldown = CustomOptionHolder.yoyoMarkCooldown.getFloat(); + markStaysOverMeeting = CustomOptionHolder.yoyoMarkStaysOverMeeting.getBool(); + hasAdminTable = CustomOptionHolder.yoyoHasAdminTable.getBool(); + adminCooldown = CustomOptionHolder.yoyoAdminTableCooldown.getFloat(); + silhouetteVisibility = CustomOptionHolder.yoyoSilhouetteVisibility.getSelection() / 10f; + + markedLocation = null; + + } + } + // Modifier public static class Bait { public static List bait = new List(); diff --git a/TheOtherRoles/TheOtherRoles.csproj b/TheOtherRoles/TheOtherRoles.csproj index 162180684..9c056c16f 100644 --- a/TheOtherRoles/TheOtherRoles.csproj +++ b/TheOtherRoles/TheOtherRoles.csproj @@ -1,7 +1,7 @@  net6.0 - 4.5.1 + 4.5.3 TheOtherRoles Eisbison latest @@ -17,8 +17,8 @@ - + diff --git a/TheOtherRoles/packages.lock.json b/TheOtherRoles/packages.lock.json index e3543ec28..3bcb0fd0c 100644 --- a/TheOtherRoles/packages.lock.json +++ b/TheOtherRoles/packages.lock.json @@ -16,17 +16,17 @@ }, "BepInEx.Unity.IL2CPP": { "type": "Direct", - "requested": "[6.0.0-be.671, )", - "resolved": "6.0.0-be.671", - "contentHash": "XpmrBitEO7pe5YG9VHqn0nuelEF5Dp0Rpkxa2F7PFZF1a00KSsdCL809++HYnGzLumNOCIt7mO7yyDNP5k25mw==", + "requested": "[6.0.0-be.688, )", + "resolved": "6.0.0-be.688", + "contentHash": "a68J6PA9AdgYlj8HeuEK1hM4Vv+j1x/6TflK5/PaYAd05/TPdjNI09LsSTIOaS9hdWZwCcpPEw/HxLhXaQKodw==", "dependencies": { - "BepInEx.Core": "6.0.0-be.671", - "BepInEx.Unity.Common": "6.0.0-be.671", + "BepInEx.Core": "6.0.0-be.688", + "BepInEx.Unity.Common": "6.0.0-be.688", "HarmonyX": "2.10.1", "Iced": "1.18.0", - "Il2CppInterop.Generator": "1.4.6-ci.367", - "Il2CppInterop.HarmonySupport": "1.4.6-ci.367", - "Il2CppInterop.Runtime": "1.4.6-ci.367", + "Il2CppInterop.Generator": "1.4.6-ci.389", + "Il2CppInterop.HarmonySupport": "1.4.6-ci.389", + "Il2CppInterop.Runtime": "1.4.6-ci.389", "MonoMod.RuntimeDetour": "22.5.1.1", "Samboy063.Cpp2IL.Core": "2022.1.0-development.866" } @@ -70,15 +70,20 @@ "AsmResolver": "5.1.0" } }, + "AssetRipper.Primitives": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "nrgwUMa69ztOfMKbmytNI3mU/fuN3eWptq2Mu8aLg2ly394w51KJbUx5z477HbRvabD8TD8rM4wRe6EBqB2xdA==" + }, "AssetRipper.VersionUtilities": { "type": "Transitive", - "resolved": "1.3.1", - "contentHash": "/1D18NOpqm7rS7+qVUbAReVMNWwgDuYpsnf0RkX1Aah/I0a0irqldoFJ+Kku7YdbSm0zqD+Z6iYUGKoP3GwTNQ==" + "resolved": "1.2.1", + "contentHash": "knQ/W1YwTZS2AbdaZh+nhyyBEZQPQDcahhSOnh88i+cdg4/FEoFJiCwaavgFvCMNuUeHTbcZc4qttF8WQ8xLIA==" }, "BepInEx.Core": { "type": "Transitive", - "resolved": "6.0.0-be.671", - "contentHash": "Hp9QsgwtlGuNULFq5tF8YHrVD5R5WA5nMgFTJbcScWsGJDq7KPEhiLNGvKHAxcmMM8GA0CKM+jn8cJPtlMKvNQ==", + "resolved": "6.0.0-be.688", + "contentHash": "34VErIttx6PckRukoaRXIb6ZF5oby+9Oktt9E3ZafOGzA0lBWOmY/BKHfg766XZBplE06KijHp+vrryCjfLP7Q==", "dependencies": { "HarmonyX": "2.10.1", "MonoMod.Utils": "22.5.1.1", @@ -87,8 +92,8 @@ }, "BepInEx.Unity.Common": { "type": "Transitive", - "resolved": "6.0.0-be.671", - "contentHash": "05W7ERsHizZl0MacTAhiGkcihZl2b0DYBP0e6gA1Vzoay+teQ/mHy3zorGu1r8lLWlesH4LXl89HwFjrMA1ZKw==", + "resolved": "6.0.0-be.688", + "contentHash": "RRPG9sEgIdGgut0LOSQopW+6mMpE0LDggKZWfLBBeaJj1p0WFrVBCqEAruFLO0FrwT/+dEC7EtV62n13RV1JfA==", "dependencies": { "AssetRipper.VersionUtilities": "1.2.1", "MonoMod.Utils": "22.5.1.1" @@ -115,8 +120,8 @@ }, "Il2CppInterop.Common": { "type": "Transitive", - "resolved": "1.4.6-ci.367", - "contentHash": "zviSAk0COGdxx1KLTJlSi6lyvfRjbPO4qhj9RvLAU5zP74hwAkjhim0WsSo9clkkyGS+KXDrjnUEHqfXuMMm9Q==", + "resolved": "1.4.6-ci.389", + "contentHash": "KTyf2f66Q2mS9a6xhvoPWwD0VzRIoskPMVQehaVMo1dx4Di1FPFsKqukQ+ob6wgP5Rbnx53kiH0PY+IRSb35XA==", "dependencies": { "Iced": "1.17.0", "Microsoft.Extensions.Logging.Abstractions": "6.0.1", @@ -125,29 +130,29 @@ }, "Il2CppInterop.Generator": { "type": "Transitive", - "resolved": "1.4.6-ci.367", - "contentHash": "VP/1LX3wEy0/5BCrgggzIm9niyRGp/zjXaxFJip1D2bvM7oIXwK0LR0Rp8BE/uxKW8aQjVYxxwVwsdXPS/1KZw==", + "resolved": "1.4.6-ci.389", + "contentHash": "XJX4sn/RzAEBNIZZXuyDcLZrFx5tCoahujDu5aKWjApiMj/nTRQAxZn17daIIvd9aHqLaAfiWWth5QDLIt2bKw==", "dependencies": { - "Il2CppInterop.Common": "1.4.6-ci.367", + "Il2CppInterop.Common": "1.4.6-ci.389", "Mono.Cecil": "0.11.3" } }, "Il2CppInterop.HarmonySupport": { "type": "Transitive", - "resolved": "1.4.6-ci.367", - "contentHash": "rKb4Bt4cZQNWtI1L1/n/m5jJelP8pwAcQHwN/gaUAcobnapGZPJvRp8gyLQRvthGm3sxeleIQelEsv6L+21A2g==", + "resolved": "1.4.6-ci.389", + "contentHash": "Xd2zK6sLqwA0ReyUy83SWKcALwY99fq6vVL5gFOMN5Ct8OOVhtNIws0ysCWsfx1GL0RJiRYfR4pza/MmWRz4PQ==", "dependencies": { "HarmonyX": "2.10.0", - "Il2CppInterop.Runtime": "1.4.6-ci.367" + "Il2CppInterop.Runtime": "1.4.6-ci.389" } }, "Il2CppInterop.Runtime": { "type": "Transitive", - "resolved": "1.4.6-ci.367", - "contentHash": "Wb4rj/ESlfiYljfVXskndbkYNSX1WxPcsylrYex39QnVzujk6tRQUbHLA7PZn509z6P5wYbqJvhodzJ+w9Kk4A==", + "resolved": "1.4.6-ci.389", + "contentHash": "nzYjuVzDG/O8+AQ8ax3WVHf+ZVsQKrVtp/yvuW8XoEPLdkbgryIrMo75dvN+tPqxOU3o2MPt9MZ9j25P5aVJMw==", "dependencies": { "Iced": "1.17.0", - "Il2CppInterop.Common": "1.4.6-ci.367" + "Il2CppInterop.Common": "1.4.6-ci.389" } }, "js6pak.Gee.External.Capstone": { @@ -317,17 +322,17 @@ }, "Samboy063.LibCpp2IL": { "type": "Transitive", - "resolved": "2022.1.0-development.866", - "contentHash": "EcJSWTfQko8SQozozoUT+aQJVWC8wj8C0YUiPBF4rNRId19yTKp2IXcXnI747v+8/aal222QR6WHfoBK2WlVLg==", + "resolved": "2022.1.0-pre-release.13", + "contentHash": "fwkVLAXqD+7XfIXJEDh2OkJqe6YMkNmOP05oudEnuq3ITEuVUSb0K8ffa22vx+n/NDIyNP+s1lLRFcmHVP57oQ==", "dependencies": { - "AssetRipper.VersionUtilities": "1.3.1", - "Samboy063.WasmDisassembler": "2022.1.0-development.866" + "AssetRipper.Primitives": "2.1.0", + "Samboy063.WasmDisassembler": "2022.1.0-pre-release.13" } }, "Samboy063.WasmDisassembler": { "type": "Transitive", - "resolved": "2022.1.0-development.866", - "contentHash": "2QK8F3eISkLcoW/Nt7wtxyQh31EXAqEMBVXXjEnuxyvXpBXxOIGpjmE3pWhGwxQwDCbe4zBsLF1zUiqq3/pXRA==" + "resolved": "2022.1.0-pre-release.13", + "contentHash": "dI4PDG+AFctYzaD0pqojK7SGiiPi6xgIRXp07hHnXumW+DYbS2nVQ8nTFSHiP6xE7UhW6I+PpbC5jh/2nksW+Q==" }, "SemanticVersioning": { "type": "Transitive", @@ -336,8 +341,8 @@ }, "StableNameDotNet": { "type": "Transitive", - "resolved": "0.1.0-development.866", - "contentHash": "DJb8x4dV3ucDgM12sU28HxCdeqY/JudJbeJG6mgXWDJzpFZw2Jd7JF1pKFRNLzh/0gpo8bCGLQS9gOWZmBjdtg==" + "resolved": "0.1.0-pre-release.13", + "contentHash": "8ovX1WcVUO6R1pHzaW1v1SC9coSWSYh5JjjZ/vvr7jsb7+hWzMVpsV+uyWLMie9olE2FW1k4RLaXf5GmvlVwMg==" }, "System.Collections": { "type": "Transitive", diff --git a/nuget.config b/nuget.config index c00459bf4..9d33aaaa2 100644 --- a/nuget.config +++ b/nuget.config @@ -4,6 +4,5 @@ -