diff --git a/Strings.xlsx b/Strings.xlsx index 0563794..30ccf2d 100644 Binary files a/Strings.xlsx and b/Strings.xlsx differ diff --git a/TheOtherRoles/Buttons.cs b/TheOtherRoles/Buttons.cs index eac2ec9..3f1f19a 100644 --- a/TheOtherRoles/Buttons.cs +++ b/TheOtherRoles/Buttons.cs @@ -99,6 +99,9 @@ static class HudManagerStartPatch public static CustomButton noisemakerButton; public static CustomButton schrodingersCatKillButton; public static CustomButton schrodingersCatSwitchButton; + public static CustomButton operateButton; + public static CustomButton freePlaySuicideButton; + public static CustomButton freePlayReviveButton; //public static CustomButton trapperButton; //public static CustomButton bomberButton; //public static CustomButton defuseButton; @@ -245,6 +248,9 @@ public static void setCustomButtonCooldowns() { foxImmoralistButton.MaxTimer = 20f; immoralistButton.MaxTimer = 20f; buskerButton.MaxTimer = Busker.cooldown; + operateButton.Timer = 0f; + freePlayReviveButton.Timer = 0f; + freePlaySuicideButton.Timer = 0f; //trapperButton.MaxTimer = Trapper.cooldown; //bomberButton.MaxTimer = Bomber.bombCooldown; hunterLighterButton.MaxTimer = Hunter.lightCooldown; @@ -1384,10 +1390,12 @@ public static void createButtonsPostfix(HudManager __instance) { RPCProcedure.serialKillerSuicide(targetId); }, abilityTexture: true - ); - jekyllAndHydeSuicideButton.showButtonText = true; - jekyllAndHydeSuicideButton.buttonText = ModTranslation.getString("serialKillerSuicideText"); - jekyllAndHydeSuicideButton.isEffectActive = true; + ) + { + showButtonText = true, + buttonText = ModTranslation.getString("serialKillerSuicideText"), + isEffectActive = true + }; jekyllAndHydeDrugButton = new CustomButton( // OnClick @@ -1729,21 +1737,21 @@ public static void createButtonsPostfix(HudManager __instance) { trapperSetTrapButton = new CustomButton( () => - { // ボタンが兀されたrにg佩 + { // 帥潟若絎茵 if (!CachedPlayer.LocalPlayer.PlayerControl.CanMove || Trap.hasTrappedPlayer()) return; Trapper.setTrap(); trapperSetTrapButton.Timer = trapperSetTrapButton.MaxTimer; }, () => - { /*ボタン嗤燭砲覆詭周*/ + { /*帥恰鴻>散*/ return CachedPlayer.LocalPlayer.PlayerControl == Trapper.trapper && !CachedPlayer.LocalPlayer.PlayerControl.Data.IsDead; }, () => - { /*ボタンが聞える訳周*/ + { /*帥潟篏帥>散*/ return CachedPlayer.LocalPlayer.PlayerControl.CanMove && !Trap.hasTrappedPlayer(); }, () => - { /*ミ`ティングK阻r*/ + { /*若c潟亥篋*/ trapperSetTrapButton.Timer = trapperSetTrapButton.MaxTimer; }, Trapper.getTrapButtonSprite(), @@ -1771,7 +1779,7 @@ public static void createButtonsPostfix(HudManager __instance) { RPCProcedure.setBrainwash(Moriarty.currentTarget.PlayerId); SoundEffectsManager.play("moriartyBrainwash"); - // 牢K阻までのカウントダウン + // 羇括篋障с潟 TMPro.TMP_Text text; RoomTracker roomTracker = HudManager.Instance?.roomTracker; GameObject gameObject = UnityEngine.Object.Instantiate(roomTracker.gameObject); @@ -2626,8 +2634,10 @@ public static void createButtonsPostfix(HudManager __instance) { CustomButton.ButtonPositions.upperRowLeft, // Vector3 PositionOffset __instance, // HudManager hudManager KeyCode.F - ); - undertakerDragButton.showButtonText = ModTranslation.getString("DropBodyText") != ""; + ) + { + showButtonText = ModTranslation.getString("DropBodyText") != "" + }; buskerButton = new CustomButton( () => @@ -2653,12 +2663,12 @@ public static void createButtonsPostfix(HudManager __instance) { if (buskerButton.isEffectActive) { buskerButton.buttonText = ModTranslation.getString("ReviveText"); - buskerButton.resetKeyBind(); + buskerButton.resetKeyBind(); } else { buskerButton.buttonText = ModTranslation.getString("PseudocideText"); - buskerButton.resetKeyBind(); + buskerButton.resetKeyBind(); } return CachedPlayer.LocalPlayer.PlayerControl.CanMove && (!Busker.pseudocideFlag || MapData.GetCurrentMapData().CheckMapArea(CachedPlayer.LocalPlayer.PlayerControl.transform.position)); }, @@ -2694,8 +2704,10 @@ public static void createButtonsPostfix(HudManager __instance) { }, buttonText: ModTranslation.getString("PseudocideText"), abilityTexture: true - ); - buskerButton.effectCancellable = true; + ) + { + effectCancellable = true + }; noisemakerButton = new CustomButton( () => @@ -3084,28 +3096,29 @@ public static void createButtonsPostfix(HudManager __instance) { if (ninjaButton.isEffectActive) { ninjaButton.buttonText = ModTranslation.getString("NinjaUnstealthText"); - ninjaButton.resetKeyBind(); + ninjaButton.resetKeyBind(); } else { ninjaButton.buttonText = ModTranslation.getString("NinjaText"); - ninjaButton.resetKeyBind(); + ninjaButton.resetKeyBind(); } return CachedPlayer.LocalPlayer.PlayerControl.CanMove; }, - () => { + () => + { ninjaButton.Timer = ninjaButton.MaxTimer = Ninja.stealthCooldown; ninjaButton.actionButton.cooldownTimerText.color = Palette.EnabledColor; ninjaButton.isEffectActive = false; Ninja.stealthed = false; Ninja.ninja.SetKillTimer(GameOptionsManager.Instance.currentNormalGameOptions.KillCooldown + (Ninja.penalized ? Ninja.killPenalty : 0f)); }, - Ninja.getButtonSprite(), - //new Vector3(-1.8f, -0.06f, 0), + Ninja.getButtonSprite(), + //new Vector3(-1.8f, -0.06f, 0), CustomButton.ButtonPositions.upperRowLeft, __instance, - KeyCode.F, - true, + KeyCode.F, + true, Ninja.stealthDuration, () => { @@ -3120,8 +3133,10 @@ public static void createButtonsPostfix(HudManager __instance) { CachedPlayer.LocalPlayer.PlayerControl.SetKillTimer(Math.Max(CachedPlayer.LocalPlayer.PlayerControl.killTimer, Ninja.killPenalty)); }, buttonText: ModTranslation.getString("NinjaText") - ); - ninjaButton.effectCancellable = true; + ) + { + effectCancellable = true + }; foxStealthButton = new CustomButton( () => @@ -3143,12 +3158,12 @@ public static void createButtonsPostfix(HudManager __instance) { if (foxStealthButton.isEffectActive) { foxStealthButton.buttonText = ModTranslation.getString("FoxUnstealthText"); - foxStealthButton.resetKeyBind(); + foxStealthButton.resetKeyBind(); } else { foxStealthButton.buttonText = ModTranslation.getString("FoxStealthText"); - foxStealthButton.resetKeyBind(); + foxStealthButton.resetKeyBind(); } return CachedPlayer.LocalPlayer.PlayerControl.CanMove; }, @@ -3175,8 +3190,10 @@ public static void createButtonsPostfix(HudManager __instance) { }, buttonText: ModTranslation.getString("FoxStealthText"), abilityTexture: true - ); - foxStealthButton.effectCancellable = true; + ) + { + effectCancellable = true + }; foxRepairButton = new CustomButton( () => @@ -3316,12 +3333,14 @@ public static void createButtonsPostfix(HudManager __instance) { RPCProcedure.serialKillerSuicide(targetId); }, abilityTexture: true - ); - //UnityEngine.Object.Destroy(serialKillerButton.actionButton.buttonLabelText); - //serialKillerButton.actionButton.buttonLabelText = UnityEngine.Object.Instantiate(__instance.AbilityButton.buttonLabelText, serialKillerButton.actionButton.transform); - serialKillerButton.showButtonText = true; - serialKillerButton.buttonText = ModTranslation.getString("serialKillerSuicideText"); - serialKillerButton.isEffectActive = true; + ) + { + //UnityEngine.Object.Destroy(serialKillerButton.actionButton.buttonLabelText); + //serialKillerButton.actionButton.buttonLabelText = UnityEngine.Object.Instantiate(__instance.AbilityButton.buttonLabelText, serialKillerButton.actionButton.transform); + showButtonText = true, + buttonText = ModTranslation.getString("serialKillerSuicideText"), + isEffectActive = true + }; // Evil Tracker track evilTrackerButton = new CustomButton( @@ -3560,7 +3579,7 @@ Func fortuneTellerCouldUse(byte index) return () => { int adjustedIndex = index < CachedPlayer.LocalPlayer.PlayerId ? index : index - 1; - // 媼い參翌の栽、リソ`スがない栽はボタンを燕幣しない + //絽篁ュ翫純若鴻翫帥潟茵腓冴 if (!TORMapOptions.playerIcons.ContainsKey(index) || !CachedPlayer.LocalPlayer.PlayerControl == FortuneTeller.fortuneTeller || CachedPlayer.LocalPlayer.PlayerControl.Data.IsDead || @@ -3574,10 +3593,10 @@ Func fortuneTellerCouldUse(byte index) return false; } - // ボタンの了崔を筝 + // 帥潟篏臀紊 setButtonPos(index); - // ボタンにテキストをO協 + // 帥潟鴻荐絎 bool status = true; if (FortuneTeller.playerStatus.ContainsKey(index)) { @@ -3595,7 +3614,7 @@ Func fortuneTellerCouldUse(byte index) fortuneTellerButtons[index].buttonText = ModTranslation.getString("fortuneTellerDead"); } - // アイコンの了崔と邑苧業を筝 + // ≪ゃ潟潟篏臀綺紊 setIconPos(index, !FortuneTeller.canDivine(index)); TORMapOptions.playerIcons[index].gameObject.SetActive(!(MapBehaviour.Instance && MapBehaviour.Instance.IsOpen) && @@ -3790,7 +3809,8 @@ Func fortuneTellerCouldUse(byte index) ); sprintButton = new CustomButton( - () => { + () => + { if (sprintButton.isEffectActive) { sprintButton.Timer = 0; @@ -3835,7 +3855,8 @@ Func fortuneTellerCouldUse(byte index) KeyCode.F, true, Sprinter.sprintDuration, - () => { + () => + { sprintButton.Timer = sprintButton.MaxTimer = Sprinter.sprintCooldown; if (Sprinter.acTokenMove != null) Sprinter.acTokenMove.Value.cleared |= CachedPlayer.LocalPlayer.PlayerControl.GetTruePosition().Distance(Sprinter.acTokenMove.Value.pos) > 15f; MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SprinterSprint, Hazel.SendOption.Reliable, -1); @@ -3846,8 +3867,10 @@ Func fortuneTellerCouldUse(byte index) }, abilityTexture: true, buttonText: ModTranslation.getString("SprintText") - ); - sprintButton.effectCancellable = true; + ) + { + effectCancellable = true + }; // Assassin mark and assassinate button assassinButton = new CustomButton( @@ -3990,33 +4013,33 @@ Func fortuneTellerCouldUse(byte index) // Trapper button //trapperButton = 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)); - - MessageWriter writer = AmongUsClient.Instance.StartRpc(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.SetTrap, Hazel.SendOption.Reliable); - writer.WriteBytesAndSize(buff); - writer.EndMessage(); - RPCProcedure.setTrap(buff); - - SoundEffectsManager.play("trapperTrap"); - trapperButton.Timer = trapperButton.MaxTimer; - }, - () => { return Trapper.trapper != null && Trapper.trapper == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead; }, - () => { - if (trapperChargesText != null) trapperChargesText.text = $"{Trapper.charges} / {Trapper.maxCharges}"; - return CachedPlayer.LocalPlayer.PlayerControl.CanMove && Trapper.charges > 0; - }, - () => { trapperButton.Timer = trapperButton.MaxTimer; }, - Trapper.getButtonSprite(), - CustomButton.ButtonPositions.lowerRowRight, - __instance, - KeyCode.F - );*/ + /*() => { + + + 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)); + + MessageWriter writer = AmongUsClient.Instance.StartRpc(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.SetTrap, Hazel.SendOption.Reliable); + writer.WriteBytesAndSize(buff); + writer.EndMessage(); + RPCProcedure.setTrap(buff); + + SoundEffectsManager.play("trapperTrap"); + trapperButton.Timer = trapperButton.MaxTimer; + }, + () => { return Trapper.trapper != null && Trapper.trapper == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead; }, + () => { + if (trapperChargesText != null) trapperChargesText.text = $"{Trapper.charges} / {Trapper.maxCharges}"; + return CachedPlayer.LocalPlayer.PlayerControl.CanMove && Trapper.charges > 0; + }, + () => { trapperButton.Timer = trapperButton.MaxTimer; }, + Trapper.getButtonSprite(), + CustomButton.ButtonPositions.lowerRowRight, + __instance, + KeyCode.F + );*/ // Bomber button /*bomberButton = new CustomButton( @@ -4092,6 +4115,77 @@ Func fortuneTellerCouldUse(byte index) true );*/ + operateButton = new CustomButton( + () => { FreePlayGM.OpenRoleWindow(); }, + () => { return FreePlayGM.isFreePlayGM; }, + () => { return true; }, + () => { }, + FreePlayGM.getOperateButtonSprite(), + new Vector3(0f, 1f, 0f), + __instance, + KeyCode.Z, + true, + buttonText: ModTranslation.getString("FreePlayOperateText"), + abilityTexture: true + ); + + freePlayReviveButton = new CustomButton( + () => + { + PlayerControl.LocalPlayer.Revive(); + DeadBody[] array = UnityEngine.Object.FindObjectsOfType(); + for (int i = 0; i < array.Length; i++) + { + if (GameData.Instance.GetPlayerById(array[i].ParentId).PlayerId == PlayerControl.LocalPlayer.PlayerId) + { + UnityEngine.Object.Destroy(array[i].gameObject); + } + } + }, + () => { return FreePlayGM.isFreePlayGM && PlayerControl.LocalPlayer.Data.IsDead; }, + () => + { + return true; + }, + () => { }, + FreePlayGM.getReviveButtonSprite(), + new Vector3(1f, 1f, 0f), + __instance, + KeyCode.X, + true, + buttonText: ModTranslation.getString("FreePlayReviveText"), + abilityTexture: true + ); + + freePlaySuicideButton = new CustomButton( + () => + { + if (PlayerControl.LocalPlayer.AmOwner) + { + if (Constants.ShouldPlaySfx()) + { + SoundManager.Instance.PlaySound(PlayerControl.LocalPlayer.KillSfx, false, 0.8f); + } + PlayerControl.LocalPlayer.cosmetics.SetNameMask(false); + PlayerControl.LocalPlayer.RpcSetScanner(false); + } + PlayerControl.LocalPlayer.MyPhysics.StartCoroutine(PlayerControl.LocalPlayer.KillAnimations.First().CoPerformKill(PlayerControl.LocalPlayer, PlayerControl.LocalPlayer)); + }, + () => { return FreePlayGM.isFreePlayGM && !PlayerControl.LocalPlayer.Data.IsDead; }, + () => + { + return true; + }, + () => { }, + __instance.KillButton.graphic.sprite, + new Vector3(1f, 1f, 0f), + __instance, + KeyCode.X, + true, + buttonText: ModTranslation.getString("FreePlaySuicideText"), + abilityTexture: true + ); + thiefKillButton = new CustomButton( () => { PlayerControl thief = Thief.thief; @@ -4148,9 +4242,13 @@ Func fortuneTellerCouldUse(byte index) //trapperChargesText.transform.localPosition += new Vector3(-0.05f, 0.7f, 0); zoomOutButton = new CustomButton( - () => { Helpers.toggleZoom(); + () => + { + Helpers.toggleZoom(); }, - () => { if (CachedPlayer.LocalPlayer.PlayerControl == null || !CachedPlayer.LocalPlayer.Data.IsDead || CachedPlayer.LocalPlayer.Data.Role.IsImpostor || (CachedPlayer.LocalPlayer.PlayerControl == Busker.busker && Busker.pseudocideFlag)) return false; + () => + { + if (CachedPlayer.LocalPlayer.PlayerControl == null || !CachedPlayer.LocalPlayer.Data.IsDead || CachedPlayer.LocalPlayer.Data.Role.IsImpostor || (CachedPlayer.LocalPlayer.PlayerControl == Busker.busker && Busker.pseudocideFlag)) return false; var (playerCompleted, playerTotal) = TasksHandler.taskInfo(CachedPlayer.LocalPlayer.Data); int numberOfLeftTasks = playerTotal - playerCompleted; return numberOfLeftTasks <= 0 || !CustomOptionHolder.finishTasksBeforeHauntingOrZoomingOut.getBool(); @@ -4161,8 +4259,10 @@ Func fortuneTellerCouldUse(byte index) new Vector3(0.4f, 2.8f, 0), __instance, KeyCode.KeypadPlus - ); - zoomOutButton.Timer = 0f; + ) + { + Timer = 0f + }; hunterLighterButton = new CustomButton( diff --git a/TheOtherRoles/CustomGameModes/FreePlayGM.cs b/TheOtherRoles/CustomGameModes/FreePlayGM.cs new file mode 100644 index 0000000..607eaf1 --- /dev/null +++ b/TheOtherRoles/CustomGameModes/FreePlayGM.cs @@ -0,0 +1,240 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using AmongUs.GameOptions; +using HarmonyLib; +using MonoMod.Cil; +using TheOtherRoles.MetaContext; +using TheOtherRoles.Objects; +using TheOtherRoles.Patches; +using TheOtherRoles.Players; +using UnityEngine; + +namespace TheOtherRoles.CustomGameModes +{ + public static class FreePlayGM + { + public static bool isFreePlayGM = false; + public static Sprite operateButtonSprite; + public static Sprite reviveSprite; + + public static Sprite getOperateButtonSprite() + { + if (operateButtonSprite) return operateButtonSprite; + operateButtonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.OperateButton.png", 115f); + return operateButtonSprite; + } + + public static Sprite getReviveButtonSprite() + { + if (reviveSprite) return reviveSprite; + reviveSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.ReviveButton.png", 115f); + return reviveSprite; + } + + public static void OpenRoleWindow() + { + var window = MetaScreen.GenerateWindow(new Vector2(7.5f, 4.5f), HudManager.Instance.transform, new Vector3(0, 0, -400f), true, false); + + var gui = TORGUIContextEngine.Instance; + var roleMaskedTittleAttr = gui.GetAttribute(AttributeAsset.MetaRoleButton); + var roleTittleAttr = new TextAttributes(roleMaskedTittleAttr) { Font = gui.GetFont(FontAsset.Gothic) }; + + void SetWidget(int tab) + { + List guis = new() + { gui.LocalizedButton(GUIAlignment.Center, roleTittleAttr, "freePlayRoles", () => SetWidget(0), color: tab == 0 ? Color.yellow : null), + gui.LocalizedButton(GUIAlignment.Center, roleTittleAttr, "freePlayModifiers", () => SetWidget(1), color: tab == 1 ? Color.yellow : null)}; + var holder = gui.HorizontalHolder(GUIAlignment.Center, + guis + ); + + GUIContext inner = GUIEmptyWidget.Default; + + if (tab == 0) + { + inner = gui.Arrange(GUIAlignment.Center, RoleInfo.allRoleInfos.Where(x => x != RoleInfo.bomberB && x != RoleInfo.bomberA && x != RoleInfo.jackal + && x != RoleInfo.sidekick && x != RoleInfo.mimicA && x != RoleInfo.mimicK && x != RoleInfo.arsonist && x != RoleInfo.bountyHunter && !x.isModifier).Select(r => gui.RawButton(GUIAlignment.Center, roleMaskedTittleAttr, Helpers.cs(r.color, r.name), () => + { + var formerRole = RoleInfo.getRoleInfoForPlayer(PlayerControl.LocalPlayer, false).FirstOrDefault(); + if (formerRole == r) return; // Do nothing if the same role was given + RPCProcedure.erasePlayerRoles(PlayerControl.LocalPlayer.PlayerId); + if (r.isImpostor() && !formerRole.isImpostor()) PlayerControl.LocalPlayer.FastSetRole(RoleTypes.Impostor); + else if (!r.isImpostor() && formerRole.isImpostor()) PlayerControl.LocalPlayer.FastSetRole(RoleTypes.Crewmate); + + if (r == RoleInfo.chainshifter) Shifter.isNeutral = true; + else if (r == RoleInfo.niceshifter) Shifter.isNeutral = false; + RPCProcedure.setRole((byte)r.roleId, PlayerControl.LocalPlayer.PlayerId); + + if (r.roleId == RoleId.Fox) { + if (Shrine.allShrine?.FirstOrDefault() == null){ + Shrine.activateShrines(GameOptionsManager.Instance.currentNormalGameOptions.MapId);System.Console.WriteLine("1"); + } + List taskIdList = new(); + Shrine.allShrine.ForEach(shrine => taskIdList.Add((byte)shrine.console.ConsoleId)); + taskIdList.Shuffle(); + var cpt = new CustomNormalPlayerTask("foxTaskStay", Il2CppType.Of(), Fox.numTasks, taskIdList.ToArray(), Shrine.allShrine.Find(x => x.console.ConsoleId == taskIdList.ToArray()[0]).console.Room, true); + cpt.addTaskToPlayer(CachedPlayer.LocalPlayer.PlayerId); + } else if (r.roleId == RoleId.JekyllAndHyde) { + CachedPlayer.LocalPlayer.PlayerControl.generateAndAssignTasks(JekyllAndHyde.numCommonTasks, JekyllAndHyde.numShortTasks, JekyllAndHyde.numLongTasks); + } else if (formerRole.roleId == RoleId.Fox || formerRole.roleId == RoleId.JekyllAndHyde || formerRole.roleId == RoleId.TaskMaster) { + var options = GameOptionsManager.Instance.currentNormalGameOptions; + PlayerControl.LocalPlayer.generateAndAssignTasks(options.NumCommonTasks, options.NumShortTasks, options.NumLongTasks); + } + RPCProcedure.resetAchievement(); + window.CloseScreen(); + })), 4); + } + else if (tab == 1) + { + inner = gui.VerticalHolder(GUIAlignment.Center, + new List() { gui.LocalizedText(GUIAlignment.Center, roleMaskedTittleAttr, "freePlayModifiersEquipped"), + gui.Arrange(GUIAlignment.Center, RoleInfo.allRoleInfos.Where(r => r.isModifier && RoleInfo.getRoleInfoForPlayer(PlayerControl.LocalPlayer).Contains(r)).Select(r => gui.RawButton(GUIAlignment.Center, roleMaskedTittleAttr, Helpers.cs(r.color, r.name), () => + { + removeModifier(r.roleId); + SetWidget(1); + })), 4), + gui.LocalizedText(GUIAlignment.Center, roleMaskedTittleAttr, "freePlayModifiersUnequipped"), + gui.Arrange(GUIAlignment.Center, RoleInfo.allRoleInfos.Where(r => r.isModifier && r != RoleInfo.cupidLover && r != RoleInfo.lover && r != RoleInfo.mini && !RoleInfo.getRoleInfoForPlayer(PlayerControl.LocalPlayer).Contains(r)).Select(r => gui.RawButton(GUIAlignment.Center, roleMaskedTittleAttr, Helpers.cs(r.color, r.name), () => + { + RPCProcedure.setModifier((byte)r.roleId, PlayerControl.LocalPlayer.PlayerId, 0); + SetWidget(1); + })), 4)} + ); + } + window.SetContext(gui.VerticalHolder(GUIAlignment.Center, new List() { holder, gui.ScrollView(GUIAlignment.Center, new(7.4f, 3.5f), null, inner, out _) }), out _); + } + + SetWidget(0); + } + + private static void FastSetRole(this PlayerControl targetPlayer, RoleTypes roleType) + { + NetworkedPlayerInfo data = targetPlayer.Data; + RoleBehaviour roleBehaviour = UnityEngine.Object.Instantiate(RoleManager.Instance.AllRoles.First(r => r.Role == roleType), data.gameObject.transform); + roleBehaviour.Initialize(targetPlayer); + targetPlayer.Data.Role = roleBehaviour; + targetPlayer.Data.RoleType = roleType; + if (roleType != RoleTypes.ImpostorGhost && roleType != RoleTypes.CrewmateGhost) + targetPlayer.Data.RoleWhenAlive = new Il2CppSystem.Nullable(roleType); + roleBehaviour.AdjustTasks(targetPlayer); + } + + private static bool isImpostor(this RoleInfo roleInfo) => roleInfo.color == Palette.ImpostorRed && roleInfo.roleId != RoleId.Spy; + + public static void removeModifier(RoleId modifierId) + { + var player = PlayerControl.LocalPlayer; + var playerId = player.PlayerId; + switch (modifierId) + { + case RoleId.AntiTeleport: + AntiTeleport.antiTeleport.RemoveAll(x => x.PlayerId == playerId); + break; + case RoleId.Chameleon: + Chameleon.chameleon.RemoveAll(x => x.PlayerId == playerId); + break; + case RoleId.Mini: + Mini.mini = null; + break; + case RoleId.Invert: + Invert.invert.RemoveAll(x => x.PlayerId == playerId); + break; + case RoleId.Bloody: + Bloody.bloody.RemoveAll(x => x.PlayerId == playerId); + break; + case RoleId.Sunglasses: + Sunglasses.sunglasses.RemoveAll(x => x.PlayerId == playerId); + break; + case RoleId.Tiebreaker: + Tiebreaker.tiebreaker = null; + break; + case RoleId.Vip: + Vip.vip.RemoveAll(x => x.PlayerId == playerId); + break; + } + } + + public static PlayerControl SpawnDummy() + { + var playerControl = UnityEngine.Object.Instantiate(AmongUsClient.Instance.PlayerPrefab); + var i = playerControl.PlayerId = (byte)GameData.Instance.GetAvailableId(); + + playerControl.isDummy = true; + + var playerInfo = GameData.Instance.AddDummy(playerControl); + + playerControl.transform.position = PlayerControl.LocalPlayer.transform.position; + playerControl.GetComponent().enabled = true; + playerControl.isDummy = true; + playerControl.SetName(AccountManager.Instance.GetRandomName()); + playerControl.SetColor(i); + playerControl.SetHat(CosmeticsLayer.EMPTY_HAT_ID, i); + playerControl.SetVisor(CosmeticsLayer.EMPTY_VISOR_ID, i); + playerControl.SetSkin(CosmeticsLayer.EMPTY_SKIN_ID, i); + playerControl.SetPet(CosmeticsLayer.EMPTY_PET_ID, i); + + AmongUsClient.Instance.Spawn(playerControl, -2, InnerNet.SpawnFlags.None); + playerInfo.RpcSetTasks(new byte[0]); + + return playerControl; + } + + public static void clearAndReload() + { + isFreePlayGM = TORMapOptions.gameMode == CustomGamemodes.FreePlay; + } + + [HarmonyPatch(typeof(GameStartManager), nameof(GameStartManager.BeginGame))] + public class GameStartManagerBeginGame + { + public static bool Prefix(GameStartManager __instance) + { + if (TORMapOptions.gameMode == CustomGamemodes.FreePlay) + { + if (AmongUsClient.Instance.AmHost && PlayerControl.AllPlayerControls.Count == 1) + { + var numDummies = CustomOptionHolder.freePlayGameModeNumDummies != null ? (int)CustomOptionHolder.freePlayGameModeNumDummies.getFloat() : 0; + for (int i = 0; i < numDummies; i++) SpawnDummy(); + } + } + return true; + } + } + + [HarmonyPatch(typeof(GameManager), nameof(GameManager.CheckTaskCompletion))] + static class CheckTaskCompletionPatch + { + static bool Prefix(GameManager __instance, ref bool __result) + { + if (!isFreePlayGM) return true; + __result = false; + return false; + } + } + + [HarmonyPatch(typeof(GameManager), nameof(GameManager.CheckEndGameViaTasks))] + static class CheckEndGameViaTasksPatch + { + static bool Prefix(GameManager __instance, ref bool __result) + { + if (!isFreePlayGM) return true; + __result = false; + return false; + } + } + + [HarmonyPatch(typeof(LogicGameFlowNormal), nameof(LogicGameFlowNormal.IsGameOverDueToDeath))] + public static class BlockGameOverPatch + { + public static bool Prefix(LogicGameFlowNormal __instance, ref bool __result) + { + if (!isFreePlayGM) return true; + __result = false; + return false; + } + } + } +} diff --git a/TheOtherRoles/CustomGameModes/GameModePatches.cs b/TheOtherRoles/CustomGameModes/GameModePatches.cs index 5960416..86b2e3e 100644 --- a/TheOtherRoles/CustomGameModes/GameModePatches.cs +++ b/TheOtherRoles/CustomGameModes/GameModePatches.cs @@ -1,4 +1,4 @@ -鏤using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -46,7 +46,7 @@ public static void Postfix(LobbyInfoPane __instance) gameModeButton.transform.GetChild(2).GetComponent().color = new Color(0f, 0f, 0f); pButton.OnClick.AddListener((Action)(() => { - TORMapOptions.gameMode = (CustomGamemodes)((int)(TORMapOptions.gameMode + 1) % Enum.GetNames(typeof(CustomGamemodes)).Length); + TORMapOptions.gameMode = (CustomGamemodes)((int)(TORMapOptions.gameMode + 1) % (Enum.GetNames(typeof(CustomGamemodes)).Length - 1)); __instance.StartCoroutine(Effects.Lerp(0.1f, new Action(p => { pButton.buttonText.text = Helpers.cs(Color.yellow, GameModeText.GetComponent().text); }))); MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.ShareGamemode, Hazel.SendOption.Reliable, -1); writer.Write((byte)TORMapOptions.gameMode); @@ -67,4 +67,4 @@ public static void Postfix(LobbyInfoPane __instance) } } } -} \ No newline at end of file +} diff --git a/TheOtherRoles/CustomOptionHolder.cs b/TheOtherRoles/CustomOptionHolder.cs index 402b3c4..b90e5f3 100644 --- a/TheOtherRoles/CustomOptionHolder.cs +++ b/TheOtherRoles/CustomOptionHolder.cs @@ -24,6 +24,7 @@ public class CustomOptionHolder { public static CustomOption enableEventMode; public static CustomOption anyPlayerCanStopStart; + public static CustomOption freePlayGameModeNumDummies; public static CustomOption mafiaSpawnRate; public static CustomOption janitorCooldown; @@ -1175,7 +1176,8 @@ public static void Load() { huntedShieldNumber = CustomOption.Create(3026, Types.HideNSeekRoles, cs(Color.gray, "huntedShieldNumber"), 3f, 1f, 15f, 1f, format: "unitScrews"); // Other options - maxNumberOfMeetings = CustomOption.Create(3, Types.General, "maxNumberOfMeetings", 10, 0, 15, 1, null, true, "unitShots", heading: "headingGameplay"); + maxNumberOfMeetings = CustomOption.Create(3, Types.General, "maxNumberOfMeetings", 10, 0, 15, 1, null, true, "unitShots", heading: "headingGameplay"); + freePlayGameModeNumDummies = CustomOption.Create(10424, Types.General, cs(Color.green, "freePlayGameModeNumDummies"), 1f, 1f, 23f, 1f, format: "unitPlayers"); anyPlayerCanStopStart = CustomOption.Create(2, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "anyPlayerCanStopStart"), false, null, false); blockSkippingInEmergencyMeetings = CustomOption.Create(4, Types.General, "blockSkippingInEmergencyMeetings", false); noVoteIsSelfVote = CustomOption.Create(5, Types.General, "noVoteIsSelfVote", false, blockSkippingInEmergencyMeetings); diff --git a/TheOtherRoles/Helpers.cs b/TheOtherRoles/Helpers.cs index 85c7437..7da91af 100644 --- a/TheOtherRoles/Helpers.cs +++ b/TheOtherRoles/Helpers.cs @@ -41,7 +41,8 @@ public enum MurderAttemptResult { public enum CustomGamemodes { Classic, Guesser, - HideNSeek + HideNSeek, + FreePlay } public static class Direction diff --git a/TheOtherRoles/Main.cs b/TheOtherRoles/Main.cs index 85bb120..e112c88 100644 --- a/TheOtherRoles/Main.cs +++ b/TheOtherRoles/Main.cs @@ -1,4 +1,4 @@ -鏤global using Il2CppInterop.Runtime; +global using Il2CppInterop.Runtime; global using Il2CppInterop.Runtime.Attributes; global using Il2CppInterop.Runtime.InteropTypes; global using Il2CppInterop.Runtime.InteropTypes.Arrays; diff --git a/TheOtherRoles/MetaContext/MetaContext.cs b/TheOtherRoles/MetaContext/MetaContext.cs index 95b54ea..ef2cb5a 100644 --- a/TheOtherRoles/MetaContext/MetaContext.cs +++ b/TheOtherRoles/MetaContext/MetaContext.cs @@ -1,4 +1,4 @@ -鏤using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -476,12 +476,33 @@ public TextAttributes GetAttribute(AttributeAsset attribute) AttributeAsset.OblongHeader => new TextAttributes(TextAlignment.Left, GetFont(FontAsset.Oblong), FontStyle.Normal, new(5.2f, false), new(0.45f, 3f), new(255, 255, 255), true), AttributeAsset.StandardMediumMasked => new TextAttributes(TextAlignment.Center, GetFont(FontAsset.Gothic), FontStyle.Bold, new(1.6f, 0.8f, 1.6f), new(1.45f, 0.3f), new(255, 255, 255), false), AttributeAsset.StandardLargeWideMasked => new TextAttributes(TextAlignment.Center, GetFont(FontAsset.Gothic), FontStyle.Bold, new(1.7f, 1f, 1.7f), new(2.9f, 0.45f), new(255, 255, 255), false), - AttributeAsset.OverlayContent => new TextAttributes(Instance.GetAttribute(AttributeParams.StandardBaredLeft)) { FontSize = new(1.5f, 1.1f, 1.5f), Size = new(5f, 6f) }, + AttributeAsset.OverlayContent => new TextAttributes(Instance.GetAttribute(AttributeParams.StandardBaredLeft)) { FontSize = new(1.5f, 1.1f, 1.5f), Size = new(5f, 6f) }, + AttributeAsset.MetaRoleButton => new TextAttributes(TextAlignment.Center, GetFont(FontAsset.GothicMasked), FontStyle.Bold, new(1.8f, 1f, 2f), new(1.4f, 0.26f), new(255, 255, 255), false), _ => null! }; } return allAttrAsset[attribute]; + } + + public GUIContext Arrange(GUIAlignment alignment, IEnumerable inner, int perLine) + { + List widgets = new(); + List horizontalWidgets = new(); + foreach (var widget in inner) + { + if (widget == null) continue; + + horizontalWidgets.Add(widget); + if (horizontalWidgets.Count == perLine) + { + widgets.Add(HorizontalHolder(alignment, horizontalWidgets.ToArray())); + horizontalWidgets.Clear(); + } + } + if (horizontalWidgets.Count > 0) widgets.Add(HorizontalHolder(alignment, horizontalWidgets)); + + return VerticalHolder(alignment, widgets); } public TextAttributes GenerateAttribute(AttributeParams attribute, Color color, FontSize fontSize, Size size) @@ -559,6 +580,21 @@ public GUIContext Button(GUIAlignment alignment, TextAttributes attribute, TextC public TextComponent LocalizedTextComponent(string translationKey) => new TranslateTextComponent(translationKey); public TextComponent ColorTextComponent(Color color, TextComponent component) => new ColorTextComponent(color, component); + } + + public class GUIEmptyWidget : AbstractGUIContext + { + static public GUIEmptyWidget Default = new(); + + public GUIEmptyWidget(GUIAlignment alignment = GUIAlignment.Left) : base(alignment) + { + } + + public override GameObject Instantiate(Size size, out Size actualSize) + { + actualSize = new(0f, 0f); + return null; + } } public class TORGUIImage : AbstractGUIContext diff --git a/TheOtherRoles/MetaContext/MetaGUI.cs b/TheOtherRoles/MetaContext/MetaGUI.cs index b9a9b18..90d6712 100644 --- a/TheOtherRoles/MetaContext/MetaGUI.cs +++ b/TheOtherRoles/MetaContext/MetaGUI.cs @@ -1,4 +1,4 @@ -鏤using System; +using System; using System.Collections; using System.Collections.Generic; using System.Linq; @@ -282,7 +282,16 @@ public interface GUI /// 潟潟鴻臀篏臀 /// 筝鴻潟潟鴻 /// 潟潟鴻絎臂 - GUIContext HorizontalHolder(GUIAlignment alignment, params GUIContext[] inner) => HorizontalHolder(alignment, inner, null); + GUIContext HorizontalHolder(GUIAlignment alignment, params GUIContext[] inner) => HorizontalHolder(alignment, inner, null); + + /// + /// c吾絎違ょ研劫篌吾違臀障 + /// + /// + /// + /// + /// + GUIContext Arrange(GUIAlignment alignment, IEnumerable inner, int perLine); /// /// 篏純茵潟潟鴻с荀眼篏睡障 diff --git a/TheOtherRoles/MetaContext/MetaText.cs b/TheOtherRoles/MetaContext/MetaText.cs index 3f81af0..c4c2a78 100644 --- a/TheOtherRoles/MetaContext/MetaText.cs +++ b/TheOtherRoles/MetaContext/MetaText.cs @@ -1,4 +1,4 @@ -鏤using System; +using System; using System.Linq; using TMPro; using UnityEngine; @@ -113,6 +113,11 @@ public enum AttributeAsset /// 筝祉若若ゅ紊泣ゃ冴鴻絮сс /// OverlayContent, + + /// + /// 若ゃ綵壕潔御帥潟т戎鴻絮сс + /// + MetaRoleButton, } [Flags] @@ -243,4 +248,4 @@ public FuzzySize(float? width, float? height) Width = width; Height = height; if (!Width.HasValue && !Height.HasValue) Width = 1f; } -} \ No newline at end of file +} diff --git a/TheOtherRoles/Modules/CustomOptions.cs b/TheOtherRoles/Modules/CustomOptions.cs index f045149..2597735 100644 --- a/TheOtherRoles/Modules/CustomOptions.cs +++ b/TheOtherRoles/Modules/CustomOptions.cs @@ -588,7 +588,7 @@ public static void createSettingTabs(LobbyViewSettingsPane __instance) { // Handle different gamemodes and tabs needed therein. int next = 3; - if (TORMapOptions.gameMode == CustomGamemodes.Guesser || TORMapOptions.gameMode == CustomGamemodes.Classic) + if (TORMapOptions.gameMode == CustomGamemodes.Guesser || TORMapOptions.gameMode == CustomGamemodes.Classic || TORMapOptions.gameMode == CustomGamemodes.FreePlay) { // create TOR settings @@ -974,6 +974,8 @@ public static void createGameOptionsMenu(GameSettingMenu __instance, CustomOptio var relevantOptions = options.Where(x => x.type == optionType).ToList(); if (TORMapOptions.gameMode == CustomGamemodes.Guesser) // Exclude guesser options in neutral mode relevantOptions = relevantOptions.Where(x => !(new List { 310, 311, 312, 313, 314, 315, 316, 317, 318 }).Contains(x.id)).ToList(); + if (TORMapOptions.gameMode != CustomGamemodes.FreePlay) + relevantOptions = relevantOptions.Where(x => x.id != 10424).ToList(); createSettings(torSettingsGOM, relevantOptions); currentTabs.Add(torSettingsTab); @@ -984,7 +986,7 @@ private static void createSettingTabs(GameSettingMenu __instance) { // Handle different gamemodes and tabs needed therein. int next = 3; - if (TORMapOptions.gameMode == CustomGamemodes.Guesser || TORMapOptions.gameMode == CustomGamemodes.Classic) + if (TORMapOptions.gameMode == CustomGamemodes.Guesser || TORMapOptions.gameMode == CustomGamemodes.Classic || TORMapOptions.gameMode == CustomGamemodes.FreePlay) { // create TOR settings @@ -1121,7 +1123,8 @@ private static string buildOptionsOfType(CustomOption.CustomOptionType type, boo options = options.Where(x => !(x.type == CustomOption.CustomOptionType.Guesser || x == CustomOptionHolder.crewmateRolesFill)); else if (TORMapOptions.gameMode == CustomGamemodes.HideNSeek) options = options.Where(x => (x.type == CustomOption.CustomOptionType.HideNSeekMain || x.type == CustomOption.CustomOptionType.HideNSeekRoles)); - + if (TORMapOptions.gameMode != CustomGamemodes.FreePlay) + options = options.Where(x => x.id != 10424); foreach (var option in options) { if (option.parent == null) { string line = $"{option.getName()}: {option.getString()}"; diff --git a/TheOtherRoles/Patches/CreateOptionsPickerPatch.cs b/TheOtherRoles/Patches/CreateOptionsPickerPatch.cs index 9d13599..c8fab44 100644 --- a/TheOtherRoles/Patches/CreateOptionsPickerPatch.cs +++ b/TheOtherRoles/Patches/CreateOptionsPickerPatch.cs @@ -1,4 +1,4 @@ -鏤using AmongUs.GameOptions; +using AmongUs.GameOptions; using HarmonyLib; using System; using System.Collections.Generic; @@ -19,14 +19,19 @@ public static bool Prefix(CreateOptionsPicker __instance, ref GameModes mode) { } __instance.SetGameMode(GameModes.Normal); //__instance.Refresh(); - - if ((int)mode == 3) { + CustomGamemodes gm = (CustomGamemodes)((int)mode - 2); + if (gm == CustomGamemodes.Guesser) { __instance.GameModeText.text = ModTranslation.getString("torGuesser"); TORMapOptions.gameMode = CustomGamemodes.Guesser; - } else { + } + else if (gm == CustomGamemodes.HideNSeek) { __instance.GameModeText.text = ModTranslation.getString("torHideNSeek"); TORMapOptions.gameMode = CustomGamemodes.HideNSeek; } + else if (gm == CustomGamemodes.FreePlay) { + __instance.GameModeText.text = ModTranslation.getString("torFreePlay"); + TORMapOptions.gameMode = CustomGamemodes.FreePlay; + } return false; } @@ -39,6 +44,10 @@ public static void Postfix(CreateOptionsPicker __instance) { else if (TORMapOptions.gameMode == CustomGamemodes.HideNSeek) { __instance.GameModeText.text = ModTranslation.getString("torHideNSeek"); } + else if (TORMapOptions.gameMode == CustomGamemodes.FreePlay) + { + __instance.GameModeText.text = ModTranslation.getString("torFreePlay"); + } } } @@ -60,13 +69,16 @@ public static bool Prefix(GameModeMenu __instance) { chatLanguageButton.Text.text = DestroyableSingleton.Instance.GetString(GameModesHelpers.ModeToName[entry], new Il2CppReferenceArray(0)); else { chatLanguageButton.Text.text = i == 3 ? ModTranslation.getString("torGuesser") : ModTranslation.getString("torHideNSeek"); + if (i == 5) + chatLanguageButton.Text.text = "TOR Fee Play"; } chatLanguageButton.Button.OnClick.RemoveAllListeners(); chatLanguageButton.Button.OnClick.AddListener((System.Action)delegate { __instance.ChooseOption(entry); }); - bool isCurrentMode = i <= 2 && TORMapOptions.gameMode == CustomGamemodes.Classic ? (long)entry == (long)((ulong)gameMode) : (i == 3 && TORMapOptions.gameMode == CustomGamemodes.Guesser || i == 4 && TORMapOptions.gameMode == CustomGamemodes.HideNSeek); + bool isCurrentMode = i <= 2 && TORMapOptions.gameMode == CustomGamemodes.Classic ? (long)entry == (long)((ulong)gameMode) : (i == 3 && TORMapOptions.gameMode == CustomGamemodes.Guesser || i == 4 && TORMapOptions.gameMode == CustomGamemodes.HideNSeek + || i == 5 && TORMapOptions.gameMode == CustomGamemodes.FreePlay); chatLanguageButton.SetSelected(isCurrentMode); __instance.controllerSelectable.Add(chatLanguageButton.Button); if (isCurrentMode) { diff --git a/TheOtherRoles/Patches/CredentialsPatch.cs b/TheOtherRoles/Patches/CredentialsPatch.cs index 696c1ef..a86ac80 100644 --- a/TheOtherRoles/Patches/CredentialsPatch.cs +++ b/TheOtherRoles/Patches/CredentialsPatch.cs @@ -1,4 +1,4 @@ -鏤using AmongUs.GameOptions; +using AmongUs.GameOptions; using HarmonyLib; using System; using System.Collections.Generic; @@ -34,6 +34,7 @@ static void Postfix(PingTracker __instance){ string gameModeText = $""; if (HideNSeek.isHideNSeekGM) gameModeText = ModTranslation.getString("gamemodeHideNSeek"); else if (HandleGuesser.isGuesserGm) gameModeText = ModTranslation.getString("gamemodeGuesser"); + else if (FreePlayGM.isFreePlayGM) gameModeText = ModTranslation.getString("gamemodeFreePlay"); if (gameModeText != "") gameModeText = Helpers.cs(Color.yellow, gameModeText) + "\n"; __instance.text.text = $"{Helpers.GradientColorText("FFD700", "FF0000", $"TheOtherRoles GM IA")}" + $" v{TheOtherRolesPlugin.Version.ToString() + (TheOtherRolesPlugin.betaDays > 0 ? "-BETA" : "")}\n{gameModeText}" + __instance.text.text; position.DistanceFromEdge = new Vector3(1.5f, 0.11f, 0); @@ -41,6 +42,7 @@ static void Postfix(PingTracker __instance){ string gameModeText = $""; if (TORMapOptions.gameMode == CustomGamemodes.HideNSeek) gameModeText = ModTranslation.getString("gamemodeHideNSeek"); else if (TORMapOptions.gameMode == CustomGamemodes.Guesser) gameModeText = ModTranslation.getString("gamemodeGuesser"); + else if (TORMapOptions.gameMode == CustomGamemodes.FreePlay) gameModeText = ModTranslation.getString("gamemodeFreePlay"); if (gameModeText != "") gameModeText = Helpers.cs(Color.yellow, gameModeText); __instance.text.text = $"{ModTranslation.getString(fullCredentialsVersion)}\n{ModTranslation.getString(fullCredentials)}\n {__instance.text.text}"; diff --git a/TheOtherRoles/Patches/EndGamePatch.cs b/TheOtherRoles/Patches/EndGamePatch.cs index 7e9c13a..0cc922c 100644 --- a/TheOtherRoles/Patches/EndGamePatch.cs +++ b/TheOtherRoles/Patches/EndGamePatch.cs @@ -256,8 +256,10 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)]ref End // Mini lose if (miniLose) { EndGameResult.CachedWinners = new Il2CppSystem.Collections.Generic.List(); - CachedPlayerData wpd = new(Mini.mini.Data); - wpd.IsYou = false; // If "no one is the Mini", it will display the Mini, but also show defeat to everyone + CachedPlayerData wpd = new(Mini.mini.Data) + { + IsYou = false // If "no one is the Mini", it will display the Mini, but also show defeat to everyone + }; EndGameResult.CachedWinners.Add(wpd); AdditionalTempData.winCondition = WinCondition.MiniLose; } @@ -415,30 +417,40 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)]ref End // Jackal wins if nobody except jackal is alive AdditionalTempData.winCondition = WinCondition.JackalWin; EndGameResult.CachedWinners = new Il2CppSystem.Collections.Generic.List(); - CachedPlayerData wpd = new(Jackal.jackal.Data); - wpd.IsImpostor = false; + CachedPlayerData wpd = new(Jackal.jackal.Data) + { + IsImpostor = false + }; EndGameResult.CachedWinners.Add(wpd); // If there is a sidekick. The sidekick also wins if (Sidekick.sidekick != null) { - CachedPlayerData wpdSidekick = new(Sidekick.sidekick.Data); - wpdSidekick.IsImpostor = false; + CachedPlayerData wpdSidekick = new(Sidekick.sidekick.Data) + { + IsImpostor = false + }; EndGameResult.CachedWinners.Add(wpdSidekick); } foreach(var player in Jackal.formerJackals) { - CachedPlayerData wpdFormerJackal = new(player.Data); - wpdFormerJackal.IsImpostor = false; + CachedPlayerData wpdFormerJackal = new(player.Data) + { + IsImpostor = false + }; EndGameResult.CachedWinners.Add(wpdFormerJackal); } if (SchrodingersCat.team == SchrodingersCat.Team.Jackal) { if (SchrodingersCat.schrodingersCat != null) { - CachedPlayerData wpdSchrodingersCat = new(SchrodingersCat.schrodingersCat.Data); + CachedPlayerData wpdSchrodingersCat = new(SchrodingersCat.schrodingersCat.Data) { + IsImpostor = false + }; EndGameResult.CachedWinners.Add(wpdSchrodingersCat); } if (SchrodingersCat.formerSchrodingersCat != null) { - CachedPlayerData wpdSchrodingersCat = new(SchrodingersCat.formerSchrodingersCat.Data); + CachedPlayerData wpdSchrodingersCat = new(SchrodingersCat.formerSchrodingersCat.Data) { + IsImpostor = false + }; EndGameResult.CachedWinners.Add(wpdSchrodingersCat); } } @@ -802,6 +814,7 @@ public static bool Prefix(ShipStatus __instance) { if (!GameData.Instance) return false; if (DestroyableSingleton.InstanceExists) // InstanceExists | Don't check Custom Criteria when in Tutorial return true; + if (FreePlayGM.isFreePlayGM) return false; var statistics = new PlayerStatistics(__instance); if (CheckAndEndGameForMiniLose(__instance)) return false; if (CheckAndEndGameForJesterWin(__instance)) return false; diff --git a/TheOtherRoles/Patches/GameStartManagerPatch.cs b/TheOtherRoles/Patches/GameStartManagerPatch.cs index 703a22a..9d0edfd 100644 --- a/TheOtherRoles/Patches/GameStartManagerPatch.cs +++ b/TheOtherRoles/Patches/GameStartManagerPatch.cs @@ -16,13 +16,6 @@ public static class GameStartManagerUpdatePatch public static void Prefix(GameStartManager __instance) { __instance.MinPlayers = 1; - string str = ""; - if (__instance.LastPlayerCount > __instance.MinPlayers) - str = ""; - if (__instance.LastPlayerCount == __instance.MinPlayers) - str = ""; - if (AmongUsClient.Instance.NetworkMode == NetworkModes.LocalGame) - __instance.PlayerCounter.text = string.Format("{0}{1}/{2}", str, __instance.LastPlayerCount, 24); } } diff --git a/TheOtherRoles/Patches/HauntMenuMinigamePatch.cs b/TheOtherRoles/Patches/HauntMenuMinigamePatch.cs index 9232b62..1fee4ef 100644 --- a/TheOtherRoles/Patches/HauntMenuMinigamePatch.cs +++ b/TheOtherRoles/Patches/HauntMenuMinigamePatch.cs @@ -1,9 +1,10 @@ -鏤using HarmonyLib; +using HarmonyLib; using AmongUs.GameOptions; using System.Collections.Generic; using System.Linq; using TheOtherRoles.Players; using System; +using TheOtherRoles.CustomGameModes; namespace TheOtherRoles.Patches { [HarmonyPatch] @@ -72,6 +73,7 @@ public static void UpdatePostfix(HauntMenuMinigame __instance) { [HarmonyPatch(typeof(AbilityButton), nameof(AbilityButton.Update))] public static void showOrHideAbilityButtonPostfix(AbilityButton __instance) { bool isHideNSeek = GameOptionsManager.Instance.currentGameOptions.GameMode == GameModes.HideNSeek; + if (FreePlayGM.isFreePlayGM) return; if (Busker.busker != null && CachedPlayer.LocalPlayer.PlayerControl == Busker.busker && !(!Busker.pseudocideFlag && CachedPlayer.LocalPlayer.PlayerControl.Data.IsDead)) __instance.Hide(); if (CachedPlayer.LocalPlayer.PlayerControl == SchrodingersCat.schrodingersCat && !SchrodingersCat.isTrueDead) diff --git a/TheOtherRoles/Patches/IntroPatch.cs b/TheOtherRoles/Patches/IntroPatch.cs index 6bcf01a..8fd69ff 100644 --- a/TheOtherRoles/Patches/IntroPatch.cs +++ b/TheOtherRoles/Patches/IntroPatch.cs @@ -84,7 +84,7 @@ public static void Prefix(IntroCutscene __instance) { SoundEffectsManager.Load(); // Place props - if (CustomOptionHolder.activateProps.getBool()) + if (CustomOptionHolder.activateProps.getBool() && !FreePlayGM.isFreePlayGM) { Props.placeProps(); } diff --git a/TheOtherRoles/Patches/MainMenuPatch.cs b/TheOtherRoles/Patches/MainMenuPatch.cs index 02993ff..0b0b1c4 100644 --- a/TheOtherRoles/Patches/MainMenuPatch.cs +++ b/TheOtherRoles/Patches/MainMenuPatch.cs @@ -1,4 +1,4 @@ -鏤using System; +using System; using System.Collections.Generic; using HarmonyLib; using UnityEngine; @@ -189,9 +189,21 @@ public static void addSceneChangeCallbacks() { template.OnClick(); })); + var FreePlayButton = GameObject.Instantiate(gameButton, gameButton.parent); + FreePlayButton.transform.localPosition += new Vector3(3.4f, -0.5f); + var FreePlaytButtonText = FreePlayButton.GetComponentInChildren(); + var FreePlayButtonPassiveButton = FreePlayButton.GetComponentInChildren(); + + FreePlayButtonPassiveButton.OnClick = new Button.ButtonClickedEvent(); + FreePlayButtonPassiveButton.OnClick.AddListener((System.Action)(() => { + TORMapOptions.gameMode = CustomGamemodes.FreePlay; + template.OnClick(); + })); + template.StartCoroutine(Effects.Lerp(0.1f, new System.Action((p) => { guesserButtonText.SetText(ModTranslation.getString("torGuesser")); HideNSeekButtonText.SetText(ModTranslation.getString("torHideNSeek")); + FreePlaytButtonText.SetText(ModTranslation.getString("torFreePlay")); }))); })); } diff --git a/TheOtherRoles/Patches/MapBehaviourPatch.cs b/TheOtherRoles/Patches/MapBehaviourPatch.cs index 4e6ae9d..919e6c9 100644 --- a/TheOtherRoles/Patches/MapBehaviourPatch.cs +++ b/TheOtherRoles/Patches/MapBehaviourPatch.cs @@ -1,9 +1,10 @@ -鏤using HarmonyLib; +using HarmonyLib; using Hazel; using Reactor.Utilities.Extensions; using System; using System.Collections.Generic; using System.Linq; +using TheOtherRoles.CustomGameModes; using TheOtherRoles.Modules; using TheOtherRoles.Objects; using TheOtherRoles.Players; @@ -64,6 +65,7 @@ public static void reset() private static bool evilTrackerShowTask(MapTaskOverlay __instance) { + if (FreePlayGM.isFreePlayGM) return true; if (!MeetingHud.Instance) return true; // Only run in meetings, and then set the Position of the HerePoint to the Position before the Meeting! if (CachedPlayer.LocalPlayer.PlayerControl != EvilTracker.evilTracker || !EvilTracker.canSeeTargetTasks) return true; if (EvilTracker.target == null) return true; diff --git a/TheOtherRoles/Patches/PlayerControlPatch.cs b/TheOtherRoles/Patches/PlayerControlPatch.cs index c4a9c49..605fd6e 100644 --- a/TheOtherRoles/Patches/PlayerControlPatch.cs +++ b/TheOtherRoles/Patches/PlayerControlPatch.cs @@ -709,7 +709,7 @@ public static void plagueDoctorUpdate() } else { - // デ`タがoい栽は恬撹する + // 若帥<翫篏 if (!PlagueDoctor.progress.ContainsKey(p.PlayerId)) { PlagueDoctor.progress[p.PlayerId] = 0f; @@ -742,7 +742,7 @@ public static void plagueDoctorUpdate() { PlagueDoctor.progress[target.PlayerId] += Time.fixedDeltaTime; - // 麿のクライアントにM佩彜rを宥岑する + // 篁ゃ≪潟画倶ャ MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.PlagueDoctorUpdateProgress, Hazel.SendOption.Reliable, -1); writer.Write(target.PlayerId); writer.Write(PlagueDoctor.progress[target.PlayerId]); @@ -940,7 +940,7 @@ public static void updatePlayerInfo() { p.cosmetics.nameText.transform.parent.SetLocalZ(-0.0001f); // This moves both the name AND the colorblindtext behind objects (if the player is behind the object), like the rock on polus if ((Lawyer.lawyerKnowsRole && CachedPlayer.LocalPlayer.PlayerControl == Lawyer.lawyer && p == Lawyer.target) || (Akujo.knowsRoles && CachedPlayer.LocalPlayer.PlayerControl == Akujo.akujo && (p == Akujo.honmei || Akujo.keeps.Any(x => x.PlayerId == p.PlayerId))) || p == CachedPlayer.LocalPlayer.PlayerControl || (CachedPlayer.LocalPlayer.Data.IsDead - && !(CachedPlayer.LocalPlayer.PlayerControl == Busker.busker && Busker.pseudocideFlag))) { + && !(CachedPlayer.LocalPlayer.PlayerControl == Busker.busker && Busker.pseudocideFlag)) || FreePlayGM.isFreePlayGM) { Transform playerInfoTransform = p.cosmetics.nameText.transform.parent.FindChild("Info"); TMPro.TextMeshPro playerInfo = playerInfoTransform != null ? playerInfoTransform.GetComponent() : null; if (playerInfo == null) { @@ -1227,7 +1227,7 @@ public static void trapperUpdate() if (CachedPlayer.LocalPlayer.PlayerControl == Trapper.trapper && Trap.hasTrappedPlayer() && !Trapper.meetingFlag) { - // トラップにかかっているプレイヤ`を照竃する + // cゃゃ若冴 foreach (var trap in Trap.traps) { if (trap.Value.trap == null || !trap.Value.isActive) return; @@ -1667,7 +1667,7 @@ public static void fortuneTellerUpdate() if (p.Data.IsDead) continue; var fortuneTeller = CachedPlayer.LocalPlayer.PlayerControl; float distance = Vector3.Distance(p.transform.position, fortuneTeller.transform.position); - // 嬾墾麗登協 + // 絎括ゅ bool anythingBetween = PhysicsHelpers.AnythingBetween(p.GetTruePosition(), fortuneTeller.GetTruePosition(), Constants.ShipAndObjectsMask, false); if (!anythingBetween && distance <= FortuneTeller.distance && FortuneTeller.progress[p.PlayerId] < FortuneTeller.duration) { @@ -1720,13 +1720,13 @@ public static void impostorArrowUpdate() } if (CachedPlayer.LocalPlayer.Data.Role.IsImpostor) { - // 念フレ`ムからのU^rgをマイナスする + // 若腟ゃ鴻 FortuneTeller.updateTimer -= Time.fixedDeltaTime; - // 1昼U^したらArrowを厚仟 + // 1腱腟Arrow贋 if (FortuneTeller.updateTimer <= 0.0f) { - // 念指のArrowをすべて篤する + // Arrow鴻贋 foreach (Arrow arrow1 in FortuneTeller.arrows) { if (arrow1?.arrow != null) @@ -1736,7 +1736,7 @@ public static void impostorArrowUpdate() } } - // Arrow匯E + // Arrow筝荀 FortuneTeller.arrows = new List(); if (FortuneTeller.fortuneTeller == null || !FortuneTeller.divinedFlag || !FortuneTeller.isCompletedNumTasks(FortuneTeller.fortuneTeller) || FortuneTeller.fortuneTeller.Data.IsDead) @@ -1749,7 +1749,7 @@ public static void impostorArrowUpdate() arrow.Update(FortuneTeller.fortuneTeller.transform.position); FortuneTeller.arrows.Add(arrow); - // タイマ`にrgをセット + // 帥ゃ若祉 FortuneTeller.updateTimer = 1f; } else @@ -2274,7 +2274,7 @@ public static class AssignRolePatch { public static bool Prefix([HarmonyArgument(0)] PlayerControl player, bool specialRolesAllowed) { - if (player == SchrodingersCat.schrodingersCat && !SchrodingersCat.hasTeam()) + if ((player == SchrodingersCat.schrodingersCat && !SchrodingersCat.hasTeam()) || FreePlayGM.isFreePlayGM) return false; return true; } @@ -2306,7 +2306,7 @@ public static void Postfix(PlayerControl __instance, [HarmonyArgument(0)]PlayerC if (resetToDead) __instance.Data.IsDead = true; // Remove fake tasks when player dies - if (target.hasFakeTasks() || target == Lawyer.lawyer || target == Pursuer.pursuer || target == Thief.thief || (target == Shifter.shifter && Shifter.isNeutral) || Madmate.madmate.Any(x => x.PlayerId == target.PlayerId) || target == CreatedMadmate.createdMadmate || target == JekyllAndHyde.jekyllAndHyde || target == Fox.fox) + if ((target.hasFakeTasks() || target == Lawyer.lawyer || target == Pursuer.pursuer || target == Thief.thief || (target == Shifter.shifter && Shifter.isNeutral) || Madmate.madmate.Any(x => x.PlayerId == target.PlayerId) || target == CreatedMadmate.createdMadmate || target == JekyllAndHyde.jekyllAndHyde || target == Fox.fox) && !FreePlayGM.isFreePlayGM) target.clearAllTasks(); // First kill (set before lover suicide) @@ -2534,7 +2534,7 @@ public static void Postfix(PlayerControl __instance, [HarmonyArgument(0)]PlayerC EvilHacker.acTokenChallenge.Value.admin = false; } - if (JekyllAndHyde.jekyllAndHyde != null && CachedPlayer.LocalPlayer.PlayerControl == JekyllAndHyde.jekyllAndHyde && __instance == JekyllAndHyde.jekyllAndHyde && target != JekyllAndHyde.jekyllAndHyde) + if (JekyllAndHyde.jekyllAndHyde != null && __instance == JekyllAndHyde.jekyllAndHyde && target != JekyllAndHyde.jekyllAndHyde) { JekyllAndHyde.counter++; if (JekyllAndHyde.counter >= JekyllAndHyde.numberToWin) JekyllAndHyde.triggerWin = true; @@ -2548,17 +2548,17 @@ public static void Postfix(PlayerControl __instance, [HarmonyArgument(0)]PlayerC // Trapper peforms kills if (Trapper.trapper != null && CachedPlayer.LocalPlayer.PlayerControl == Trapper.trapper && __instance == Trapper.trapper) { - if (Trap.isTrapped(target) && !Trapper.isTrapKill) // トラップにかかっている鵑鬟ルした栽のボ`ナス + if (Trap.isTrapped(target) && !Trapper.isTrapKill) // c絲乗院翫若 { Trapper.trapper.killTimer = GameOptionsManager.Instance.currentNormalGameOptions.KillCooldown - Trapper.bonusTime; HudManagerStartPatch.trapperSetTrapButton.Timer = Trapper.cooldown - Trapper.bonusTime; } - else if (Trap.isTrapped(target) && Trapper.isTrapKill) // トラップキルした栽のペナルティ + else if (Trap.isTrapped(target) && Trapper.isTrapKill) // 翫 { Trapper.killTimer = GameOptionsManager.Instance.currentNormalGameOptions.KillCooldown; HudManagerStartPatch.trapperSetTrapButton.Timer = Trapper.cooldown; } - else // トラップにかかっていない鵑鰺┳キルした栽はペナルティ`を鞭ける + else // c絲乗院絽吾翫c若 { Trapper.killTimer = GameOptionsManager.Instance.currentNormalGameOptions.KillCooldown + Trapper.penaltyTime; HudManagerStartPatch.trapperSetTrapButton.Timer = Trapper.cooldown + Trapper.penaltyTime; @@ -2965,7 +2965,7 @@ public static class PlayerControlDiePatch { public static void Postfix(PlayerControl __instance, [HarmonyArgument(0)] DeathReason reason) { - if (TaskMaster.isTaskMaster(__instance.PlayerId) && __instance.PlayerId == CachedPlayer.LocalPlayer.PlayerControl.PlayerId && TaskMaster.isTaskComplete) + if (TaskMaster.isTaskMaster(__instance.PlayerId) && __instance.PlayerId == CachedPlayer.LocalPlayer.PlayerControl.PlayerId && TaskMaster.isTaskComplete && !FreePlayGM.isFreePlayGM) __instance.clearAllTasks(); } } @@ -2981,7 +2981,7 @@ public static void Postfix(PlayerControl __instance) // Remove fake tasks when player dies - if (__instance.hasFakeTasks() || __instance == Lawyer.lawyer || __instance == Pursuer.pursuer || __instance == Thief.thief || (__instance == Shifter.shifter && Shifter.isNeutral) || Madmate.madmate.Any(x => x.PlayerId == __instance.PlayerId) || __instance == CreatedMadmate.createdMadmate || __instance == JekyllAndHyde.jekyllAndHyde || __instance == Fox.fox) + if ((__instance.hasFakeTasks() || __instance == Lawyer.lawyer || __instance == Pursuer.pursuer || __instance == Thief.thief || (__instance == Shifter.shifter && Shifter.isNeutral) || Madmate.madmate.Any(x => x.PlayerId == __instance.PlayerId) || __instance == CreatedMadmate.createdMadmate || __instance == JekyllAndHyde.jekyllAndHyde || __instance == Fox.fox) && !FreePlayGM.isFreePlayGM) __instance.clearAllTasks(); // Neko-Kabocha revenge on exile diff --git a/TheOtherRoles/Patches/RoleAssignmentPatch.cs b/TheOtherRoles/Patches/RoleAssignmentPatch.cs index 993addb..af7d49d 100644 --- a/TheOtherRoles/Patches/RoleAssignmentPatch.cs +++ b/TheOtherRoles/Patches/RoleAssignmentPatch.cs @@ -1,4 +1,4 @@ -鏤using HarmonyLib; +using HarmonyLib; using Hazel; using System.Collections.Generic; using System.Linq; @@ -24,7 +24,11 @@ public static void Postfix(ref int __result) { if (TORMapOptions.gameMode == CustomGamemodes.HideNSeek) { int impCount = Mathf.RoundToInt(CustomOptionHolder.hideNSeekHunterCount.getFloat()); __result = impCount; ; // Set Imp Num - } else if (GameOptionsManager.Instance.CurrentGameOptions.GameMode == GameModes.Normal) { // Ignore Vanilla impostor limits in TOR Games. + } + else if (TORMapOptions.gameMode == CustomGamemodes.FreePlay) { + __result = 0; // No imps for freeplay + } + else if (GameOptionsManager.Instance.CurrentGameOptions.GameMode == GameModes.Normal) { // Ignore Vanilla impostor limits in TOR Games. __result = Mathf.Clamp(GameOptionsManager.Instance.CurrentGameOptions.NumImpostors, 1, 6); } } @@ -50,7 +54,7 @@ public static void Postfix() { MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.ResetVaribles, Hazel.SendOption.Reliable, -1); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.resetVariables(); - if (TORMapOptions.gameMode == CustomGamemodes.HideNSeek || GameOptionsManager.Instance.currentGameOptions.GameMode == GameModes.HideNSeek) return; // Don't assign Roles in Hide N Seek + if (TORMapOptions.gameMode == CustomGamemodes.HideNSeek || GameOptionsManager.Instance.currentGameOptions.GameMode == GameModes.HideNSeek || TORMapOptions.gameMode == CustomGamemodes.FreePlay) return; // Don't assign Roles in Hide N Seek assignRoles(); MessageWriter acWriter = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.ResetAchievement, SendOption.Reliable, -1); AmongUsClient.Instance.FinishRpcImmediately(acWriter); diff --git a/TheOtherRoles/Patches/VitalsStatePatch.cs b/TheOtherRoles/Patches/VitalsStatePatch.cs index 08b91cf..5839daa 100644 --- a/TheOtherRoles/Patches/VitalsStatePatch.cs +++ b/TheOtherRoles/Patches/VitalsStatePatch.cs @@ -1,4 +1,4 @@ -鏤using Il2CppSystem; +using Il2CppSystem; using System; using System.Collections.Generic; using System.Linq; @@ -24,7 +24,7 @@ static public FakeVitals VitalsFromActuals get { List param = new(); - var deadBodies = UnityEngine.Object.FindObjectsOfType(); ; + var deadBodies = UnityEngine.Object.FindObjectsOfType(); foreach (var p in GameData.Instance.AllPlayers.GetFastEnumerator()) { VitalsState state = VitalsState.Alive; diff --git a/TheOtherRoles/Resources/OperateButton.png b/TheOtherRoles/Resources/OperateButton.png new file mode 100644 index 0000000..3b6030d Binary files /dev/null and b/TheOtherRoles/Resources/OperateButton.png differ diff --git a/TheOtherRoles/Resources/ReviveButton.png b/TheOtherRoles/Resources/ReviveButton.png new file mode 100644 index 0000000..34b3410 Binary files /dev/null and b/TheOtherRoles/Resources/ReviveButton.png differ diff --git a/TheOtherRoles/Resources/stringData.json b/TheOtherRoles/Resources/stringData.json index 154650d..5b9dbae 100644 --- a/TheOtherRoles/Resources/stringData.json +++ b/TheOtherRoles/Resources/stringData.json @@ -89,6 +89,10 @@ "13": "\u603b\u7d27\u6025\u4f1a\u8bae\u6570\uff08\u4e0d\u5305\u62ec\u5e02\u957f\u4f1a\u8bae\uff09", "14": "\u7e3d\u7dca\u6025\u6703\u8b70\u6578\uff08\u4e0d\u5305\u62ec\u5e02\u9577\u6703\u8b70\uff09" }, + "freePlayGameModeNumDummies": { + "0": "Free Play Number Of Dummies", + "13": "\u81ea\u7531\u6a21\u5f0f\u5047\u4eba\u6570\u91cf" + }, "blockSkippingInEmergencyMeetings": { "0": "Block Skipping In Emergency Meetings", "11": "\u7dca\u6025\u4f1a\u8b70\u306e\u30b9\u30ad\u30c3\u30d7\u3092\u3067\u304d\u306a\u304f\u3059\u308b", @@ -4082,6 +4086,10 @@ "11": "\u304b\u304f\u308c\u3093\u307c", "13": "\u8fdb\u9636\u6349\u8ff7\u85cf" }, + "gamemodeFreePlay": { + "0": "Free Play", + "13": "\u81ea\u7531\u6a21\u5f0f" + }, "torGuesser": { "0": "TOR Guesser", "11": "TOR\u30b2\u30c3\u30b5\u30fc", @@ -4092,6 +4100,26 @@ "11": "TOR\u304b\u304f\u308c\u3093\u307c", "13": "TOR\u6349\u8ff7\u85cf" }, + "torFreePlay": { + "0": "TOR Free Play", + "13": "TOR\u81ea\u7531\u6a21\u5f0f" + }, + "freePlayRoles": { + "0": "Roles", + "13": "\u804c\u4e1a" + }, + "freePlayModifiers": { + "0": "Modifiers", + "13": "\u526f\u804c\u4e1a" + }, + "freePlayModifiersEquipped": { + "0": "Equipped", + "13": "\u5df2\u88c5\u5907" + }, + "freePlayModifiersUnequipped": { + "0": "Unequipped", + "13": "\u672a\u88c5\u5907" + }, "roleInfoErased": { "0": "(erased) ", "11": "(\u6d88\u53bb\u6e08)", @@ -6596,6 +6624,18 @@ "11": "\u30ce\u30a4\u30ba", "13": "\u5e7f\u64ad" }, + "FreePlaySuicideText": { + "0": "Suicide", + "13": "\u81ea\u6740" + }, + "FreePlayReviveText": { + "0": "Revive", + "13": "\u590d\u6d3b" + }, + "FreePlayOperateText": { + "0": "Operate", + "13": "\u64cd\u4f5c" + }, "jesterFullDesc": { "0": "The Jester does not have any tasks.\nThey win the game if they get ejected during a meeting.", "11": "\u30fb\u4eba\u72fc\u3067\u3044\u3046\u300e\u3066\u308b\u3066\u308b\u300f\n\u30fb\u306a\u306b\u3082\u80fd\u529b\u3092\u6301\u305f\u306a\u3044\n\u30fb\u81ea\u8eab\u304c\u540a\u3089\u308c\u305f\u3068\u304d\u306b\u52dd\u5229\u3059\u308b", diff --git a/TheOtherRoles/TheOtherRoles.cs b/TheOtherRoles/TheOtherRoles.cs index 5b62a29..4698c87 100644 --- a/TheOtherRoles/TheOtherRoles.cs +++ b/TheOtherRoles/TheOtherRoles.cs @@ -121,7 +121,7 @@ public static void clearAndReloadRoles() { // Gamemodes HandleGuesser.clearAndReload(); HideNSeek.clearAndReload(); - + FreePlayGM.clearAndReload(); } public static class Jester { @@ -654,14 +654,15 @@ public static class Swapper { public static void niceSwapperOnAchievementActivate() { - if (swapper == null || CachedPlayer.LocalPlayer.PlayerControl != swapper || CachedPlayer.LocalPlayer.PlayerControl.Data.Role.IsImpostor) return; + if (swapper == null || CachedPlayer.LocalPlayer.PlayerControl != swapper) return; acTokenChallenge ??= new("niceSwapper.challenge", (byte.MaxValue, byte.MaxValue, false), (val, _) => val.cleared); } public static void evilSwapperOnAchievementActivate() - { - if (swapper == null || CachedPlayer.LocalPlayer.PlayerControl != swapper || !CachedPlayer.LocalPlayer.PlayerControl.Data.Role.IsImpostor) return; - evilSwapperAcTokenChallenge ??= new("evilSwapper.challenge", (byte.MaxValue, byte.MaxValue, false), (val, _) => val.cleared); + { + if (swapper != null && CachedPlayer.LocalPlayer.PlayerControl == swapper) { + evilSwapperAcTokenChallenge ??= new("evilSwapper.challenge", (byte.MaxValue, byte.MaxValue, false), (val, _) => val.cleared); + } } public static Sprite getCheckSprite() { @@ -2468,13 +2469,13 @@ public static class Yasuna public static void yasunaOnAchievementActivate() { - if (yasuna != null && !CachedPlayer.LocalPlayer.PlayerControl.Data.Role.IsImpostor && CachedPlayer.LocalPlayer.PlayerControl == yasuna) + if (yasuna != null && CachedPlayer.LocalPlayer.PlayerControl == yasuna) yasunaAcTokenChallenge ??= new("niceYasuna.challenge", (byte.MaxValue, false), (val, _) => val.cleared); } public static void evilYasunaOnAcheivementActivate() { - if (yasuna == null || CachedPlayer.LocalPlayer.PlayerControl != yasuna || !CachedPlayer.LocalPlayer.PlayerControl.Data.Role.IsImpostor) return; + if (yasuna == null || CachedPlayer.LocalPlayer.PlayerControl != yasuna) return; evilYasunaAcTokenChallenge ??= new("evilYasuna.another1", (byte.MaxValue, false), (val, _) => val.cleared); }