diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 63ac0804..6942a488 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -110,5 +110,5 @@ jobs: files: | TheOtherUs.dll ./TheOtherUs.zip - draft: true + draft: false prerelease: false \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index f4b37e88..a6e3bd53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,10 @@ -v1.0.8.8-Beta更新日志: +v1.0.9.3更新日志: -* 新增伪装者职业:掷弹兵(技能图标未完成) -* 新增选项: "禁用破坏功能", 可以直接禁用所有破坏(但可以关门) -* 新增选项:"诅咒模式", 将小部分的任务难度加强到地狱级 -* 修复大神官能多次使用技能的问题 -* 修复巴甫洛夫无法破坏的问题 - -注:本次为Beta测试版,30天后版本过期 \ No newline at end of file +* 继续完善职业介绍 +* 重做纵火狂:现在可随时点火,但需要在已涂油目标附近才可点火 +* 纵火狂:更改为击杀型中立,游戏存在纵火狂时不会结束 +* 市长:已死亡的玩家可以看见已揭示的市长名称变色 +* 魅魔:修复选项 “魅魔不招募备胎会自杀” ,如果该选项开启时,备胎数量少于1且招募时间结束则会自杀。 +* 魅魔:在非跟随胜利的场景时,如果场上不存在杀手玩家,则直接夺取船员胜利(包括恋人) +* 巨人:在小黑人时,会恢复正常的体型与速度 +* 还有一部分小更改 \ No newline at end of file diff --git a/README.md b/README.md index 16400e12..5b001aa1 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,9 @@ | 游戏版本 | 模组版本 | 发布日期 | 链接 | | ------------------- | -------- | --------- | ------------------------------------------------------------ | -| 2024.8.13 ~ 2024.10.29 | v2.0.0.0 | 即将推出 | [下载](https://github.com/mxyx-club/TheOtherUs-Edited/releases/download/v1.0.8.7/TheOtherUs.zip) | +| 2024.8.13 ~ 2024.10.29 | v2.0.0.0 | 即将推出 | | +| 2024.3.5 ~ 2024.6.4 | v1.1.0.0 | 即将推出 | | +| 2024.3.5 ~ 2024.6.4 | v1.0.9.0 | 2024.11.5 | [下载](https://github.com/mxyx-club/TheOtherUs-Edited/releases/download/v1.0.9.0TheOtherUs.zip) | | 2024.3.5 ~ 2024.6.4 | v1.0.8.7 | 2024.10.24 | [下载](https://github.com/mxyx-club/TheOtherUs-Edited/releases/download/v1.0.8.7/TheOtherUs.zip) | | 2024.3.5 ~ 2024.6.4 | v1.0.8.6 | 2024.10.18 | [下载](https://github.com/mxyx-club/TheOtherUs-Edited/releases/download/v1.0.8.6/TheOtherUs.zip) | | 2024.3.5 ~ 2024.6.4 | v1.0.7.7 | 2024.9.16 | [下载](https://github.com/mxyx-club/TheOtherUs-Edited/releases/download/v1.0.7.7/TheOtherUs.zip) | @@ -37,6 +39,29 @@ ## 更新日志 +### v1.0.9.0: + +* 完善职业介绍 +* 游戏内添加职业介绍按钮(可按H打开) +* 优化游戏内按钮布局 +* 新增伪装者职业:掷弹兵 +* 新增选项: "禁用破坏功能", 可以直接禁用所有破坏(但可以关门) +* 新增选项:"诅咒模式", 将小部分的任务难度加强 +* 反骨:隐藏职业时,可以分配到已有附加能力的玩家中。 +* 破平者:重做逻辑,现在为全局1.5票,不会与其它职业冲突。 +* 大神官:现在不会出现与破平冲突导致驱除出错的问题了 +* 大神官:更换会议界面背景图片 +* 抹除者:修复抹除刀余波时会导致房主会卡在驱逐画面的问题 +* 专业刺客:优化赌怪猜测,修复猜错后无法继续猜测下一位玩家的问题。 +* 身份窃贼:修复击杀巴甫洛夫阵营时会出现一个人同时是"巴甫洛夫"和"巴甫洛夫的狗"的问题 +* 修正部分预设问题 +* 修复巴甫洛夫无法破坏的问题 +* 修复大神官能多次使用技能的问题 +* 修复一个玩家有可能获得两个附加能力的问题 + +
+ 点我查看更多更新日志 + ### v1.0.8.7: * 修复部分情况下刺客无法连赌的问题 @@ -58,9 +83,6 @@ * 可以使用F11键位控制游戏分辨率大小 * 添加 "最小/最大 独立阵营杀手数" 调整选项,如果这两项都是随机,则使用原先的概率分配。 -
- 点我查看更多更新日志 - ### v1.0.7.7: - #### Bug修复与其它优化: diff --git a/Strings.xlsx b/Strings.xlsx index 75b6a148..3ed2ab4e 100644 Binary files a/Strings.xlsx and b/Strings.xlsx differ diff --git a/TheOtherRoles/Buttons/Buttons.cs b/TheOtherRoles/Buttons/Buttons.cs index d4463ad6..abff2c08 100644 --- a/TheOtherRoles/Buttons/Buttons.cs +++ b/TheOtherRoles/Buttons/Buttons.cs @@ -4,6 +4,7 @@ using Hazel; using TheOtherRoles.CustomGameModes; using TheOtherRoles.Objects; +using TheOtherRoles.Options; using TheOtherRoles.Patches; using TheOtherRoles.Utilities; using TMPro; @@ -66,6 +67,7 @@ internal static class HudManagerStartPatch public static CustomButton securityGuardButton; public static CustomButton securityGuardCamButton; public static CustomButton arsonistButton; + public static CustomButton arsonistKillButton; public static CustomButton vultureEatButton; public static CustomButton mediumButton; public static CustomButton pursuerButton; @@ -274,7 +276,6 @@ public static void setCustomButtonCooldowns() lightsOutButton.Timer = lightsOutButton.MaxTimer; zoomOutButton.MaxTimer = 0f; //changeChatButton.MaxTimer = 0f; - } public static void showTargetNameOnButton(PlayerControl target, CustomButton button, string defaultText) @@ -1151,7 +1152,7 @@ public static void createButtonsPostfix(HudManager __instance) () => { if (Morphling.sampledTarget == null) showTargetNameOnButton(Morphling.currentTarget, morphlingButton, getString("SampleText")); - return (Morphling.currentTarget || Morphling.sampledTarget) && !isActiveCamoComms() && + return (Morphling.currentTarget || Morphling.sampledTarget) && !isActiveCamoComms && CachedPlayer.LocalPlayer.PlayerControl.CanMove && !MushroomSabotageActive(); }, () => @@ -1200,7 +1201,7 @@ public static void createButtonsPostfix(HudManager __instance) Camouflager.camouflager == CachedPlayer.LocalPlayer.PlayerControl && !CachedPlayer.LocalPlayer.Data.IsDead; }, - () => { return !isActiveCamoComms() && CachedPlayer.LocalPlayer.PlayerControl.CanMove; }, + () => { return !isActiveCamoComms && CachedPlayer.LocalPlayer.PlayerControl.CanMove; }, () => { camouflagerButton.Timer = camouflagerButton.MaxTimer; @@ -3019,22 +3020,10 @@ public static void createButtonsPostfix(HudManager __instance) arsonistButton = new CustomButton( () => { - var dousedEveryoneAlive = Arsonist.dousedEveryoneAlive(); - if (dousedEveryoneAlive) - { - var winWriter = AmongUsClient.Instance.StartRpcImmediately( - CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.ArsonistWin, SendOption.Reliable); - AmongUsClient.Instance.FinishRpcImmediately(winWriter); - RPCProcedure.arsonistWin(); - arsonistButton.HasEffect = false; - } - else if (Arsonist.currentTarget != null) - { - if (checkAndDoVetKill(Arsonist.currentTarget)) return; - Arsonist.douseTarget = Arsonist.currentTarget; - arsonistButton.HasEffect = true; - SoundEffectsManager.play("arsonistDouse"); - } + if (checkAndDoVetKill(Arsonist.currentTarget)) return; + Arsonist.douseTarget = Arsonist.currentTarget; + arsonistButton.HasEffect = true; + SoundEffectsManager.play("arsonistDouse"); }, () => { @@ -3046,7 +3035,6 @@ public static void createButtonsPostfix(HudManager __instance) var dousedEveryoneAlive = Arsonist.dousedEveryoneAlive(); if (!dousedEveryoneAlive) showTargetNameOnButton(Arsonist.currentTarget, arsonistButton, getString("DouseText")); - if (dousedEveryoneAlive) arsonistButton.actionButton.graphic.sprite = Arsonist.igniteSprite; if (arsonistButton.isEffectActive && Arsonist.douseTarget != Arsonist.currentTarget) { @@ -3055,8 +3043,7 @@ public static void createButtonsPostfix(HudManager __instance) arsonistButton.isEffectActive = false; } - return CachedPlayer.LocalPlayer.PlayerControl.CanMove && - (dousedEveryoneAlive || Arsonist.currentTarget != null); + return CachedPlayer.LocalPlayer.PlayerControl.CanMove && Arsonist.currentTarget != null; }, () => { @@ -3065,7 +3052,7 @@ public static void createButtonsPostfix(HudManager __instance) Arsonist.douseTarget = null; }, Arsonist.douseSprite, - ButtonPositions.lowerRowRight, + ButtonPositions.upperRowRight, __instance, abilityInput.keyCode, true, @@ -3074,8 +3061,8 @@ public static void createButtonsPostfix(HudManager __instance) { if (Arsonist.douseTarget != null) Arsonist.dousedPlayers.Add(Arsonist.douseTarget); - arsonistButton.Timer = Arsonist.dousedEveryoneAlive() ? 0 : arsonistButton.MaxTimer; - + arsonistButton.Timer = arsonistButton.MaxTimer; + arsonistKillButton.Timer = arsonistButton.MaxTimer; foreach (var p in Arsonist.dousedPlayers) if (ModOption.playerIcons.ContainsKey(p.PlayerId)) ModOption.playerIcons[p.PlayerId].setSemiTransparent(false); @@ -3092,6 +3079,45 @@ public static void createButtonsPostfix(HudManager __instance) } ); + // Arsonist button + arsonistKillButton = new CustomButton( + () => + { + foreach (PlayerControl p in Arsonist.dousedPlayers.Where(p => p.IsAlive())) + { + checkMurderAttemptAndKill(Arsonist.arsonist, p, false, false, false); + GameHistory.overrideDeathReasonAndKiller(p, DeadPlayer.CustomDeathReason.Arson, Arsonist.arsonist); + } + Message("点火"); + arsonistKillButton.Timer = arsonistKillButton.MaxTimer; + arsonistButton.Timer = arsonistButton.MaxTimer; + }, + () => + { + return Arsonist.arsonist != null && Arsonist.arsonist == CachedPlayer.LocalPlayer.PlayerControl && + CachedPlayer.LocalPlayer.IsAlive && Arsonist.dousedPlayers != null && Arsonist.dousedPlayers.Count > 0; + }, + () => + { + showTargetNameOnButton(Arsonist.currentTarget2, arsonistKillButton, getString("IgniteText")); + return CachedPlayer.LocalPlayer.PlayerControl.CanMove && Arsonist.currentTarget2 != null && Arsonist.dousedPlayers.Any(p => p == Arsonist.currentTarget2); + }, + () => + { + /*var alivePlayersList = PlayerControl.AllPlayerControls.ToArray().Where(pc => !pc.Data.IsDead); + var count = alivePlayersList.Count(pc => isNeutral(pc) && pc.isKiller()); + + if (count < 1) arsonistKillButton.Timer = arsonistKillButton.MaxTimer = 0f; + else */ + arsonistKillButton.Timer = arsonistKillButton.MaxTimer; + }, + Arsonist.igniteSprite, + ButtonPositions.upperRowCenter, + __instance, + modKillInput.keyCode, + buttonText: getString("IgniteText") + ); + // Vulture Eat vultureEatButton = new CustomButton( () => diff --git a/TheOtherRoles/Helper/Helpers.cs b/TheOtherRoles/Helper/Helpers.cs index d8fdede8..53d59fe3 100644 --- a/TheOtherRoles/Helper/Helpers.cs +++ b/TheOtherRoles/Helper/Helpers.cs @@ -41,7 +41,7 @@ public enum SabatageTypes None } -public enum RoleTeam +public enum RoleType { Crewmate, Impostor, @@ -288,7 +288,7 @@ public static bool isShiftNeutral(PlayerControl player) public static bool isNeutral(PlayerControl player) { var roleInfo = RoleInfo.getRoleInfoForPlayer(player, false).FirstOrDefault(); - return roleInfo != null && roleInfo.roleTeam == RoleTeam.Neutral; + return roleInfo != null && roleInfo.roleTeam == RoleType.Neutral; } public static bool isKillerNeutral(PlayerControl player) @@ -389,7 +389,7 @@ public static bool roleCanSabotage(this PlayerControl player) return roleCouldUse; } - public static SabatageTypes getActiveSabo() + public static SabatageTypes GetActiveSabo() { foreach (var task in CachedPlayer.LocalPlayer.PlayerControl.myTasks.GetFastEnumerator()) if (task.TaskType == TaskTypes.FixLights) @@ -405,27 +405,21 @@ public static SabatageTypes getActiveSabo() return SabatageTypes.None; } - public static bool isLightsActive() => getActiveSabo() == SabatageTypes.Lights; + public static bool isLightsActive => GetActiveSabo() == SabatageTypes.Lights; - public static bool isCommsActive() => getActiveSabo() == SabatageTypes.Comms; + public static bool isCommsActive => GetActiveSabo() == SabatageTypes.Comms; - public static bool isCamoComms() => isCommsActive() && ModOption.camoComms; + public static bool isReactor => GetActiveSabo() is SabatageTypes.Reactor or SabatageTypes.O2; - public static bool isActiveCamoComms() => isCamoComms() && Camouflager.camoComms; + public static bool isCamoComms => isCommsActive && ModOption.camoComms; - public static bool wasActiveCamoComms() => !isCamoComms() && Camouflager.camoComms; + public static bool isActiveCamoComms => isCamoComms && Camouflager.camoComms; - public static bool sabotageActive() - { - var sabSystem = ShipStatus.Instance.Systems[SystemTypes.Sabotage].CastFast(); - return sabSystem.AnyActive; - } + public static bool wasActiveCamoComms => !isCamoComms && Camouflager.camoComms; - public static float sabotageTimer() - { - var sabSystem = ShipStatus.Instance.Systems[SystemTypes.Sabotage].CastFast(); - return sabSystem.Timer; - } + public static bool sabotageActive => ShipStatus.Instance.Systems[SystemTypes.Sabotage].CastFast().AnyActive; + + public static float sabotageTimer => ShipStatus.Instance.Systems[SystemTypes.Sabotage].CastFast().Timer; public static bool canUseSabotage() { @@ -479,27 +473,6 @@ public static int getAvailableId() } } - public static void turnToCrewmate(PlayerControl player) - { - var writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, - (byte)CustomRPC.TurnToCrewmate, SendOption.Reliable); - writer.Write(player.PlayerId); - AmongUsClient.Instance.FinishRpcImmediately(writer); - RPCProcedure.turnToCrewmate(player.PlayerId); - foreach (var player2 in PlayerControl.AllPlayerControls) - if (player2.Data.Role.IsImpostor && CachedPlayer.LocalPlayer.PlayerControl.Data.Role.IsImpostor) - player.cosmetics.nameText.color = Palette.White; - } - - public static void turnToCrewmate(List players, PlayerControl player) - { - foreach (var p in players) - { - if (p == player) continue; - turnToCrewmate(p); - } - } - public static void turnToImpostorRPC(PlayerControl player) { var writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, @@ -529,9 +502,9 @@ public static void showTargetNameOnButton(PlayerControl target, CustomButton but // Should the button show the target name option string text; // set text to default if camo is on - if (Camouflager.camouflageTimer >= 0.1f || isCamoComms()) text = defaultText; + if (Camouflager.camouflageTimer >= 0.1f || isCamoComms) text = defaultText; // set to default if lights are out - else if (isLightsActive()) text = defaultText; + else if (isLightsActive) text = defaultText; // set to default if trickster ability is active else if (Trickster.trickster != null && Trickster.lightsOutTimer > 0f) text = defaultText; // set to morphed player @@ -680,7 +653,7 @@ public static List allRoleInfos() var allRoleInfo = new List(); foreach (var role in RoleInfo.allRoleInfos) { - if (role.roleTeam == RoleTeam.Modifier) continue; + if (role.roleTeam == RoleType.Modifier) continue; allRoleInfo.Add(role); } return allRoleInfo; @@ -841,15 +814,15 @@ public static async Task checkBeta() } } - public static Color getTeamColor(RoleTeam team) + public static Color getTeamColor(RoleType team) { return team switch { - RoleTeam.Crewmate => Color.white, - RoleTeam.Impostor => Palette.ImpostorRed, - RoleTeam.Neutral => Color.gray, - RoleTeam.Modifier => Color.yellow, - RoleTeam.Special => Palette.Purple, + RoleType.Crewmate => Color.white, + RoleType.Impostor => Palette.ImpostorRed, + RoleType.Neutral => Color.gray, + RoleType.Modifier => Color.yellow, + RoleType.Special => Palette.Purple, _ => Palette.White }; } @@ -1029,7 +1002,7 @@ public static KeyValuePair MaxPair(this Dictionary self, o public static bool hidePlayerName(PlayerControl source, PlayerControl target) { var localPlayer = PlayerControl.LocalPlayer; - if (Camouflager.camouflageTimer > 0f || MushroomSabotageActive() || isCamoComms()) + if (Camouflager.camouflageTimer > 0f || MushroomSabotageActive() || isCamoComms) return true; // No names are visible if (SurveillanceMinigamePatch.nightVisionIsActive) return true; if (Ninja.isInvisble && Ninja.ninja == target) return true; diff --git a/TheOtherRoles/Helper/LogHelper.cs b/TheOtherRoles/Helper/LogHelper.cs index ea2c4b4a..6471748f 100644 --- a/TheOtherRoles/Helper/LogHelper.cs +++ b/TheOtherRoles/Helper/LogHelper.cs @@ -15,56 +15,43 @@ internal static void SetLogSource(ManualLogSource Source) logSource = Source; } - /// - /// 一般信息 - /// - /// - public static void Info(string Message) - { - logSource.LogInfo(Message); - } - - /// - /// 报错 - /// - /// - public static void Error(string Message) - { - logSource.LogError(Message); - } + public static void Info(object text, string Tag = "") => SendLog(text.ToString(), Tag, LogLevel.Info); + public static void Message(object text, string Tag = "") => SendLog(text.ToString(), Tag, LogLevel.Message); + public static void Warn(object text, string Tag = "") => SendLog(text.ToString(), Tag, LogLevel.Warning); + public static void Error(object text, string Tag = "") => SendLog(text.ToString(), Tag, LogLevel.Error); + public static void Debug(object text, string Tag = "") => SendLog(text.ToString(), Tag, LogLevel.Debug); + public static void Fatal(object text, string Tag = "") => SendLog(text.ToString(), Tag, LogLevel.Fatal); - /// - /// 测试 - /// - /// - public static void Debug(string Message) + public static void SendLog(string text, string tag = "", LogLevel logLevel = LogLevel.Info) { - logSource.LogDebug(Message); - } - - public static void Fatal(string Message) - { - logSource.LogFatal(Message); - } + string time = DateTime.Now.ToString("HH:mm:ss"); + if (!string.IsNullOrWhiteSpace(tag)) text = $"[{time}][{tag}] {text}"; + else text = $"[{time}] {text}"; - /// - /// 警告 - /// - /// - public static void Warn(string Message) - { - logSource.LogWarning(Message); - } - - - public static void Message(string Message) - { - logSource.LogMessage(Message); - } - - public static void Exception(Exception exception) - { - Error(exception.ToString()); + switch (logLevel) + { + case LogLevel.Message: + logSource.LogMessage(text); + break; + case LogLevel.Error: + logSource.LogError(text); + break; + case LogLevel.Warning: + logSource.LogWarning(text); + break; + case LogLevel.Fatal: + logSource.LogFatal(text); + break; + case LogLevel.Info: + logSource.LogInfo(text); + break; + case LogLevel.Debug: + logSource.LogDebug(text); + break; + default: + logSource.LogInfo(text); + break; + } } public static void FastLog(LogLevel errorLevel, object @object) diff --git a/TheOtherRoles/Main.cs b/TheOtherRoles/Main.cs index 60ec36e6..2014885f 100644 --- a/TheOtherRoles/Main.cs +++ b/TheOtherRoles/Main.cs @@ -22,7 +22,7 @@ public class TheOtherRolesPlugin : BasePlugin public const string ModName = MyPluginInfo.PLUGIN_NAME; public const string VersionString = MyPluginInfo.PLUGIN_VERSION; #if RELEASE - public static uint betaDays; // amount of days for the build to be usable (0 for infinite!) + public static uint betaDays; #else public static uint betaDays = 30; #endif @@ -101,12 +101,6 @@ public override void Load() CrowdedPlayer.Start(); Harmony.PatchAll(); - ModOption.reloadPluginOptions(); - CosmeticsManager.Load(); - CustomOptionHolder.Load(); - AssetLoader.LoadAudioAssets(); - if (ToggleCursor.Value) enableCursor(true); - if (BepInExUpdater.UpdateRequired) { AddComponent(); @@ -114,10 +108,16 @@ public override void Load() } AddComponent(); + ModOption.reloadPluginOptions(); + CosmeticsManager.Load(); + CustomOptionHolder.Load(); + AssetLoader.LoadAudioAssets(); + ModInputManager.Load(); + if (ToggleCursor.Value) enableCursor(true); + SubmergedCompatibility.Initialize(); MainMenuPatch.addSceneChangeCallbacks(); AddToKillDistanceSetting.addKillDistance(); - ModInputManager.Load(); Info($"\n---------------\n Loading TheOtherUs completed!\n TheOtherUs-Edited v{VersionString}\n---------------"); } } diff --git a/TheOtherRoles/Modules/ModUpdater.cs b/TheOtherRoles/Modules/ModUpdater.cs index 95f88281..b9e39029 100644 --- a/TheOtherRoles/Modules/ModUpdater.cs +++ b/TheOtherRoles/Modules/ModUpdater.cs @@ -97,7 +97,7 @@ private IEnumerator CoDownloadRelease(GithubRelease release) var asset = release.Assets.Find(FilterPluginAsset); var www = new UnityWebRequest(); www.SetMethod(UnityWebRequest.UnityWebRequestMethod.Get); - www.SetUrl(asset.DownloadUrl); + www.SetUrl(asset.DownloadUrl.GithubUrl()); www.downloadHandler = new DownloadHandlerBuffer(); var operation = www.SendWebRequest(); diff --git a/TheOtherRoles/Modules/TaskQueue.cs b/TheOtherRoles/Modules/TaskQueue.cs index cf858b5c..b47a7ab0 100644 --- a/TheOtherRoles/Modules/TaskQueue.cs +++ b/TheOtherRoles/Modules/TaskQueue.cs @@ -36,7 +36,7 @@ public TaskQueue StartTask(Action action, string Id, Action OnCompleted = null) } catch (Exception e) { - Exception(e); + Error(e); Error($"加载失败 TaskQueue Id:{Id}"); } }); diff --git a/TheOtherRoles/Objects/Footprint.cs b/TheOtherRoles/Objects/Footprint.cs index bb87bacd..e972bc7f 100644 --- a/TheOtherRoles/Objects/Footprint.cs +++ b/TheOtherRoles/Objects/Footprint.cs @@ -26,7 +26,7 @@ public static FootprintHolder Instance private static Sprite FootprintSprite => _footprintSprite ??= UnityHelper.loadSpriteFromResources("TheOtherRoles.Resources.Footprint.png", 600f); private static bool AnonymousFootprints => Detective.anonymousFootprints == 2; - private static bool SabotageActive => (isActiveCamoComms() || MushroomSabotageActive()) && Detective.anonymousFootprints == 1; + private static bool SabotageActive => (isActiveCamoComms || MushroomSabotageActive()) && Detective.anonymousFootprints == 1; private static float FootprintDuration => Detective.footprintDuration; private class Footprint diff --git a/TheOtherRoles/Options/CustomOptionHolder.cs b/TheOtherRoles/Options/CustomOptionHolder.cs index e4e44a20..aec797bc 100644 --- a/TheOtherRoles/Options/CustomOptionHolder.cs +++ b/TheOtherRoles/Options/CustomOptionHolder.cs @@ -579,7 +579,8 @@ public class CustomOptionHolder public static CustomOption ShowVentsOnMap; public static CustomOption ShowVentsOnMeetingMap; - public static CustomOption enableMapOptions; + + //public static CustomOption enableMapOptions; public static CustomOption randomGameStartPosition; public static CustomOption randomGameStartToVents; public static CustomOption allowModGuess; @@ -774,11 +775,11 @@ public static void Load() blockGameEnd = Create(29, Types.General, cs(Color.yellow, "blockGameEnd"), true); deadImpsBlockSabotage = Create(32, Types.General, cs(Palette.ImpostorRed, "deadImpsBlockSabotage"), false); randomLigherPlayer = Create(34, Types.General, "randomLigherPlayer", true); - disableSabotage = Create(35, Types.General, cs(Palette.ImpostorRed, "disableSabotage"), false, enableMapOptions); + disableSabotage = Create(35, Types.General, cs(Palette.ImpostorRed, "disableSabotage"), false, null); allowModGuess = Create(31, Types.General, "allowModGuess", false); //ghostSpeed = Create(33, Types.General, "ghostSpeed", 1f, 0.75f, 5f, 0.125f); - WireTaskIsRandomOption = Create(221, Types.General, "WireTaskIsRandomOption", false, enableMapOptions, true); + WireTaskIsRandomOption = Create(221, Types.General, "WireTaskIsRandomOption", false, null, true); WireTaskNumOption = Create(222, Types.General, "WireTaskNumOption", 3f, 1f, 8f, 1f, WireTaskIsRandomOption); transparentTasks = Create(40, Types.General, "transparentTasks", false); disableMedbayWalk = Create(41, Types.General, "disableMedbayWalk", false); @@ -788,7 +789,7 @@ public static void Load() enableCursedTasks = Create(45, Types.General, cs(Palette.Purple, "enableCursedTasks"), false); //Map options - enableMapOptions = Create(200, Types.General, "enableMapOptions", false, null, true); + //enableMapOptions = Create(200, Types.General, "enableMapOptions", false, null, true); IsReactorDurationSetting = Create(201, Types.General, "IsReactorDurationSetting", false, null, true); SkeldReactorTimeLimit = Create(202, Types.General, "SkeldReactorTimeLimit", 30f, 0f, 30f, 2.5f, IsReactorDurationSetting); @@ -799,41 +800,41 @@ public static void Load() AirshipReactorTimeLimit = Create(207, Types.General, "AirshipReactorTimeLimit", 75f, 0f, 90f, 2.5f, IsReactorDurationSetting); FungleReactorTimeLimit = Create(208, Types.General, "FungleReactorTimeLimit", 45f, 0f, 60f, 2.5f, IsReactorDurationSetting); - randomGameStartPosition = Create(50, Types.General, "randomGameStartPosition", false, enableMapOptions, true); + randomGameStartPosition = Create(50, Types.General, "randomGameStartPosition", false, null, true); randomGameStartToVents = Create(51, Types.General, "randomGameStartToVents", true, randomGameStartPosition); - ShowVentsOnMap = Create(211, Types.General, "ShowVentsOnMapText", false, enableMapOptions, true); + ShowVentsOnMap = Create(211, Types.General, "ShowVentsOnMapText", false, null, true); ShowVentsOnMeetingMap = Create(212, Types.General, "ShowVentsOnMeetingMap", true, ShowVentsOnMap); - enableMiraModify = Create(70, Types.General, cs(Color.yellow, "Mira"), false, enableMapOptions, true); + enableMiraModify = Create(70, Types.General, cs(Color.yellow, "Mira"), false, null, true); miraVitals = Create(71, Types.General, "miraVitals", false, enableMiraModify); - enableBetterPolus = Create(80, Types.General, cs(Color.yellow, "Polus"), false, enableMapOptions); + enableBetterPolus = Create(80, Types.General, cs(Color.yellow, "Polus"), false, null); movePolusVents = Create(81, Types.General, "movePolusVents", false, enableBetterPolus); addPolusVents = Create(82, Types.General, "addPolusVents", false, enableBetterPolus); movePolusVitals = Create(83, Types.General, "movePolusVitals", false, enableBetterPolus); swapNavWifi = Create(84, Types.General, "swapNavWifi", false, enableBetterPolus); moveColdTemp = Create(85, Types.General, "moveColdTemp", false, enableBetterPolus); - enableAirShipModify = Create(90, Types.General, cs(Color.yellow, "AirShip"), false, enableMapOptions); + enableAirShipModify = Create(90, Types.General, cs(Color.yellow, "AirShip"), false, null); airshipOptimize = Create(91, Types.General, "airshipOptimize", false, enableAirShipModify); addAirShipVents = Create(92, Types.General, "addAirShipVents", false, enableAirShipModify); airshipLadder = Create(93, Types.General, "airshipLadder", false, enableAirShipModify); - enableFungleModify = Create(100, Types.General, cs(Color.yellow, "Fungle"), false, enableMapOptions); + enableFungleModify = Create(100, Types.General, cs(Color.yellow, "Fungle"), false, null); fungleElectrical = Create(101, Types.General, "fungleElectrical", false, enableFungleModify); - enableCamoComms = Create(120, Types.General, cs(Palette.ImpostorRed, "enableCamoComms"), false, enableMapOptions, true); + enableCamoComms = Create(120, Types.General, cs(Palette.ImpostorRed, "enableCamoComms"), false, null, true); //fungleDisableCamoComms = Create(211, Types.General, "fungleDisableCamoComms", true, enableCamoComms); - restrictDevices = Create(121, Types.General, "restrictDevices", ["optionOff", "restrictDevices2", "restrictDevices3"], enableMapOptions); + restrictDevices = Create(121, Types.General, "restrictDevices", ["optionOff", "restrictDevices2", "restrictDevices3"], null); //restrictAdmin = Create(122, Types.General, "restrictAdmin", 30f, 0f, 600f, 5f, restrictDevices); restrictCameras = Create(123, Types.General, "restrictCameras", 30f, 0f, 600f, 5f, restrictDevices); restrictVents = Create(124, Types.General, "restrictVents", 30f, 0f, 600f, 5f, restrictDevices); - disableCamsRound1 = Create(125, Types.General, "disableCamsRound1", false, enableMapOptions); - camsNightVision = Create(126, Types.General, "camsNightVision", false, enableMapOptions); + disableCamsRound1 = Create(125, Types.General, "disableCamsRound1", false, null); + camsNightVision = Create(126, Types.General, "camsNightVision", false, null); camsNoNightVisionIfImpVision = Create(127, Types.General, "camsNoNightVisionIfImpVision", false, camsNightVision); - dynamicMap = Create(130, Types.General, "dynamicMap", false, enableMapOptions, true); + dynamicMap = Create(130, Types.General, "dynamicMap", false, null, true); dynamicMapEnableSkeld = Create(131, Types.General, "Skeld", rates, dynamicMap); dynamicMapEnableMira = Create(132, Types.General, "Mira", rates, dynamicMap); dynamicMapEnablePolus = Create(133, Types.General, "Polus", rates, dynamicMap); @@ -965,7 +966,7 @@ public static void Load() gamblerSuccessRate = Create(10333, Types.Impostor, "gamblerSuccessRate", rates, gamblerSpawnRate); grenadierSpawnRate = Create(10340, Types.Impostor, cs(Grenadier.color, "Grenadier"), rates, null, true); - grenadierCooldown = Create(10341, Types.Impostor, "grenadierCooldown", 25f, 0f, 45f, 0.5f, grenadierSpawnRate); + grenadierCooldown = Create(10341, Types.Impostor, "grenadierCooldown", 25f, 0f, 45f, 2.5f, grenadierSpawnRate); grenadierDuration = Create(10342, Types.Impostor, "grenadierDuration", 9f, 4f, 10f, 0.5f, grenadierSpawnRate); grenadierFlashRadius = Create(10343, Types.Impostor, "grenadierFlashRadius", 1.25f, 0.25f, 5f, 0.125f, grenadierSpawnRate); grenadierTeamIndicators = Create(10344, Types.Impostor, "grenadierTeamIndicators", @@ -992,10 +993,6 @@ public static void Load() jesterCanVent = Create(20102, Types.Neutral, "jesterCanVent", true, jesterSpawnRate); jesterHasImpostorVision = Create(20103, Types.Neutral, "jesterHasImpostorVision", true, jesterSpawnRate); - arsonistSpawnRate = Create(20120, Types.Neutral, cs(Arsonist.color, "Arsonist"), rates, null, true); - arsonistCooldown = Create(20121, Types.Neutral, "arsonistCooldown", 12.5f, 5f, 60f, 2.5f, arsonistSpawnRate); - arsonistDuration = Create(20122, Types.Neutral, "arsonistDuration", 0.5f, 0f, 10f, 0.25f, arsonistSpawnRate); - jackalSpawnRate = Create(20130, Types.Neutral, cs(Jackal.color, "Jackal"), rates, null, true); jackalChanceSwoop = Create(20142, Types.Neutral, cs(Swooper.color, "jackalChanceSwoop"), rates, jackalSpawnRate); jackalKillCooldown = Create(20131, Types.Neutral, "jackalKillCooldown", 25f, 10f, 60f, 2.5f, jackalSpawnRate); @@ -1026,6 +1023,10 @@ public static void Load() pavlovsownerRampageKillCooldown = Create(20261, Types.Neutral, "pavlovsownerRampageKillCooldown", 15f, 5f, 60f, 2.5f, pavlovsownerRampage); pavlovsownerRampageDeathTime = Create(20262, Types.Neutral, "pavlovsownerRampageDeathTime", 60f, 30f, 180f, 2.5f, pavlovsownerRampageKillCooldown); + arsonistSpawnRate = Create(20120, Types.Neutral, cs(Arsonist.color, "Arsonist"), rates, null, true); + arsonistCooldown = Create(20121, Types.Neutral, "arsonistCooldown", 12.5f, 5f, 60f, 2.5f, arsonistSpawnRate); + arsonistDuration = Create(20122, Types.Neutral, "arsonistDuration", 0.5f, 0f, 10f, 0.25f, arsonistSpawnRate); + swooperSpawnRate = Create(20150, Types.Neutral, cs(Swooper.color, "Swooper"), rates, null, true); swooperKillCooldown = Create(20151, Types.Neutral, "swooperKillCooldown", 25f, 10f, 60f, 2.5f, swooperSpawnRate); swooperCooldown = Create(20152, Types.Neutral, "swooperCooldown", 20f, 10f, 60f, 2.5f, swooperSpawnRate); @@ -1313,8 +1314,6 @@ public static void Load() modifierLastImpostor = Create(40110, Types.Modifier, cs(Palette.ImpostorRed, "LastImpostor"), false, null, true); modifierLastImpostorDeduce = Create(40111, Types.Modifier, "modifierLastImpostorDeduce", 5f, 2.5f, 15f, 2.5f, modifierLastImpostor); - modifierSpecoality = Create(40350, Types.Modifier, cs(Palette.ImpostorRed, "Specoality"), rates, null, true); - modifierBloody = Create(40120, Types.Modifier, cs(Color.yellow, "Bloody"), rates, null, true); modifierBloodyQuantity = Create(40121, Types.Modifier, cs(Color.yellow, "modifierBloodyQuantity"), ratesCount, modifierBloody); modifierBloodyDuration = Create(40122, Types.Modifier, "modifierBloodyDuration", 10f, 3f, 60f, 0.5f, modifierBloody); diff --git a/TheOtherRoles/Patches/CursedTasks/MedScan.cs b/TheOtherRoles/Patches/CursedTasks/MedScan.cs index 4c8df7c8..369523a6 100644 --- a/TheOtherRoles/Patches/CursedTasks/MedScan.cs +++ b/TheOtherRoles/Patches/CursedTasks/MedScan.cs @@ -1,5 +1,4 @@ -using System; - +/*using System; namespace TheOtherRoles.Patches.CursedTasks; @@ -28,7 +27,7 @@ private static void BeginPostfix(MedScanMinigame __instance) __instance.completeString = "Player Identity: " + PlayerControl.LocalPlayer.Data.ColorName + " Player " + PlayerData.id + "\nIdentification Number: " + PlayerData.id + "\nPlayer Name: " + PlayerControl.LocalPlayer.cosmetics.nameText.text + "\nHeight: 3 feet, 6 inches" + "\nWeight: 92 pounds" + "\nColor: " + $"{PlayerControl.LocalPlayer.Data.ColorName} " + "\nBlood Type: " + MedScanMinigame.BloodTypes[PlayerData.bloodType]; - __instance.ScanDuration = 90f; + __instance.ScanDuration = 20f; } } @@ -43,4 +42,4 @@ private static void StartPrefix() PlayerData = default; } } -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/TheOtherRoles/Patches/EndGamePatch.cs b/TheOtherRoles/Patches/EndGamePatch.cs index 45b48da2..c466f43a 100644 --- a/TheOtherRoles/Patches/EndGamePatch.cs +++ b/TheOtherRoles/Patches/EndGamePatch.cs @@ -769,11 +769,11 @@ public static bool Prefix(ShipStatus __instance) if (CheckAndEndGameForMiniLose(__instance)) return false; if (CheckAndEndGameForJesterWin(__instance)) return false; if (CheckAndEndGameForDoomsayerWin(__instance)) return false; - if (CheckAndEndGameForArsonistWin(__instance)) return false; if (CheckAndEndGameForVultureWin(__instance)) return false; if (CheckAndEndGameForSabotageWin(__instance)) return false; if (CheckAndEndGameForExecutionerWin(__instance)) return false; if (CheckAndEndGameForAkujoWin(__instance, statistics)) return false; + if (CheckAndEndGameForArsonistWin(__instance, statistics)) return false; if (CheckAndEndGameForWerewolfWin(__instance, statistics)) return false; if (CheckAndEndGameForLoverWin(__instance, statistics)) return false; if (CheckAndEndGameForJackalWin(__instance, statistics)) return false; @@ -815,17 +815,6 @@ private static bool CheckAndEndGameForDoomsayerWin(ShipStatus __instance) return false; } - private static bool CheckAndEndGameForArsonistWin(ShipStatus __instance) - { - if (Arsonist.triggerArsonistWin) - { - //__instance.enabled = false; - GameManager.Instance.RpcEndGame((GameOverReason)CustomGameOverReason.ArsonistWin, false); - return true; - } - return false; - } - private static bool CheckAndEndGameForVultureWin(ShipStatus __instance) { if (Vulture.triggerVultureWin) @@ -911,9 +900,37 @@ private static bool CheckAndEndGameForLoverWin(ShipStatus __instance, PlayerStat return false; } + private static bool CheckAndEndGameForArsonistWin(ShipStatus __instance, PlayerStatistics statistics) + { + if (statistics.TeamArsonistAlive >= statistics.TotalAlive - statistics.TeamArsonistAlive && + statistics.TeamImpostorsAlive == 0 && + statistics.TeamJuggernautAlive == 0 && + statistics.TeamPavlovsAlive == 0 && + statistics.TeamJackalAlive == 0 && + statistics.TeamWerewolfAlive == 0 && + statistics.TeamAkujoAlive == 0 && + statistics.TeamSwooperAlive == 0 && + !(statistics.TeamArsonisHasAliveLover && statistics.TeamLoversAlive == 2) + && !killingCrewAlive()) + { + //__instance.enabled = false; + GameManager.Instance.RpcEndGame((GameOverReason)CustomGameOverReason.ArsonistWin, false); + return true; + } + return false; + } + private static bool CheckAndEndGameForAkujoWin(ShipStatus __instance, PlayerStatistics statistics) { - if (statistics.TeamAkujoAlive == 2 && statistics.TotalAlive <= 3) + if (statistics.TeamAkujoAlive == 2 && + statistics.TeamImpostorsAlive == 0 && + statistics.TeamArsonistAlive == 0 && + statistics.TeamJuggernautAlive == 0 && + statistics.TeamPavlovsAlive == 0 && + statistics.TeamWerewolfAlive == 0 && + statistics.TeamJackalAlive == 0 && + statistics.TeamSwooperAlive == 0 && + !(statistics.TeamLoversAlive != 0 && Lovers.existingWithKiller())) { GameManager.Instance.RpcEndGame((GameOverReason)CustomGameOverReason.AkujoWin, false); return true; @@ -927,6 +944,7 @@ private static bool CheckAndEndGameForJackalWin(ShipStatus __instance, PlayerSta statistics.TeamImpostorsAlive == 0 && statistics.TeamJuggernautAlive == 0 && statistics.TeamPavlovsAlive == 0 && + statistics.TeamArsonistAlive == 0 && statistics.TeamWerewolfAlive == 0 && statistics.TeamAkujoAlive == 0 && statistics.TeamSwooperAlive == 0 && @@ -947,6 +965,7 @@ private static bool CheckAndEndGameForPavlovsWin(ShipStatus __instance, PlayerSt statistics.TeamJackalAlive == 0 && statistics.TeamJuggernautAlive == 0 && statistics.TeamWerewolfAlive == 0 && + statistics.TeamArsonistAlive == 0 && statistics.TeamAkujoAlive == 0 && statistics.TeamSwooperAlive == 0 && !(statistics.TeamPavlovsHasAliveLover && statistics.TeamLoversAlive == 2) && !killingCrewAlive()) @@ -966,6 +985,7 @@ private static bool CheckAndEndGameForSwooperWin(ShipStatus __instance, PlayerSt statistics.TeamJackalAlive == 0 && statistics.TeamPavlovsAlive == 0 && statistics.TeamWerewolfAlive == 0 && + statistics.TeamArsonistAlive == 0 && !(statistics.TeamSwooperHasAliveLover && statistics.TeamLoversAlive == 2) && !killingCrewAlive()) @@ -984,6 +1004,7 @@ private static bool CheckAndEndGameForWerewolfWin(ShipStatus __instance, PlayerS statistics.TeamJuggernautAlive == 0 && statistics.TeamJackalAlive == 0 && statistics.TeamPavlovsAlive == 0 && + statistics.TeamArsonistAlive == 0 && statistics.TeamSwooperAlive == 0 && !(statistics.TeamWerewolfHasAliveLover && statistics.TeamLoversAlive == 2) && @@ -1006,6 +1027,7 @@ private static bool CheckAndEndGameForJuggernautWin(ShipStatus __instance, Playe statistics.TeamJackalAlive == 0 && statistics.TeamPavlovsAlive == 0 && statistics.TeamWerewolfAlive == 0 && + statistics.TeamArsonistAlive == 0 && statistics.TeamSwooperAlive == 0 && !(statistics.TeamJuggernautHasAliveLover && statistics.TeamLoversAlive == 2) && @@ -1031,6 +1053,7 @@ private static bool CheckAndEndGameForImpostorWin(ShipStatus __instance, PlayerS statistics.TeamPavlovsAlive == 0 && statistics.TeamWerewolfAlive == 0 && statistics.TeamSwooperAlive == 0 && + statistics.TeamArsonistAlive == 0 && statistics.TeamAkujoAlive == 0 && statistics.TeamJuggernautAlive == 0 && !(statistics.TeamImpostorHasAliveLover && statistics.TeamLoversAlive == 2) && !killingCrewAlive()) @@ -1073,21 +1096,16 @@ private static bool CheckAndEndGameForCrewmateWin(ShipStatus __instance, PlayerS if (statistics.TeamImpostorsAlive == 0 && statistics.TeamJackalAlive == 0 && statistics.TeamPavlovsAlive == 0 && + statistics.TeamArsonistAlive == 0 && statistics.TeamWerewolfAlive == 0 && statistics.TeamSwooperAlive == 0 && statistics.TeamJuggernautAlive == 0) { - if (Akujo.honmeiOptimizeWin) - { - GameManager.Instance.RpcEndGame(GameOverReason.HumansByVote, false); - return true; - } - else if (statistics.TeamAkujoAlive <= 1) + if (Akujo.honmeiOptimizeWin || statistics.TeamAkujoAlive <= 1) { GameManager.Instance.RpcEndGame(GameOverReason.HumansByVote, false); return true; } - return true; } return false; } @@ -1116,9 +1134,11 @@ public PlayerStatistics(ShipStatus __instance) public bool TeamJackalHasAliveLover { get; set; } public bool TeamPavlovsHasAliveLover { get; set; } public int TeamWerewolfAlive { get; set; } + public int TeamArsonistAlive { get; set; } public int TeamAkujoAlive { get; set; } public bool TeamSwooperHasAliveLover { get; set; } public bool TeamWerewolfHasAliveLover { get; set; } + public bool TeamArsonisHasAliveLover { get; set; } public int TeamJuggernautAlive { get; set; } public bool TeamJuggernautHasAliveLover { get; set; } @@ -1136,12 +1156,14 @@ private void GetPlayerCounts() var numLoversAlive = 0; var numTotalAlive = 0; var numSwooperAlive = 0; + var numArsonistAlive = 0; var numWerewolfAlive = 0; var numJuggernautAlive = 0; var numAkujoAlive = 0; var impLover = false; var jackalLover = false; var pavlovsLover = false; + var arsonistLover = false; var swooperLover = false; var werewolfLover = false; var juggernautLover = false; @@ -1173,6 +1195,12 @@ private void GetPlayerCounts() if (lover) jackalLover = true; } + if (Arsonist.arsonist != null && Arsonist.arsonist.PlayerId == playerInfo.PlayerId) + { + numArsonistAlive++; + if (lover) arsonistLover = true; + } + if (Pavlovsdogs.pavlovsowner != null && Pavlovsdogs.pavlovsowner.PlayerId == playerInfo.PlayerId) { numPavlovsAlive++; @@ -1221,9 +1249,11 @@ private void GetPlayerCounts() TeamPavlovsHasAliveLover = pavlovsLover; TeamWerewolfHasAliveLover = werewolfLover; TeamWerewolfAlive = numWerewolfAlive; + TeamArsonistAlive = numArsonistAlive; TeamSwooperHasAliveLover = swooperLover; TeamSwooperAlive = numSwooperAlive; TeamJuggernautAlive = numJuggernautAlive; + TeamArsonisHasAliveLover = arsonistLover; TeamJuggernautHasAliveLover = juggernautLover; } } \ No newline at end of file diff --git a/TheOtherRoles/Patches/ExileControllerPatch.cs b/TheOtherRoles/Patches/ExileControllerPatch.cs index 1e36ffa1..5b810bdb 100644 --- a/TheOtherRoles/Patches/ExileControllerPatch.cs +++ b/TheOtherRoles/Patches/ExileControllerPatch.cs @@ -110,7 +110,8 @@ void createlate(int index) if (Eraser.eraser != null && AmongUsClient.Instance.AmHost && Eraser.futureErased != null) { // We need to send the RPC from the host here, to make sure that the order of shifting and erasing is correct (for that reason the futureShifted and futureErased are being synced) - foreach (var target in Eraser.futureErased) + var rasePlayerList = new List(Eraser.futureErased); + foreach (var target in rasePlayerList) { var writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.ErasePlayerRoles, SendOption.Reliable); @@ -295,7 +296,6 @@ private static void WrapUpPostfix(GameData.PlayerInfo exiled) else if (exiled != null && Jester.jester != null && Jester.jester.PlayerId == exiled.PlayerId) Jester.triggerJesterWin = true; - // Reset custom button timers where necessary CustomButton.MeetingEndedUpdate(); @@ -501,11 +501,6 @@ private static void Postfix(ref string __result, [HarmonyArgument(0)] StringName if (Jester.jester != null && player.PlayerId == Jester.jester.PlayerId) __result = ""; if (Prosecutor.ProsecuteThisMeeting) __result += " (被起诉)"; - else if (Tiebreaker.isTiebreak) - { - __result += " (破平)"; - Tiebreaker.isTiebreak = false; - } } } catch diff --git a/TheOtherRoles/Patches/GameStartManagerPatch.cs b/TheOtherRoles/Patches/GameStartManagerPatch.cs index 2e3fe86e..8438c315 100644 --- a/TheOtherRoles/Patches/GameStartManagerPatch.cs +++ b/TheOtherRoles/Patches/GameStartManagerPatch.cs @@ -151,7 +151,7 @@ public static void Postfix(GameStartManager __instance) copiedStartButton.SetActive(true); var startButtonText = copiedStartButton.GetComponentInChildren(); startButtonText.text = getString("stopGameStartText"); - startButtonText.fontSize *= 0.8f; + startButtonText.fontSize *= 0.62f; startButtonText.fontSizeMax = startButtonText.fontSize; startButtonText.gameObject.transform.localPosition = Vector3.zero; PassiveButton startButtonPassiveButton = copiedStartButton.GetComponent(); diff --git a/TheOtherRoles/Patches/HauntMenuMinigamePatch.cs b/TheOtherRoles/Patches/HauntMenuMinigamePatch.cs index e9bfc826..7d882b8e 100644 --- a/TheOtherRoles/Patches/HauntMenuMinigamePatch.cs +++ b/TheOtherRoles/Patches/HauntMenuMinigamePatch.cs @@ -45,7 +45,7 @@ public static void MatchesFilterPostfix(HauntMenuMinigame __instance, PlayerCont if (__instance.filterMode == HauntMenuMinigame.HauntFilters.Impostor) { var info = RoleInfo.getRoleInfoForPlayer(pc, false); - __result = (pc.Data.Role.IsImpostor || info.Any(x => x.roleTeam == RoleTeam.Neutral)) && !pc.Data.IsDead; + __result = (pc.Data.Role.IsImpostor || info.Any(x => x.roleTeam == RoleType.Neutral)) && !pc.Data.IsDead; } } diff --git a/TheOtherRoles/Patches/IntroPatch.cs b/TheOtherRoles/Patches/IntroPatch.cs index 97e94572..a4338880 100644 --- a/TheOtherRoles/Patches/IntroPatch.cs +++ b/TheOtherRoles/Patches/IntroPatch.cs @@ -296,9 +296,9 @@ public static void setupIntroTeamIcons(IntroCutscene __instance, ref List yourTeam) { var infos = RoleInfo.getRoleInfoForPlayer(CachedPlayer.LocalPlayer.PlayerControl); - var roleInfo = infos.FirstOrDefault(info => info.roleTeam != RoleTeam.Modifier); + var roleInfo = infos.FirstOrDefault(info => info.roleTeam != RoleType.Modifier); if (roleInfo == null) return; - if (roleInfo.roleTeam == RoleTeam.Neutral) + if (roleInfo.roleTeam == RoleType.Neutral) { var neutralColor = new Color32(76, 84, 78, 255); __instance.BackgroundBar.material.color = roleInfo.color; @@ -352,8 +352,8 @@ public static void SetRoleTexts(IntroCutscene __instance) { // Don't override the intro of the vanilla roles var infos = RoleInfo.getRoleInfoForPlayer(CachedPlayer.LocalPlayer.PlayerControl); - var roleInfo = infos.FirstOrDefault(info => info.roleTeam != RoleTeam.Modifier); - var modifierInfo = infos.FirstOrDefault(info => info.roleTeam == RoleTeam.Modifier); + var roleInfo = infos.FirstOrDefault(info => info.roleTeam != RoleType.Modifier); + var modifierInfo = infos.FirstOrDefault(info => info.roleTeam == RoleType.Modifier); __instance.RoleBlurbText.text = ""; if (roleInfo != null) diff --git a/TheOtherRoles/Patches/LobbyRoleList.cs b/TheOtherRoles/Patches/LobbyRoleList.cs index 3fc08c8f..7d1d8d39 100644 --- a/TheOtherRoles/Patches/LobbyRoleList.cs +++ b/TheOtherRoles/Patches/LobbyRoleList.cs @@ -60,24 +60,24 @@ public static void RoleSummaryOnClick() for (int i = 0; i < Teams.Count; i++) { string team = ""; - RoleTeam teamid = RoleTeam.Crewmate; + RoleType teamid = RoleType.Crewmate; switch (Teams[i]) { case "Impostors": team = cs(Palette.ImpostorRed, getString("ImpostorRolesText")); - teamid = RoleTeam.Impostor; + teamid = RoleType.Impostor; break; case "Neutrals": team = cs(new Color32(76, 84, 78, 255), getString("NeutralRolesText")); - teamid = RoleTeam.Neutral; + teamid = RoleType.Neutral; break; case "Crewmates": team = cs(Palette.CrewmateBlue, getString("CrewmateRolesText")); - teamid = RoleTeam.Crewmate; + teamid = RoleType.Crewmate; break; case "Modifiers": team = cs(Color.yellow, getString("ModifierRolesText")); - teamid = RoleTeam.Modifier; + teamid = RoleType.Modifier; break; } @@ -118,7 +118,7 @@ public static void RoleSummaryOnClick() } } - public static void roleInfosOnclick(string team, RoleTeam teamId) + public static void roleInfosOnclick(string team, RoleType teamId) { SpriteRenderer container = new GameObject("RoleListMenuContainer").AddComponent(); container.sprite = new ResourceSprite("LobbyRoleInfo.RoleListScreen.png", 110f); @@ -142,10 +142,10 @@ public static void roleInfosOnclick(string team, RoleTeam teamId) bool gameStarted = AmongUsClient.Instance.GameState == InnerNet.InnerNetClient.GameStates.Started; foreach (RoleInfo roleInfo in RoleInfo.allRoleInfos) { - if (roleInfo.roleTeam == RoleTeam.Modifier && teamId != RoleTeam.Modifier) continue; - else if (roleInfo.roleTeam == RoleTeam.Neutral && teamId != RoleTeam.Neutral) continue; - else if (roleInfo.roleTeam == RoleTeam.Impostor && teamId != RoleTeam.Impostor) continue; - else if (roleInfo.roleTeam == RoleTeam.Crewmate && teamId != RoleTeam.Crewmate) continue; + if (roleInfo.roleTeam == RoleType.Modifier && teamId != RoleType.Modifier) continue; + else if (roleInfo.roleTeam == RoleType.Neutral && teamId != RoleType.Neutral) continue; + else if (roleInfo.roleTeam == RoleType.Impostor && teamId != RoleType.Impostor) continue; + else if (roleInfo.roleTeam == RoleType.Crewmate && teamId != RoleType.Crewmate) continue; Transform buttonTransform = Object.Instantiate(buttonTemplate, container.transform); buttonTransform.name = cs(roleInfo.color, roleInfo.Name) + " Button"; diff --git a/TheOtherRoles/Patches/MainMenuPatch.cs b/TheOtherRoles/Patches/MainMenuPatch.cs index 6eb9c839..e11df1d6 100644 --- a/TheOtherRoles/Patches/MainMenuPatch.cs +++ b/TheOtherRoles/Patches/MainMenuPatch.cs @@ -39,7 +39,6 @@ private static void Prefix(MainMenuManager __instance) passiveButtonGitHub.OnClick = new ButtonClickedEvent(); passiveButtonGitHub.OnClick.AddListener((Action)(() => Application.OpenURL("https://github.com/mxyx-club/TheOtherUs/"))); -#if !SUNDAY if (IsCN()) { var buttonDiscord = Object.Instantiate(template, null); @@ -67,7 +66,6 @@ private static void Prefix(MainMenuManager __instance) buttonSpriteDiscord.color = textDiscord.color = discordColor; }); } -#endif // TOR credits button if (template == null) return; @@ -124,8 +122,8 @@ private static void Prefix(MainMenuManager __instance) Announcement creditsAnnouncement = new() { - Id = "Credits", - Language = 0, + Id = "ModCredits", + Language = 13, Number = 500, Title = "The Other Us Edited\nCredits & Resources", ShortTitle = "TOU Credits", diff --git a/TheOtherRoles/Patches/MeetingHudPatch.cs b/TheOtherRoles/Patches/MeetingHudPatch.cs index a80a2441..43078972 100644 --- a/TheOtherRoles/Patches/MeetingHudPatch.cs +++ b/TheOtherRoles/Patches/MeetingHudPatch.cs @@ -370,16 +370,15 @@ public static bool CheckVoted(PlayerVoteArea playerVoteArea) return true; } - private static Dictionary CalculateVotes(MeetingHud __instance) + private static Dictionary CalculateVotes(MeetingHud __instance) { - var dictionary = new Dictionary(); + var dictionary = new Dictionary(); foreach (var playerVoteArea in __instance.playerStates) { if (playerVoteArea.VotedFor is 252 or 255 or 254) continue; var player = playerById(playerVoteArea.TargetPlayerId); - if (player == null || player.Data == null || player.Data.IsDead || - player.Data.Disconnected) continue; + if (player == null || player.Data == null || player.Data.IsDead || player.Data.Disconnected) continue; if (InfoSleuth.infoSleuth != null && playerVoteArea.TargetPlayerId == InfoSleuth.infoSleuth.PlayerId) { @@ -390,13 +389,16 @@ private static Dictionary CalculateVotes(MeetingHud __instance) RPCProcedure.infoSleuthTarget(playerVoteArea.VotedFor); } - var additionalVotes = 1; + float additionalVotes = 1; if (Prosecutor.prosecutor != null && Prosecutor.prosecutor.PlayerId == playerVoteArea.TargetPlayerId) additionalVotes = Prosecutor.ProsecuteThisMeeting ? 15 : 1; if (Mayor.mayor != null && Mayor.mayor.PlayerId == playerVoteArea.TargetPlayerId) additionalVotes = Mayor.Revealed ? Mayor.Vote : 1; + if (Tiebreaker.tiebreaker != null && Tiebreaker.tiebreaker.PlayerId == playerVoteArea.TargetPlayerId) + additionalVotes = 1.5f; + if (Prosecutor.prosecutor != null && Prosecutor.ProsecuteThisMeeting && Prosecutor.prosecutor.PlayerId != playerVoteArea.TargetPlayerId) additionalVotes = 0; @@ -443,28 +445,6 @@ private static bool Prefix(MeetingHud __instance) //var max = self.MaxPair(out var tie); var exiled = CachedPlayer.LocalPlayer.Data; bool tie = false; - bool tiebreakerHandled = false; - // TieBreaker - var potentialExiled = new List(); - var skipIsTie = false; - if (self.Count > 0 && !Prosecutor.ProsecuteThisMeeting) // 阻止破平者在检察官会议中生效 - { - Tiebreaker.isTiebreak = false; - var maxVoteValue = self.Values.Max(); - PlayerVoteArea tb = null; - if (Tiebreaker.tiebreaker != null) - tb = __instance.playerStates.ToArray().FirstOrDefault(x => x.TargetPlayerId == Tiebreaker.tiebreaker.PlayerId); - - var isTiebreakerSkip = tb == null || tb.VotedFor == 253 || (tb != null && tb.AmDead); - - foreach (var pair in self.Where(pair => pair.Value == maxVoteValue && !isTiebreakerSkip)) - { - if (pair.Key != 253) - potentialExiled.Add(GameData.Instance.AllPlayers.ToArray().FirstOrDefault(x => x.PlayerId == pair.Key)); - else - skipIsTie = true; - } - } VoterState[] states; List statesList = new(); @@ -487,8 +467,8 @@ private static bool Prefix(MeetingHud __instance) VoterId = playerVoteArea.TargetPlayerId, VotedForId = playerVoteArea.VotedFor }); - - if (Tiebreaker.tiebreaker == null || playerVoteArea.TargetPlayerId != Tiebreaker.tiebreaker.PlayerId) + /* + if (Tiebreaker.tiebreaker == null || Balancer.currentAbilityUser != null || playerVoteArea.TargetPlayerId != Tiebreaker.tiebreaker.PlayerId) continue; var tiebreakerVote = playerVoteArea.VotedFor; @@ -506,28 +486,25 @@ private static bool Prefix(MeetingHud __instance) var writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.SetTiebreak, SendOption.Reliable); AmongUsClient.Instance.FinishRpcImmediately(writer); - RPCProcedure.setTiebreak(); + RPCProcedure.setTiebreak();*/ } states = statesList.ToArray(); - if (!tiebreakerHandled) + var VotingData = CalculateVotes(__instance); + byte exileId = byte.MaxValue; + float max1 = 0; + foreach (var data in VotingData) { - var VotingData = CalculateVotes(__instance); - byte exileId = byte.MaxValue; - int max1 = 0; - foreach (var data in VotingData) + if (data.Value > max1) { - if (data.Value > max1) - { - exileId = data.Key; - max1 = data.Value; - tie = false; - } - else if (data.Value == max1) - { - exileId = byte.MaxValue; - tie = true; - } + exileId = data.Key; + max1 = data.Value; + tie = false; + } + else if (data.Value == max1) + { + exileId = byte.MaxValue; + tie = true; } exiled = GameData.Instance.AllPlayers.FirstOrDefault(info => !tie && info.PlayerId == exileId); @@ -983,7 +960,6 @@ public static void Postfix(MeetingHud __instance) writer.Write(msg); AmongUsClient.Instance.FinishRpcImmediately(writer); - var writer1 = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.InfoSleuthNoTarget, SendOption.Reliable); AmongUsClient.Instance.FinishRpcImmediately(writer1); diff --git a/TheOtherRoles/Patches/PlayerControlPatch.cs b/TheOtherRoles/Patches/PlayerControlPatch.cs index f2ecbae5..aff47a2d 100644 --- a/TheOtherRoles/Patches/PlayerControlPatch.cs +++ b/TheOtherRoles/Patches/PlayerControlPatch.cs @@ -81,7 +81,7 @@ private static void setBasePlayerOutlines() var isMorphedMorphling = target == Morphling.morphling && Morphling.morphTarget != null && Morphling.morphTimer > 0f; var hasVisibleShield = false; var color = Medic.shieldedColor; - if (!isCamoComms() && Camouflager.camouflageTimer <= 0f && !MushroomSabotageActive() && + if (!isCamoComms && Camouflager.camouflageTimer <= 0f && !MushroomSabotageActive() && Medic.shielded != null && ((target == Medic.shielded && !isMorphedMorphling) || (isMorphedMorphling && Morphling.morphTarget == Medic.shielded))) { @@ -106,7 +106,7 @@ private static void setBasePlayerOutlines() color = new Color32(205, 150, 100, byte.MaxValue); } - if (!isCamoComms() && Camouflager.camouflageTimer <= 0f && !MushroomSabotageActive() && + if (!isCamoComms && Camouflager.camouflageTimer <= 0f && !MushroomSabotageActive() && ModOption.firstKillPlayer != null && ModOption.shieldFirstKill && ((target == ModOption.firstKillPlayer && !isMorphedMorphling) || (isMorphedMorphling && Morphling.morphTarget == ModOption.firstKillPlayer))) @@ -696,7 +696,7 @@ public static void MiniSizeUpdate(PlayerControl p) collider.offset = Mini.defaultColliderOffset * Vector2.down; // Set adapted player size to Mini and Morphling - if (Mini.mini == null || isCamoComms() || Camouflager.camouflageTimer > 0f || + if (Mini.mini == null || isCamoComms || Camouflager.camouflageTimer > 0f || MushroomSabotageActive() || (Mini.mini == Morphling.morphling && Morphling.morphTimer > 0)) return; var growingProgress = Mini.growingProgress(); @@ -736,24 +736,17 @@ public static void updatePlayerInfo() { var local = CachedPlayer.LocalPlayer.PlayerControl; - var colorBlindTextMeetingInitialLocalPos = new Vector3(0.3384f, -0.16666f, -0.01f); - var colorBlindTextMeetingInitialLocalScale = new Vector3(0.9f, 1f, 1f); + //var colorBlindTextMeetingInitialLocalPos = new Vector3(0.3384f, -0.16666f, -0.01f); + //var colorBlindTextMeetingInitialLocalScale = new Vector3(0.9f, 1f, 1f); foreach (PlayerControl p in CachedPlayer.AllPlayers) { // Colorblind Text in Meeting var playerVoteArea = MeetingHud.Instance?.playerStates?.FirstOrDefault(x => x.TargetPlayerId == p.PlayerId); if (playerVoteArea != null && playerVoteArea.ColorBlindName.gameObject.active) { - playerVoteArea.ColorBlindName.transform.localPosition = - colorBlindTextMeetingInitialLocalPos + new Vector3(0f, 0.4f, 0f); - playerVoteArea.ColorBlindName.transform.localScale = colorBlindTextMeetingInitialLocalScale * 0.8f; + playerVoteArea.ColorBlindName.transform.localPosition = new Vector3(-0.93f, -0.2f, -0.1f); + //playerVoteArea.ColorBlindName.transform.localScale = colorBlindTextMeetingInitialLocalScale * 0.8f; } - /* - // Colorblind Text During the round - if (p.cosmetics.colorBlindText != null && p.cosmetics.showColorBlindText && - p.cosmetics.colorBlindText.gameObject.active) - p.cosmetics.colorBlindText.transform.localPosition = new Vector3(0, -1f, 0f); - */ // This moves both the name AND the colorblindtext behind objects (if the player is behind the object), like the rock on polus p.cosmetics.nameText.transform.parent.SetLocalZ(-0.0001f); @@ -918,6 +911,9 @@ public static void arsonistSetTarget() Arsonist.currentTarget = setTarget(untargetablePlayers: untargetables); if (Arsonist.currentTarget != null) setPlayerOutline(Arsonist.currentTarget, Arsonist.color); + + Arsonist.currentTarget2 = setTarget(false, true); + if (Arsonist.currentTarget2 != null) setPlayerOutline(Arsonist.currentTarget2, Arsonist.color); } private static void snitchUpdate() @@ -1412,7 +1408,7 @@ private static void morphlingAndCamouflagerUpdate() var mushRoomSaboIsActive = MushroomSabotageActive(); if (!mushroomSaboWasActive) mushroomSaboWasActive = mushRoomSaboIsActive; - if (isCamoComms() && !isActiveCamoComms()) + if (isCamoComms && !isActiveCamoComms) { var writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.CamouflagerCamouflage, SendOption.Reliable); @@ -1427,8 +1423,8 @@ private static void morphlingAndCamouflagerUpdate() Morphling.morphTimer = Mathf.Max(0f, Morphling.morphTimer - Time.fixedDeltaTime); if (mushRoomSaboIsActive) return; - if (isCamoComms()) return; - if (wasActiveCamoComms() && Camouflager.camouflageTimer <= 0f) camoReset(); + if (isCamoComms) return; + if (wasActiveCamoComms && Camouflager.camouflageTimer <= 0f) camoReset(); // Camouflage reset and set Morphling look if necessary if (oldCamouflageTimer > 0f && Camouflager.camouflageTimer <= 0f) @@ -1760,7 +1756,7 @@ public static void akujoUpdate() } else if (Akujo.timeLeft <= 0) { - if (Akujo.honmei == null || (Akujo.keeps == null && Akujo.forceKeeps)) + if (Akujo.honmei == null || (Akujo.keeps?.Count < 1 && Akujo.forceKeeps)) { MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.AkujoSuicide, SendOption.Reliable, -1); writer.Write(Akujo.akujo.PlayerId); @@ -2006,7 +2002,7 @@ internal class PlayerPhysicsWalkPlayerToPatch public static void Prefix(PlayerPhysics __instance) { - var correctOffset = !isCamoComms() && Camouflager.camouflageTimer <= 0f && + var correctOffset = !isCamoComms && Camouflager.camouflageTimer <= 0f && !MushroomSabotageActive() && (__instance.myPlayer == Mini.mini || (Morphling.morphling != null && __instance.myPlayer == Morphling.morphling && @@ -2342,7 +2338,7 @@ public static void Postfix(PlayerControl __instance, [HarmonyArgument(0)] Player { color = Color.white; if (target.Data.Role.IsImpostor) color = Color.red; - else if (RoleInfo.getRoleInfoForPlayer(target, false).FirstOrDefault().roleTeam == RoleTeam.Neutral) color = Color.blue; + else if (RoleInfo.getRoleInfoForPlayer(target, false).FirstOrDefault().roleTeam == RoleType.Neutral) color = Color.blue; } showFlash(color, 1.75f); diff --git a/TheOtherRoles/Patches/RoleAssignmentPatch.cs b/TheOtherRoles/Patches/RoleAssignmentPatch.cs index 6409fd00..665e4d08 100644 --- a/TheOtherRoles/Patches/RoleAssignmentPatch.cs +++ b/TheOtherRoles/Patches/RoleAssignmentPatch.cs @@ -160,7 +160,7 @@ public static RoleAssignmentData getRoleAssignmentData() neutralSettings.Add((byte)RoleId.Jester, CustomOptionHolder.jesterSpawnRate.getSelection()); neutralSettings.Add((byte)RoleId.Lawyer, CustomOptionHolder.lawyerSpawnRate.getSelection()); neutralSettings.Add((byte)RoleId.Executioner, CustomOptionHolder.executionerSpawnRate.getSelection()); - neutralSettings.Add((byte)RoleId.Arsonist, CustomOptionHolder.arsonistSpawnRate.getSelection()); + killerNeutralSettings.Add((byte)RoleId.Arsonist, CustomOptionHolder.arsonistSpawnRate.getSelection()); neutralSettings.Add((byte)RoleId.Vulture, CustomOptionHolder.vultureSpawnRate.getSelection()); neutralSettings.Add((byte)RoleId.Doomsayer, CustomOptionHolder.doomsayerSpawnRate.getSelection()); neutralSettings.Add((byte)RoleId.Akujo, CustomOptionHolder.akujoSpawnRate.getSelection()); @@ -255,30 +255,30 @@ private static void assignEnsuredRoles(RoleAssignmentData data) || (data.maxKillerNeutralRoles > 0 && ensuredKillerNeutralRoles.Count > 0) ))) { - var rolesToAssign = new Dictionary>(); + var rolesToAssign = new Dictionary>(); if (data.crewmates.Count > 0 && data.maxCrewmateRoles > 0 && ensuredCrewmateRoles.Count > 0) - rolesToAssign.Add(RoleType.Crewmate, ensuredCrewmateRoles); + rolesToAssign.Add(AssignType.Crewmate, ensuredCrewmateRoles); if (data.crewmates.Count > 0 && data.maxNeutralRoles > 0 && ensuredNeutralRoles.Count > 0) - rolesToAssign.Add(RoleType.Neutral, ensuredNeutralRoles); + rolesToAssign.Add(AssignType.Neutral, ensuredNeutralRoles); if (data.crewmates.Count > 0 && data.maxKillerNeutralRoles > 0 && ensuredKillerNeutralRoles.Count > 0) - rolesToAssign.Add(RoleType.KillerNeutral, ensuredKillerNeutralRoles); + rolesToAssign.Add(AssignType.KillerNeutral, ensuredKillerNeutralRoles); if (data.impostors.Count > 0 && data.maxImpostorRoles > 0 && ensuredImpostorRoles.Count > 0) - rolesToAssign.Add(RoleType.Impostor, ensuredImpostorRoles); + rolesToAssign.Add(AssignType.Impostor, ensuredImpostorRoles); // Randomly select a pool of roles to assign a role from next (Crewmate role, Neutral role or Impostor role) // then select one of the roles from the selected pool to a player // and remove the role (and any potentially blocked role pairings) from the pool(s) var roleType = rolesToAssign.Keys.ElementAt(rnd.Next(0, rolesToAssign.Keys.Count)); - var players = roleType is RoleType.Crewmate or RoleType.Neutral or RoleType.KillerNeutral ? data.crewmates : data.impostors; + var players = roleType is AssignType.Crewmate or AssignType.Neutral or AssignType.KillerNeutral ? data.crewmates : data.impostors; var index = rnd.Next(0, rolesToAssign[roleType].Count); var roleId = rolesToAssign[roleType][index]; setRoleToRandomPlayer(roleId, players); rolesToAssign[roleType].RemoveAt(index); - if (RoleClass.blockedRolePairings.ContainsKey(roleId)) + if (blockedRolePairings.ContainsKey(roleId)) { - foreach (var blockedRoleId in RoleClass.blockedRolePairings[roleId]) + foreach (var blockedRoleId in blockedRolePairings[roleId]) { // Set chance for the blocked roles to 0 for chances less than 100% if (data.impSettings.ContainsKey(blockedRoleId)) data.impSettings[blockedRoleId] = 0; @@ -294,17 +294,17 @@ private static void assignEnsuredRoles(RoleAssignmentData data) // Adjust the role limit switch (roleType) { - case RoleType.Crewmate: + case AssignType.Crewmate: data.maxCrewmateRoles--; crewValues -= 10; break; - case RoleType.Neutral: + case AssignType.Neutral: data.maxNeutralRoles--; break; - case RoleType.KillerNeutral: + case AssignType.KillerNeutral: data.maxKillerNeutralRoles--; break; - case RoleType.Impostor: + case AssignType.Impostor: data.maxImpostorRoles--; impValues -= 10; break; @@ -394,28 +394,28 @@ static List GetEnsuredRoles(Dictionary settings) => || (data.maxNeutralRoles > 0 && neutralTickets.Count > 0) || (data.maxKillerNeutralRoles > 0 && killerNeutralTickets.Count > 0)))) { - var rolesToAssign = new Dictionary>(); + var rolesToAssign = new Dictionary>(); if (data.crewmates.Count > 0 && data.maxCrewmateRoles > 0 && crewmateTickets.Count > 0) - rolesToAssign.Add(RoleType.Crewmate, crewmateTickets); + rolesToAssign.Add(AssignType.Crewmate, crewmateTickets); if (data.crewmates.Count > 0 && data.maxNeutralRoles > 0 && neutralTickets.Count > 0) - rolesToAssign.Add(RoleType.Neutral, neutralTickets); + rolesToAssign.Add(AssignType.Neutral, neutralTickets); if (data.crewmates.Count > 0 && data.maxKillerNeutralRoles > 0 && killerNeutralTickets.Count > 0) - rolesToAssign.Add(RoleType.KillerNeutral, killerNeutralTickets); + rolesToAssign.Add(AssignType.KillerNeutral, killerNeutralTickets); if (data.impostors.Count > 0 && data.maxImpostorRoles > 0 && impostorTickets.Count > 0) - rolesToAssign.Add(RoleType.Impostor, impostorTickets); + rolesToAssign.Add(AssignType.Impostor, impostorTickets); // Randomly select a pool of role tickets to assign a role from next (Crewmate role, Neutral role or Impostor role) // then select one of the roles from the selected pool to a player // and remove all tickets of this role (and any potentially blocked role pairings) from the pool(s) var roleType = rolesToAssign.Keys.ElementAt(rnd.Next(0, rolesToAssign.Keys.Count)); - var players = roleType is RoleType.Crewmate or RoleType.Neutral or RoleType.KillerNeutral ? data.crewmates : data.impostors; + var players = roleType is AssignType.Crewmate or AssignType.Neutral or AssignType.KillerNeutral ? data.crewmates : data.impostors; var index = rnd.Next(0, rolesToAssign[roleType].Count); var roleId = rolesToAssign[roleType][index]; setRoleToRandomPlayer(roleId, players); rolesToAssign[roleType].RemoveAll(x => x == roleId); - if (RoleClass.blockedRolePairings.ContainsKey(roleId)) - foreach (var blockedRoleId in RoleClass.blockedRolePairings[roleId]) + if (blockedRolePairings.ContainsKey(roleId)) + foreach (var blockedRoleId in blockedRolePairings[roleId]) { // Remove tickets of blocked roles from all pools crewmateTickets.RemoveAll(x => x == blockedRoleId); @@ -427,16 +427,16 @@ static List GetEnsuredRoles(Dictionary settings) => // Adjust the role limit switch (roleType) { - case RoleType.Crewmate: + case AssignType.Crewmate: data.maxCrewmateRoles--; break; - case RoleType.Neutral: + case AssignType.Neutral: data.maxNeutralRoles--; break; - case RoleType.KillerNeutral: + case AssignType.KillerNeutral: data.maxKillerNeutralRoles--; break; - case RoleType.Impostor: + case AssignType.Impostor: data.maxImpostorRoles--; break; } @@ -746,10 +746,6 @@ private static void assignModifiersToPlayers(List modifiers, List(playerList); crewPlayer.RemoveAll(x => x.Data.Role.IsImpostor || isNeutral(x)); - var noImpPlayer = new List(playerList); - noImpPlayer.RemoveAll(x => x.Data.Role.IsImpostor); - - if (modifiers.Contains(RoleId.Assassin)) { var assassinCount = 0; @@ -807,10 +803,15 @@ private static void assignModifiersToPlayers(List modifiers, List Cplayers = Cursed.hideModifier + ? new List(crewPlayer) + : playerList.Where(x => x.isImpostor() || isNeutral(x)).ToList(); + + playerId = setModifierToRandomPlayer((byte)RoleId.Cursed, Cplayers); + if (!Cursed.hideModifier) crewPlayer.RemoveAll(x => x.PlayerId == playerId); playerList.RemoveAll(x => x.PlayerId == playerId); - modifiers.RemoveAll(x => x == RoleId.Cursed); + modifiers.Remove(RoleId.Cursed); } if (modifiers.Contains(RoleId.Tunneler)) @@ -873,8 +874,10 @@ private static void assignModifiersToPlayers(List modifiers, List x.PlayerId == playerId); + var APlayers = new List(playerList); + APlayers.RemoveAll(x => x.isImpostor()); + + playerId = setModifierToRandomPlayer((byte)RoleId.Aftermath, APlayers); crewPlayer.RemoveAll(x => x.PlayerId == playerId); playerList.RemoveAll(x => x.PlayerId == playerId); modifiers.RemoveAll(x => x == RoleId.Aftermath); @@ -908,7 +911,8 @@ private static void assignModifiersToPlayers(List modifiers, List x == Mayor.mayor); playerId = setModifierToRandomPlayer((byte)RoleId.ButtonBarry, buttonPlayer); - buttonPlayer.RemoveAll(x => x.PlayerId == playerId); + crewPlayer.RemoveAll(x => x.PlayerId == playerId); + impPlayer.RemoveAll(x => x.PlayerId == playerId); playerList.RemoveAll(x => x.PlayerId == playerId); modifiers.RemoveAll(x => x == RoleId.ButtonBarry); } @@ -1093,11 +1097,11 @@ public class RoleAssignmentData public int maxImpostorRoles { get; set; } } - private enum RoleType + public enum AssignType { - Crewmate = 0, - Neutral = 1, - KillerNeutral = 2, - Impostor = 3 + Crewmate, + Neutral, + KillerNeutral, + Impostor } } \ No newline at end of file diff --git a/TheOtherRoles/Objects/Map/SabotagePatch.cs b/TheOtherRoles/Patches/SabotagePatch.cs similarity index 97% rename from TheOtherRoles/Objects/Map/SabotagePatch.cs rename to TheOtherRoles/Patches/SabotagePatch.cs index 20ef2034..172c51e1 100644 --- a/TheOtherRoles/Objects/Map/SabotagePatch.cs +++ b/TheOtherRoles/Patches/SabotagePatch.cs @@ -4,7 +4,7 @@ // 参考 => https://github.com/Koke1024/Town-Of-Moss/blob/main/TownOfMoss/Patches/MeltDownBoost.cs // 来源 => https://github.com/SuperNewRoles/SuperNewRoles/blob/master/SuperNewRoles/MapOption/MapOption.cs -namespace TheOtherRoles.Objects.Map; +namespace TheOtherRoles.Patches; public static class ElectricPatch { @@ -71,6 +71,8 @@ public static void Prefix(LifeSuppSystemType __instance, float deltaTime) } } } + + [HarmonyPatch(typeof(ReactorSystemType), nameof(ReactorSystemType.Deteriorate))] public static class MeltdownBooster { @@ -109,16 +111,12 @@ public static void Prefix(HeliSabotageSystem __instance) if (CustomOptionHolder.IsReactorDurationSetting.getBool()) { if (!__instance.IsActive) - { return; - } if (MapUtilities.CachedShipStatus != null) { if (__instance.Countdown >= CustomOptionHolder.AirshipReactorTimeLimit.getFloat()) - { __instance.Countdown = CustomOptionHolder.AirshipReactorTimeLimit.getFloat(); - } } } } diff --git a/TheOtherRoles/Patches/UpdatePatch.cs b/TheOtherRoles/Patches/UpdatePatch.cs index 3ba58d15..20be371d 100644 --- a/TheOtherRoles/Patches/UpdatePatch.cs +++ b/TheOtherRoles/Patches/UpdatePatch.cs @@ -287,6 +287,23 @@ private static void setNameTags() player.NameText.text += suffix; } + var localIsArsonist = Arsonist.arsonist != null && Arsonist.dousedPlayers != null && Arsonist.arsonist == local; + var localIsDead = Arsonist.arsonist != null && Arsonist.dousedPlayers != null && local.Data.IsDead; + if (localIsArsonist || localIsDead) + { + var suffix = cs(Arsonist.color, " ♨"); + foreach(var target in Arsonist.dousedPlayers) + { + target.cosmetics.nameText.text += suffix; + } + + if (MeetingHud.Instance != null) + foreach (var target in MeetingHud.Instance.playerStates) + if (Arsonist.dousedPlayers.Any(p => p.PlayerId == target.TargetPlayerId)) + target.NameText.text += suffix; + } + + // Lawyer or Prosecutor var localIsLawyer = Lawyer.lawyer != null && Lawyer.target != null && Lawyer.lawyer == local; var localIsKnowingTarget = Lawyer.lawyer != null && Lawyer.target != null && Lawyer.targetKnows && Lawyer.target == local; @@ -331,6 +348,7 @@ private static void setNameTags() var target = playerById(player.TargetPlayerId); if (target != null) player.NameText.text += $" ({(isLighterColor(target) ? "浅" : "深")})"; } + // Add medic shield info: if (MeetingHud.Instance != null && Medic.medic != null && Medic.shielded != null && Medic.shieldVisible(Medic.shielded)) { @@ -371,7 +389,7 @@ public static void miniUpdate() (Mini.mini == Morphling.morphling && Morphling.morphTimer > 0f) || (Mini.mini == Ninja.ninja && Ninja.isInvisble) || SurveillanceMinigamePatch.nightVisionIsActive || (Mini.mini == Swooper.swooper && Swooper.isInvisable) || - (Mini.mini == Jackal.jackal && Jackal.isInvisable) || isActiveCamoComms()) return; + (Mini.mini == Jackal.jackal && Jackal.isInvisable) || isActiveCamoComms) return; var growingProgress = Mini.growingProgress(); var scale = (growingProgress * 0.35f) + 0.35f; diff --git a/TheOtherRoles/RPC.cs b/TheOtherRoles/RPC.cs index d7a29136..2a9035f0 100644 --- a/TheOtherRoles/RPC.cs +++ b/TheOtherRoles/RPC.cs @@ -16,19 +16,21 @@ using TheOtherRoles.Objects; using TheOtherRoles.Objects.Map; using TheOtherRoles.Patches; +using TheOtherRoles.Roles; using TheOtherRoles.Utilities; using TMPro; using UnityEngine; using static TheOtherRoles.Buttons.HudManagerStartPatch; using static TheOtherRoles.GameHistory; using static TheOtherRoles.Options.ModOption; -using static TheOtherRoles.Roles.RoleClass; using Object = UnityEngine.Object; namespace TheOtherRoles; public enum RoleId { + Default, + Impostor, Morphling, Bomber, @@ -74,7 +76,6 @@ public enum RoleId Akujo, Thief, - Crew, Crewmate, Vigilante, Mayor, @@ -206,13 +207,11 @@ public enum CustomRPC AmnisiacTakeRole, MimicMimicRole, UsePortal, - TurnToCrewmate, PlaceJackInTheBox, LightsOut, PlaceCamera, SealVent, PartTimerSet, - ArsonistWin, GuesserShoot, LawyerSetTarget, ExecutionerSetTarget, @@ -226,7 +225,6 @@ public enum CustomRPC Bloody, SetFirstKill, SetMeetingChatOverlay, - SetTiebreak, SetInvisibleGen, SetSwoop, SetJackalSwoop, @@ -376,9 +374,6 @@ public static void setRole(byte roleId, byte playerId) case RoleId.Jester: Jester.jester = player; break; - case RoleId.Crew: - Crew.crew = player; - break; case RoleId.Werewolf: Werewolf.werewolf = player; break; @@ -742,18 +737,6 @@ public static void setCrewmate(PlayerControl player) CachedPlayer.LocalPlayer.PlayerControl.moveable = true; } - public static void turnToCrewmate(byte targetId) - { - var player = playerById(targetId); - if (player == null) return; - player.Data.Role.TeamType = RoleTeamTypes.Crewmate; - FastDestroyableSingleton.Instance.SetRole(player, RoleTypes.Crewmate); - erasePlayerRoles(player.PlayerId); - if (player.PlayerId == CachedPlayer.LocalPlayer.PlayerId) - CachedPlayer.LocalPlayer.PlayerControl.moveable = true; - setRole((byte)RoleId.Crew, targetId); - // player.Data.Role.IsImpostor = false; - } public static void setGameStarting() { @@ -902,7 +885,7 @@ public static void amnisiacTakeRole(byte targetId) var amnisiac = Amnisiac.amnisiac; if (target == null || amnisiac == null) return; var targetInfo = RoleInfo.getRoleInfoForPlayer(target); - var roleInfo = targetInfo.FirstOrDefault(info => info.roleTeam != RoleTeam.Modifier); + var roleInfo = targetInfo.FirstOrDefault(info => info.roleTeam != RoleType.Modifier); switch (roleInfo!.roleId) { case RoleId.Crewmate: @@ -1170,7 +1153,7 @@ public static void amnisiacTakeRole(byte targetId) Warlock.warlock = amnisiac; Amnisiac.clearAndReload(); break; - + case RoleId.Grenadier: Helpers.turnToImpostor(Amnisiac.amnisiac); if (Amnisiac.resetRole) Grenadier.clearAndReload(); @@ -1407,7 +1390,7 @@ public static void mimicMimicRole(byte targetId) var target = playerById(targetId); if (target == null || Mimic.mimic == null) return; var targetInfo = RoleInfo.getRoleInfoForPlayer(target); - var roleInfo = targetInfo.FirstOrDefault(info => info.roleTeam != RoleTeam.Modifier); + var roleInfo = targetInfo.FirstOrDefault(info => info.roleTeam != RoleType.Modifier); switch (roleInfo!.roleId) { case RoleId.BodyGuard: @@ -1733,8 +1716,8 @@ public static void morphlingMorph(byte playerId) public static void camouflagerCamouflage(byte setTimer) { - if (isActiveCamoComms() && setTimer != 2) return; - if (isCamoComms()) Camouflager.camoComms = true; + if (isActiveCamoComms && setTimer != 2) return; + if (isCamoComms) Camouflager.camoComms = true; if (Camouflager.camouflager == null && !Camouflager.camoComms) return; if (setTimer == 1) Camouflager.camouflageTimer = Camouflager.duration; if (MushroomSabotageActive()) return; // Dont overwrite the fungle "camo" @@ -1984,7 +1967,7 @@ public static void erasePlayerRoles(byte playerId, bool ignoreModifier = true) if (player == Camouflager.camouflager) Camouflager.clearAndReload(); if (player == Poucher.poucher && !Poucher.spawnModifier) Poucher.clearAndReload(); if (player == Vampire.vampire) Vampire.clearAndReload(); - if (player == Eraser.eraser) Eraser.eraser = null; + if (player == Eraser.eraser) Eraser.clearAndReload(); if (player == Trickster.trickster) Trickster.clearAndReload(); if (player == Cleaner.cleaner) Cleaner.clearAndReload(); if (player == Undertaker.undertaker) Undertaker.clearAndReload(); @@ -2254,7 +2237,7 @@ public static void setInvisible(byte playerId, byte flag) target.cosmetics.colorBlindText.gameObject.SetActive(DataManager.Settings.Accessibility.ColorBlindMode); target.cosmetics.colorBlindText.color = target.cosmetics.colorBlindText.color.SetAlpha(1f); - if (Camouflager.camouflageTimer <= 0 && !MushroomSabotageActive() && !isCamoComms()) + if (Camouflager.camouflageTimer <= 0 && !MushroomSabotageActive() && !isCamoComms) target.setDefaultLook(); Ninja.isInvisble = false; return; @@ -2340,8 +2323,12 @@ public static void akujoSuicide(byte akujoId) var akujo = playerById(akujoId); if (akujo != null) { - akujo.MurderPlayer(akujo, MurderResultFlags.Succeeded); + akujo.Exiled(); overrideDeathReasonAndKiller(akujo, DeadPlayer.CustomDeathReason.Loneliness); + + if (Constants.ShouldPlaySfx()) SoundManager.Instance.PlaySound(akujo.KillSfx, false, 0.8f); + if (PlayerControl.LocalPlayer == Akujo.akujo) + FastDestroyableSingleton.Instance.KillOverlay.ShowKillAnimation(akujo.Data, akujo.Data); } } @@ -2404,7 +2391,7 @@ public static void setSwoop(byte playerId, byte flag) target.cosmetics.currentBodySprite.BodySprite.color = Color.white; target.cosmetics.colorBlindText.gameObject.SetActive(DataManager.Settings.Accessibility.ColorBlindMode); target.cosmetics.colorBlindText.color = target.cosmetics.colorBlindText.color.SetAlpha(1f); - if (Camouflager.camouflageTimer <= 0 && !MushroomSabotageActive() & !isCamoComms()) + if (Camouflager.camouflageTimer <= 0 && !MushroomSabotageActive() & !isCamoComms) target.setDefaultLook(); Swooper.isInvisable = false; return; @@ -2430,7 +2417,7 @@ public static void setJackalSwoop(byte playerId, byte flag) target.cosmetics.currentBodySprite.BodySprite.color = Color.white; target.cosmetics.colorBlindText.gameObject.SetActive(DataManager.Settings.Accessibility.ColorBlindMode); target.cosmetics.colorBlindText.color = target.cosmetics.colorBlindText.color.SetAlpha(1f); - if (Camouflager.camouflageTimer <= 0 && !MushroomSabotageActive() & !isCamoComms()) + if (Camouflager.camouflageTimer <= 0 && !MushroomSabotageActive() & !isCamoComms) target.setDefaultLook(); Jackal.isInvisable = false; return; @@ -2615,18 +2602,6 @@ public static void sealVent(int ventId) ventsToSeal.Add(vent); } - public static void arsonistWin() - { - Arsonist.triggerArsonistWin = true; - foreach (PlayerControl p in CachedPlayer.AllPlayers) - //if (p != Arsonist.arsonist && !p.Data.IsDead) - if (p != Arsonist.arsonist && Arsonist.dousedPlayers.Any(x => x == p && !p.Data.IsDead)) - { - p.Exiled(); - overrideDeathReasonAndKiller(p, DeadPlayer.CustomDeathReason.Arson, Arsonist.arsonist); - } - } - public static void lawyerSetTarget(byte playerId) { Lawyer.target = playerById(playerId); @@ -2771,8 +2746,7 @@ public static void guesserShoot(byte killerId, byte dyingTargetId, byte guessedT { if (CachedPlayer.LocalPlayer.PlayerControl == dyingTarget) { - FastDestroyableSingleton.Instance.KillOverlay.ShowKillAnimation(guesser.Data, - dyingTarget.Data); + FastDestroyableSingleton.Instance.KillOverlay.ShowKillAnimation(guesser.Data, dyingTarget.Data); if (Guesser.guesserUI != null) Guesser.guesserUIExitButton.OnClick.Invoke(); } else if (dyingLoverPartner != null && CachedPlayer.LocalPlayer.PlayerControl == dyingLoverPartner) @@ -2916,11 +2890,6 @@ public static void setChatNotificationOverlay(byte localPlayerId, byte targetPla } } - public static void setTiebreak() - { - Tiebreaker.isTiebreak = true; - } - public static void thiefStealsRole(byte playerId) { var target = playerById(playerId); @@ -3531,10 +3500,6 @@ private static bool Prefix([HarmonyArgument(0)] byte callId, [HarmonyArgument(1) RPCProcedure.sealVent(reader.ReadPackedInt32()); break; - case CustomRPC.ArsonistWin: - RPCProcedure.arsonistWin(); - break; - case CustomRPC.GuesserShoot: var killerId = reader.ReadByte(); var dyingTarget = reader.ReadByte(); @@ -3590,10 +3555,6 @@ private static bool Prefix([HarmonyArgument(0)] byte callId, [HarmonyArgument(1) RPCProcedure.setChatNotificationOverlay(localPlayerId, targetPlayerId); break; - case CustomRPC.SetTiebreak: - RPCProcedure.setTiebreak(); - break; - case CustomRPC.ShowBodyGuardFlash: RPCProcedure.showBodyGuardFlash(); break; @@ -3634,10 +3595,6 @@ private static bool Prefix([HarmonyArgument(0)] byte callId, [HarmonyArgument(1) RPCProcedure.turnToImpostor(reader.ReadByte()); break; - case CustomRPC.TurnToCrewmate: - RPCProcedure.turnToCrewmate(reader.ReadByte()); - break; - case CustomRPC.ThiefStealsRole: var thiefTargetId = reader.ReadByte(); RPCProcedure.thiefStealsRole(thiefTargetId); diff --git a/TheOtherRoles/Resources/stringData.json b/TheOtherRoles/Resources/stringData.json index 2f26b5b0..848dbe9f 100644 --- a/TheOtherRoles/Resources/stringData.json +++ b/TheOtherRoles/Resources/stringData.json @@ -4013,7 +4013,7 @@ "13": "哈哈~白板红狼!" }, "AssassinFullDesc": { - "13": "刺客使红狼具有会议上猜测别人职业的能力。\n所有刺客拥有共享的猜测次数。" + "13": "分配阵营:伪装者\n刺客使红狼具有会议上猜测别人职业的能力。\n所有刺客拥有共享的猜测次数。\n\n注:赌怪模式中不会出现侠客与刺客" }, "MorphlingFullDesc": { "13": "采样后可以伪装成其他人。" @@ -4076,7 +4076,7 @@ "13": "可以标记一个位置,使用技能后会瞬移到标记点,\n技能有持续时间,持续时间结束后将再瞬移回传送前的位置。\n\n拥有随身管理地图。" }, "EvilTrapperFullDesc": { - "13": "能够放置多个陷阱,放置后,陷阱将在特定的时间后激活。\n如果玩家离陷阱太近,玩家就会被陷阱卡住。\n在一段时间后,如果没有人来营救被困玩家,他就会死亡。\n(营救方式:其他玩家再次踩到陷阱即可)\n特定范围内的每个人都会听到被困玩家被陷阱击杀的声音。" + "13": "能够放置多个陷阱,放置后,陷阱将在特定的时间后激活。\n如果玩家离陷阱太近,玩家就会被陷阱卡住。\n在一段时间后,如果没有人来营救被困玩家,他就会死亡。\n\n(营救方式:其他玩家再次踩到陷阱即可)\n特定范围内的每个人都会听到被困玩家被陷阱击杀的声音。" }, "GamblerFullDesc": { "13": "每次击杀,下一次击杀冷却会随机变化。\n注:赌徒无法获得绝境者" @@ -4142,7 +4142,7 @@ "13": "哈哈~白板船员!" }, "VigilanteFullDesc": { - "13": "侠客具有会议上猜测别人职业的能力,猜对方就会死亡;\n猜错了,侠客自己死亡。\n" + "13": "侠客具有会议上猜测别人职业的能力,猜对方就会死亡;\n猜错了,侠客自己死亡。\n\n注:赌怪模式中不会出现侠客与刺客" }, "MayorFullDesc": { "13": "市长在投票阶段可以通过点击揭示按钮揭示自己的身份,无法被猜测。\n\n揭示后会议内拥有3票(具体按房间设置为准),同时视野大幅缩小。\n\n另外,根据房间设置,市长可以拥有远程开会议的能力。" @@ -4220,84 +4220,84 @@ "13": "可以在会议中选择两位玩家挂上天平,所有玩家只能在这两位玩家中投票。\n\n在特殊会议中,如果平票则同时驱逐两位玩家。\n\n如果其中一位玩家死亡(例如被赌死),则直接跳过投票环节直接驱逐另一位被挂上天平的玩家。可以在会议中选择两位玩家挂上天平,所有玩家只能在这两位玩家中投票。\n\n在特殊会议中,如果平票则同时驱逐两位玩家。\n\n如果其中一位玩家死亡(例如被赌死),则直接跳过投票环节直接驱逐另一位被挂上天平的玩家。" }, "LoverFullDesc": { - "13": "执子之手,与子共生。\n恋人如果有任何一方被击杀,另一方也会一起死亡。\n当恋人中有一方并非船员时并且恋人存活,\n则不会计算该玩家的任务进度。\n\n剩余3名玩家时并且两名玩家为恋人时,\n恋人将独自获胜。" + "13": "执子之手,与子共生。\n恋人如果有任何一方被击杀,另一方也会一起死亡。\n当恋人中有一方并非船员时并且恋人存活,\n则不会计算该玩家的任务进度。\n\n剩余3名玩家时并且两名玩家为恋人时,\n恋人将直接独自获胜。" }, "DisperserFullDesc": { - "13": "分散者可以打乱当前所有玩家位置。" + "13": "分配阵营:伪装者\n\n分散者可以打乱当前所有玩家位置。" }, "SpecoalityFullDesc": { - "13": "可以猜错一次职业,对目标猜测错误后,本次会议无法再次猜测该玩家。" + "13": "分配阵营:伪装者(赌怪)\n\n可以猜错一次职业,对目标猜测错误后,本次会议无法再次猜测该玩家。" }, "LastImpostorFullDesc": { - "13": "仅剩余一名伪装者时,击杀冷却减少\n(目前赏金猎人暂时无效)" + "13": "分配阵营:伪装者\n\n仅剩余一名伪装者时,击杀冷却减少\n(目前赏金猎人与赌徒无法无效)" }, "BloodyFullDesc": { - "13": "被击杀后,凶手会在地上留下血迹" + "13": "分配阵营:全部玩家\n\n被击杀后,凶手会在地上留下血迹" }, "AntiTeleportFullDesc": { - "13": "会议及分散后,通讯兵会回到会议前和分散前的位置。" + "13": "分配阵营:全部玩家\n\n会议及分散后,通讯兵会回到会议前和分散前的位置。" }, "TieBreakerFullDesc": { - "13": "破平者的投票时,票数计为1.5票" + "13": "分配阵营:全部玩家\n\n破平者的投票时,票数计为1.5票" }, "BaitFullDesc": { - "13": "被击杀后凶手自动报警" + "13": "分配阵营:全部玩家(可设置为仅船员)\n\n被击杀后凶手自动报警" }, "AftermathFullDesc": { - "13": "被击杀后凶手会被动使用一次技能。\n其中技能如果需要目标则为杀手自己。\n\n例如:\n勒索者击杀余波后会自动勒索自己,\n清理者击杀余波会自动清理余波的尸体等。" + "13": "分配阵营:中立、船员阵营\n\n被击杀后凶手会被动使用一次技能。\n其中技能如果需要目标则为杀手自己。\n\n例如:\n勒索者击杀余波后会自动勒索自己,\n清理者击杀余波会自动清理余波的尸体等。" }, "SunglassesFullDesc": { - "13": "视野会变小" + "13": "分配阵营:船员\n\n视野会变小" }, "TorchFullDesc": { - "13": "熄灯时视野不变,并且视野较大。" + "13": "分配阵营:船员\n\n熄灯时视野不变,并且视野较大。" }, "FlashFullDesc": { - "13": "移速变得更快" + "13": "分配阵营:全部玩家\n\n移速变得更快" }, "MultitaskerFullDesc": { - "13": "任务界面透明" + "13": "分配阵营:船员\n\n任务界面透明" }, "GiantFullDesc": { - "13": "体型更大,移速更“慢”" + "13": "分配阵营:全部玩家\n\n体型更大,移速更“慢”" }, "MiniFullDesc": { - "13": "18岁之前不可被击杀,但击杀CD双倍。\n18岁后可被击杀且击杀CD变短。\n\n此外,小孩被驱逐时,如果小孩为船员则结束游戏(所有玩家失败)" + "13": "分配阵营:全部玩家\n\n18岁之前不可被击杀,但击杀CD双倍。\n18岁后可被击杀且击杀CD变短。\n\n此外,小孩被驱逐时,如果小孩为船员则结束游戏(所有玩家失败)" }, "VipFullDesc": { - "13": "VIP死亡时,所有人都会接收到闪光。\n如果房间设置闪光可显示阵营颜色,\n则白色闪光代表死者为船员,蓝色代表中立,红色代表红狼。" + "13": "分配阵营:全部玩家\n\nVIP死亡时,所有人都会接收到闪光。\n如果房间设置闪光可显示阵营颜色,\n则白色闪光代表死者为船员,蓝色代表中立,红色代表红狼。" }, "IndomitableFullDesc": { - "13": "不屈者会议上不会因为猜测而死亡。" + "13": "分配阵营:全部玩家\n\n不屈者会议上不会因为猜测而死亡。" }, "SluethFullDesc": { - "13": "报警时可以获取所报尸体的职业信息" + "13": "分配阵营:全部玩家\n\n报警时可以获取所报尸体的职业信息" }, "CursedFullDesc": { - "13": "在红狼占优的情况下可能会\n自动加入红狼阵营变为白板伪装者,\n或者被红狼击杀时会立即加入红狼阵营。" + "13": "分配阵营:船员\n\n在红狼占优的情况下可能会\n自动加入红狼阵营变为白板伪装者,\n或者被红狼击杀时会立即加入红狼阵营。" }, "InvertFullDesc": { - "13": "移动方向相反" + "13": "分配阵营:全部玩家\n\n移动方向相反,过几次会议后即可醒酒" }, "BlindFullDesc": { - "13": "胆小鬼无法报告尸体。" + "13": "分配阵营:全部玩家\n\n胆小鬼无法报告尸体。" }, "WatcherFullDesc": { - "13": "会议结束时可以看到具体投票情况。" + "13": "分配阵营:全部玩家\n\n会议结束时可以看到具体投票情况。" }, "RadarFullDesc": { - "13": "始终有箭头指向离你最近的人" + "13": "分配阵营:全部玩家\n\n始终有箭头指向离你最近的人" }, "TunnelerFullDesc": { - "13": "做完所有任务后获得使用通风管道的能力" + "13": "分配阵营:船员\n\n做完所有任务后获得使用通风管道的能力" }, "ButtonBarryFullDesc": { - "13": "拥有一次远程召开会议的能力" + "13": "分配阵营:全部玩家\n\n拥有一次远程召开会议的能力" }, "ChameleonFullDesc": { - "13": "站在原地不动可以逐渐变色隐身,移动后会解除隐身状态。" + "13": "分配阵营:全部玩家\n\n站在原地不动可以逐渐变色隐身,移动后会解除隐身状态。" }, "ShifterFullDesc": { - "13": "可以在行动阶段与其他玩家交换主职业,会议结束后生效。\n如果交换目标不是船员(可以设置),会议结束时会自杀。\n(交换完毕后此附加能力消失)\n提示:交换师的目的主要是为了继承船员强力职业,例如在警长死亡前将身份交换。" + "13": "分配阵营:船员(可设置为中立交换师)\n\n可以在行动阶段与其他玩家交换主职业,交换时名字下方会有黄字提示,\n会议结束后生效。\n如果交换目标不是船员(可以设置),会议结束时会自杀。\n(交换完毕后此附加能力消失)\n提示:交换师的目的主要是为了继承船员强力职业,\n例如在警长死亡前将身份交换。\n\n注:玩家死亡不会影响交换效果。" } } \ No newline at end of file diff --git a/TheOtherRoles/Roles/Guesser.cs b/TheOtherRoles/Roles/Guesser.cs index fed77635..2ed3795c 100644 --- a/TheOtherRoles/Roles/Guesser.cs +++ b/TheOtherRoles/Roles/Guesser.cs @@ -42,16 +42,16 @@ public static int remainingShots(byte playerId, bool shoot = false) public const int MaxOneScreenRole = 40; - private static Dictionary> RoleButtons; - private static Dictionary RoleSelectButtons; - public static RoleTeam currentTeamType; + private static Dictionary> RoleButtons; + private static Dictionary RoleSelectButtons; + public static RoleType currentTeamType; private static List PageButtons; public static GameObject guesserUI; public static PassiveButton guesserUIExitButton; public static int Page; public static byte guesserCurrentTarget; - private static void guesserSelectRole(RoleTeam Role, bool SetPage = true) + private static void guesserSelectRole(RoleType Role, bool SetPage = true) { currentTeamType = Role; if (SetPage) Page = 1; @@ -137,18 +137,18 @@ public static void guesserOnClick(int buttonTarget, MeetingHud __instance) Transform TeambuttonMask = Object.Instantiate(maskTemplate, TeambuttonParent); TextMeshPro Teamlabel = Object.Instantiate(textTemplate, Teambutton); //Teambutton.GetComponent().sprite = ShipStatus.Instance.CosmeticsCache.GetNameplate("nameplate_NoPlate").Image; - RoleSelectButtons.Add((RoleTeam)index, Teambutton.GetComponent()); + RoleSelectButtons.Add((RoleType)index, Teambutton.GetComponent()); TeambuttonParent.localPosition = new(-2.75f + (index * 1.75f), 2.225f, -200); TeambuttonParent.localScale = new(0.55f, 0.55f, 1f); - Teamlabel.color = getTeamColor((RoleTeam)index); + Teamlabel.color = getTeamColor((RoleType)index); //Info($"{Teamlabel.color} {(RoleTeam)index}"); - Teamlabel.text = getString(((RoleTeam)index is RoleTeam.Crewmate ? "Crewmate" : ((RoleTeam)index).ToString()) + "RolesText"); + Teamlabel.text = getString(((RoleType)index is RoleType.Crewmate ? "Crewmate" : ((RoleType)index).ToString()) + "RolesText"); Teamlabel.alignment = TextAlignmentOptions.Center; Teamlabel.transform.localPosition = new Vector3(0, 0, Teamlabel.transform.localPosition.z); Teamlabel.transform.localScale *= 1.6f; Teamlabel.autoSizeTextContainer = true; - static void CreateTeamButton(Transform Teambutton, RoleTeam type) + static void CreateTeamButton(Transform Teambutton, RoleType type) { Teambutton.GetComponent().OnClick.AddListener((UnityEngine.Events.UnityAction)(() => { @@ -156,7 +156,7 @@ static void CreateTeamButton(Transform Teambutton, RoleTeam type) ReloadPage(); })); } - if (!PlayerControl.LocalPlayer.Data.IsDead) CreateTeamButton(Teambutton, (RoleTeam)index); + if (!PlayerControl.LocalPlayer.Data.IsDead) CreateTeamButton(Teambutton, (RoleType)index); } static void ReloadPage() @@ -231,7 +231,7 @@ static void CreatePage(bool IsNext, MeetingHud __instance, Transform container) { if (roleInfo == null) continue; // Not guessable roles - if (RoleClass.RoleIsEnable.TryGetValue(roleInfo.roleId, out int isEnabled) && isEnabled == 0) + if (RoleIsEnable.TryGetValue(roleInfo.roleId, out int isEnabled) && isEnabled == 0) { continue; } @@ -240,13 +240,13 @@ static void CreatePage(bool IsNext, MeetingHud __instance, Transform container) if (CachedPlayer.LocalId == Doomsayer.doomsayer?.PlayerId) { - if (!Doomsayer.canGuessImpostor && roleInfo.roleTeam == RoleTeam.Impostor) + if (!Doomsayer.canGuessImpostor && roleInfo.roleTeam == RoleType.Impostor) continue; - if (!Doomsayer.canGuessNeutral && roleInfo.roleTeam == RoleTeam.Neutral) + if (!Doomsayer.canGuessNeutral && roleInfo.roleTeam == RoleType.Neutral) continue; } - if (roleInfo.roleTeam == RoleTeam.Modifier && ModOption.allowModGuess && !roleInfo.isGuessable) + if (roleInfo.roleTeam == RoleType.Modifier && ModOption.allowModGuess && !roleInfo.isGuessable) continue; // remove all roles that cannot spawn due to the settings from the ui. @@ -285,7 +285,7 @@ static void CreatePage(bool IsNext, MeetingHud __instance, Transform container) void CreateRole(RoleInfo roleInfo = null) { - RoleTeam team = roleInfo?.roleTeam ?? RoleTeam.Crewmate; + RoleType team = roleInfo?.roleTeam ?? RoleType.Crewmate; //Color color = roleInfo?.color ?? Color.white; //RoleId role = roleInfo?.roleId ?? RoleId.Crewmate; @@ -350,7 +350,8 @@ void CreateRole(RoleInfo roleInfo = null) } if (focusedTarget == Indomitable.indomitable) { - showFlash(new Color32(255, 197, 97, byte.MinValue)); + //showFlash(new Color32(255, 197, 97, byte.MinValue)); + Coroutines.Start(showFlashCoroutine(Indomitable.color, 1f, 0.5f)); __instance.playerStates.ForEach(x => x.gameObject.SetActive(true)); Object.Destroy(container.gameObject); @@ -380,9 +381,10 @@ void CreateRole(RoleInfo roleInfo = null) { if (guesserUI != null) guesserUIExitButton.OnClick.Invoke(); - Coroutines.Start(showFlashCoroutine(Color.red, 0.75f, 0.4f)); + Coroutines.Start(showFlashCoroutine(Color.red, 1f, 0.5f)); Specoality.linearfunction--; - RPCProcedure.seedGuessChat(CachedPlayer.LocalPlayer.PlayerControl, dyingTarget, (byte)roleInfo.roleId); + SoundEffectsManager.play("fail"); + //RPCProcedure.seedGuessChat(CachedPlayer.LocalPlayer.PlayerControl, dyingTarget, (byte)roleInfo.roleId); __instance.playerStates.ForEach(x => { if (x.TargetPlayerId == focusedTarget.PlayerId && x.transform.FindChild("ShootButton") != null) @@ -429,7 +431,7 @@ void CreateRole(RoleInfo roleInfo = null) i[(int)team]++; ind++; } - guesserSelectRole(RoleTeam.Crewmate); + guesserSelectRole(RoleType.Crewmate); ReloadPage(); } } \ No newline at end of file diff --git a/TheOtherRoles/Roles/Impostor/Camouflager.cs b/TheOtherRoles/Roles/Impostor/Camouflager.cs index 5ae63def..8226ec59 100644 --- a/TheOtherRoles/Roles/Impostor/Camouflager.cs +++ b/TheOtherRoles/Roles/Impostor/Camouflager.cs @@ -17,7 +17,7 @@ public static class Camouflager public static void resetCamouflage() { - if (isCamoComms()) return; + if (isCamoComms) return; camouflageTimer = 0f; foreach (PlayerControl p in CachedPlayer.AllPlayers) { diff --git a/TheOtherRoles/Roles/Impostor/Grenadier.cs b/TheOtherRoles/Roles/Impostor/Grenadier.cs index 90ab9222..9218f630 100644 --- a/TheOtherRoles/Roles/Impostor/Grenadier.cs +++ b/TheOtherRoles/Roles/Impostor/Grenadier.cs @@ -28,6 +28,7 @@ public static void showFlash(Color color, float duration = 10f, float alpha = 1f FastDestroyableSingleton.Instance.FullScreen.gameObject.SetActive(true); FastDestroyableSingleton.Instance.FullScreen.enabled = true; + DestroyableSingleton.Instance.FullScreen.gameObject.active = true; FastDestroyableSingleton.Instance.StartCoroutine(Effects.Lerp(duration, new Action(p => { diff --git a/TheOtherRoles/Roles/Modifier/Indomitable.cs b/TheOtherRoles/Roles/Modifier/Indomitable.cs index 4c844171..c1e6e6ad 100644 --- a/TheOtherRoles/Roles/Modifier/Indomitable.cs +++ b/TheOtherRoles/Roles/Modifier/Indomitable.cs @@ -5,7 +5,7 @@ namespace TheOtherRoles.Roles.Modifier; public static class Indomitable { public static PlayerControl indomitable; - public static Color color = new Color32(0, 247, 255, byte.MaxValue); + public static Color color = Color.yellow; public static void clearAndReload() diff --git a/TheOtherRoles/Roles/Modifier/Tiebreaker.cs b/TheOtherRoles/Roles/Modifier/Tiebreaker.cs index d85e6713..f5c3b646 100644 --- a/TheOtherRoles/Roles/Modifier/Tiebreaker.cs +++ b/TheOtherRoles/Roles/Modifier/Tiebreaker.cs @@ -4,11 +4,9 @@ public static class Tiebreaker { public static PlayerControl tiebreaker; - public static bool isTiebreak; public static void clearAndReload() { tiebreaker = null; - isTiebreak = false; } } diff --git a/TheOtherRoles/Roles/Neutral/Arsonist.cs b/TheOtherRoles/Roles/Neutral/Arsonist.cs index 7fac03fb..d3249a05 100644 --- a/TheOtherRoles/Roles/Neutral/Arsonist.cs +++ b/TheOtherRoles/Roles/Neutral/Arsonist.cs @@ -15,6 +15,7 @@ public static class Arsonist public static bool triggerArsonistWin; public static PlayerControl currentTarget; + public static PlayerControl currentTarget2; public static PlayerControl douseTarget; public static List dousedPlayers = new(); diff --git a/TheOtherRoles/Roles/RoleClass.cs b/TheOtherRoles/Roles/RoleClass.cs deleted file mode 100644 index 5ea8b2b6..00000000 --- a/TheOtherRoles/Roles/RoleClass.cs +++ /dev/null @@ -1,265 +0,0 @@ -using System.Collections.Generic; -using MonoMod.Utils; -using TheOtherRoles.CustomGameModes; -using TheOtherRoles.Utilities; -using UnityEngine; - -namespace TheOtherRoles.Roles; - -[HarmonyPatch] -public static class RoleClass -{ - public static void clearAndReloadRoles() - { - Vigilante.clearAndReload(); - Jester.clearAndReload(); - Mayor.clearAndReload(); - Prosecutor.clearAndReload(); - Portalmaker.clearAndReload(); - Poucher.clearAndReload(); - Mimic.clearAndReload(); - Engineer.clearAndReload(); - Sheriff.clearAndReload(); - InfoSleuth.clearAndReload(); - Gambler.clearAndReload(); - Butcher.clearAndReload(); - Deputy.clearAndReload(); - Amnisiac.clearAndReload(); - Detective.clearAndReload(); - Werewolf.clearAndReload(); - TimeMaster.clearAndReload(); - BodyGuard.clearAndReload(); - Veteran.clearAndReload(); - Medic.clearAndReload(); - Shifter.clearAndReload(); - Swapper.clearAndReload(); - Lovers.clearAndReload(); - Seer.clearAndReload(); - Morphling.clearAndReload(); - Camouflager.clearAndReload(); - Hacker.clearAndReload(); - Tracker.clearAndReload(); - Vampire.clearAndReload(); - Snitch.clearAndReload(); - Jackal.clearAndReload(); - Sidekick.clearAndReload(); - Pavlovsdogs.clearAndReload(); - Eraser.clearAndReload(); - Spy.clearAndReload(); - Trickster.clearAndReload(); - Cleaner.clearAndReload(); - Undertaker.clearAndReload(); - Warlock.clearAndReload(); - SecurityGuard.clearAndReload(); - Arsonist.clearAndReload(); - BountyHunter.clearAndReload(); - Vulture.clearAndReload(); - Medium.clearAndReload(); - Bomber.clearAndReload(); - Lawyer.clearAndReload(); - Executioner.clearAndReload(); - Pursuer.clearAndReload(); - Witch.clearAndReload(); - Jumper.clearAndReload(); - Prophet.clearAndReload(); - Escapist.clearAndReload(); - Ninja.clearAndReload(); - Blackmailer.clearAndReload(); - Thief.clearAndReload(); - Miner.clearAndReload(); - Trapper.clearAndReload(); - Terrorist.clearAndReload(); - Juggernaut.clearAndReload(); - Doomsayer.clearAndReload(); - Swooper.clearAndReload(); - Balancer.clearAndReload(); - Akujo.clearAndReload(); - Yoyo.clearAndReload(); - EvilTrapper.clearAndReload(); - Survivor.clearAndReload(); - PartTimer.clearAndReload(); - Grenadier.clearAndReload(); - - // Modifier - Assassin.clearAndReload(); - Aftermath.clearAndReload(); - Bait.clearAndReload(); - Bloody.clearAndReload(); - AntiTeleport.clearAndReload(); - Tiebreaker.clearAndReload(); - Sunglasses.clearAndReload(); - Torch.clearAndReload(); - Flash.clearAndReload(); - Blind.clearAndReload(); - Watcher.clearAndReload(); - Radar.clearAndReload(); - Tunneler.clearAndReload(); - Multitasker.clearAndReload(); - Disperser.clearAndReload(); - Mini.clearAndReload(); - Giant.clearAndReload(); - Indomitable.clearAndReload(); - Slueth.clearAndReload(); - Cursed.clearAndReload(); - Vip.clearAndReload(); - Invert.clearAndReload(); - Chameleon.clearAndReload(); - ButtonBarry.clearAndReload(); - LastImpostor.clearAndReload(); - Specoality.clearAndReload(); - - // Gamemodes - HandleGuesser.clearAndReload(); - HideNSeek.clearAndReload(); - PropHunt.clearAndReload(); - - blockRole(); - ResetRoleSelection(); - } - - public static class Crew - { - public static PlayerControl crew; - public static Color color = Palette.White; - - public static void clearAndReload() - { - crew = null; - } - } - - public static Dictionary blockedRolePairings = new(); - - public static void blockRole() - { - blockedRolePairings.Clear(); - - blockedRolePairings.Add((byte)RoleId.Vampire, [(byte)RoleId.Warlock]); - blockedRolePairings.Add((byte)RoleId.Witch, [(byte)RoleId.Warlock]); - blockedRolePairings.Add((byte)RoleId.Warlock, [(byte)RoleId.Vampire]); - - if (CustomOptionHolder.pavlovsownerAndJackalAsWell.getBool()) - { - blockedRolePairings.Add((byte)RoleId.Jackal, [(byte)RoleId.Pavlovsowner]); - blockedRolePairings.Add((byte)RoleId.Pavlovsowner, [(byte)RoleId.Jackal]); - } - if (Executioner.promotesToLawyer) - { - blockedRolePairings.Add((byte)RoleId.Executioner, [(byte)RoleId.Lawyer]); - blockedRolePairings.Add((byte)RoleId.Lawyer, [(byte)RoleId.Executioner]); - } - - blockedRolePairings.Add((byte)RoleId.Vulture, [(byte)RoleId.Cleaner]); - blockedRolePairings.Add((byte)RoleId.Cleaner, [(byte)RoleId.Vulture]); - - blockedRolePairings.Add((byte)RoleId.Ninja, [(byte)RoleId.Swooper]); - blockedRolePairings.Add((byte)RoleId.Swooper, [(byte)RoleId.Ninja]); - } - - public static Dictionary RoleIsEnable = new(); - - public static void ResetRoleSelection() - { - RoleIsEnable.Clear(); - RoleIsEnable.AddRange(new() - { - { RoleId.Sheriff, CustomOptionHolder.sheriffSpawnRate.getSelection() }, - { RoleId.Deputy, CustomOptionHolder.deputySpawnRate.getSelection() }, - { RoleId.BodyGuard, CustomOptionHolder.bodyGuardSpawnRate.getSelection() }, - { RoleId.Balancer, CustomOptionHolder.balancerSpawnRate.getSelection() }, - { RoleId.Detective, CustomOptionHolder.detectiveSpawnRate.getSelection() }, - { RoleId.Engineer, CustomOptionHolder.engineerSpawnRate.getSelection() }, - { RoleId.Hacker, CustomOptionHolder.hackerSpawnRate.getSelection() }, - { RoleId.InfoSleuth, CustomOptionHolder.infoSleuthSpawnRate.getSelection() }, - { RoleId.Jumper, CustomOptionHolder.jumperSpawnRate.getSelection() }, - { RoleId.Mayor, CustomOptionHolder.mayorSpawnRate.getSelection() }, - { RoleId.Medic, CustomOptionHolder.medicSpawnRate.getSelection() }, - { RoleId.Medium, CustomOptionHolder.mediumSpawnRate.getSelection() }, - { RoleId.Portalmaker, CustomOptionHolder.portalmakerSpawnRate.getSelection() }, - { RoleId.Prophet, CustomOptionHolder.prophetSpawnRate.getSelection() }, - { RoleId.Prosecutor, CustomOptionHolder.prosecutorSpawnRate.getSelection() }, - { RoleId.SecurityGuard, CustomOptionHolder.securityGuardSpawnRate.getSelection() }, - { RoleId.Seer, CustomOptionHolder.seerSpawnRate.getSelection() }, - { RoleId.Snitch, CustomOptionHolder.snitchSpawnRate.getSelection() }, - { RoleId.Spy, CustomOptionHolder.spySpawnRate.getSelection() }, - { RoleId.Swapper, CustomOptionHolder.swapperSpawnRate.getSelection() }, - { RoleId.TimeMaster, CustomOptionHolder.timeMasterSpawnRate.getSelection() }, - { RoleId.Tracker, CustomOptionHolder.trackerSpawnRate.getSelection() }, - { RoleId.Trapper, CustomOptionHolder.trapperSpawnRate.getSelection() }, - { RoleId.Veteran, CustomOptionHolder.veteranSpawnRate.getSelection() }, - { RoleId.Vigilante, CustomOptionHolder.guesserSpawnRate.getSelection() }, - - { RoleId.Blackmailer, CustomOptionHolder.blackmailerSpawnRate.getSelection() }, - { RoleId.Bomber, CustomOptionHolder.bomberSpawnRate.getSelection() }, - { RoleId.BountyHunter, CustomOptionHolder.bountyHunterSpawnRate.getSelection() }, - { RoleId.Butcher, CustomOptionHolder.butcherSpawnRate.getSelection() }, - { RoleId.Camouflager, CustomOptionHolder.camouflagerSpawnRate.getSelection() }, - { RoleId.Cleaner, CustomOptionHolder.cleanerSpawnRate.getSelection() }, - { RoleId.Eraser, CustomOptionHolder.eraserSpawnRate.getSelection() }, - { RoleId.Escapist, CustomOptionHolder.escapistSpawnRate.getSelection() }, - { RoleId.EvilTrapper, CustomOptionHolder.evilTrapperSpawnRate.getSelection() }, - { RoleId.Gambler, CustomOptionHolder.gamblerSpawnRate.getSelection() }, - { RoleId.Mimic, CustomOptionHolder.mimicSpawnRate.getSelection() }, - { RoleId.Miner, CustomOptionHolder.minerSpawnRate.getSelection() }, - { RoleId.Morphling, CustomOptionHolder.morphlingSpawnRate.getSelection() }, - { RoleId.Ninja, CustomOptionHolder.ninjaSpawnRate.getSelection() }, - { RoleId.Poucher, CustomOptionHolder.poucherSpawnRate.getSelection() }, - { RoleId.Terrorist, CustomOptionHolder.terroristSpawnRate.getSelection() }, - { RoleId.Trickster, CustomOptionHolder.tricksterSpawnRate.getSelection() }, - { RoleId.Undertaker, CustomOptionHolder.undertakerSpawnRate.getSelection() }, - { RoleId.Vampire, CustomOptionHolder.vampireSpawnRate.getSelection() }, - { RoleId.Warlock, CustomOptionHolder.warlockSpawnRate.getSelection() }, - { RoleId.Witch, CustomOptionHolder.witchSpawnRate.getSelection() }, - { RoleId.Yoyo, CustomOptionHolder.yoyoSpawnRate.getSelection() }, - { RoleId.Grenadier, CustomOptionHolder.grenadierSpawnRate.getSelection() }, - - { RoleId.Akujo, CustomOptionHolder.akujoSpawnRate.getSelection() }, - { RoleId.Amnisiac, CustomOptionHolder.amnisiacSpawnRate.getSelection() }, - { RoleId.Arsonist, CustomOptionHolder.arsonistSpawnRate.getSelection() }, - { RoleId.Doomsayer, CustomOptionHolder.doomsayerSpawnRate.getSelection() }, - { RoleId.Executioner, CustomOptionHolder.executionerSpawnRate.getSelection() }, - { RoleId.Jackal, CustomOptionHolder.jackalSpawnRate.getSelection() }, - { RoleId.Sidekick, CustomOptionHolder.jackalSpawnRate.getSelection() }, - { RoleId.Jester, CustomOptionHolder.jesterSpawnRate.getSelection() }, - { RoleId.Juggernaut, CustomOptionHolder.juggernautSpawnRate.getSelection() }, - { RoleId.Lawyer, CustomOptionHolder.lawyerSpawnRate.getSelection() }, - { RoleId.PartTimer, CustomOptionHolder.partTimerSpawnRate.getSelection() }, - { RoleId.Pavlovsowner, CustomOptionHolder.pavlovsownerSpawnRate.getSelection() }, - { RoleId.Pavlovsdogs, CustomOptionHolder.pavlovsownerSpawnRate.getSelection() }, - { RoleId.Survivor, CustomOptionHolder.survivorSpawnRate.getSelection() }, - { RoleId.Swooper, CustomOptionHolder.swooperSpawnRate.getSelection() }, - { RoleId.Thief, CustomOptionHolder.thiefSpawnRate.getSelection() }, - { RoleId.Vulture, CustomOptionHolder.vultureSpawnRate.getSelection() }, - { RoleId.Werewolf, CustomOptionHolder.werewolfSpawnRate.getSelection() }, - { RoleId.Pursuer, CustomOptionHolder.lawyerSpawnRate.getSelection() + CustomOptionHolder.executionerSpawnRate.getSelection() }, - - { RoleId.Lover, CustomOptionHolder.modifierLover.getSelection() }, - { RoleId.Aftermath, CustomOptionHolder.modifierAftermath.getSelection() }, - { RoleId.AntiTeleport, CustomOptionHolder.modifierAntiTeleport.getSelection() }, - { RoleId.Assassin, CustomOptionHolder.modifierAssassin.getSelection() }, - { RoleId.Bait, CustomOptionHolder.modifierBait.getSelection() }, - { RoleId.Blind, CustomOptionHolder.modifierBlind.getSelection() }, - { RoleId.Bloody, CustomOptionHolder.modifierBloody.getSelection() }, - { RoleId.ButtonBarry, CustomOptionHolder.modifierButtonBarry.getSelection() }, - { RoleId.Chameleon, CustomOptionHolder.modifierChameleon.getSelection() }, - { RoleId.Cursed, CustomOptionHolder.modifierCursed.getSelection() }, - { RoleId.Disperser, CustomOptionHolder.modifierDisperser.getSelection() }, - { RoleId.Flash, CustomOptionHolder.modifierFlash.getSelection() }, - { RoleId.Giant, CustomOptionHolder.modifierGiant.getSelection() }, - { RoleId.Indomitable, CustomOptionHolder.modifierIndomitable.getSelection() }, - { RoleId.Invert, CustomOptionHolder.modifierInvert.getSelection() }, - { RoleId.LastImpostor, CustomOptionHolder.modifierLastImpostor.getSelection() }, - { RoleId.Mini, CustomOptionHolder.modifierMini.getSelection() }, - { RoleId.Multitasker, CustomOptionHolder.modifierMultitasker.getSelection() }, - { RoleId.Radar, CustomOptionHolder.modifierRadar.getSelection() }, - { RoleId.Shifter, CustomOptionHolder.modifierShifter.getSelection() }, - { RoleId.Slueth, CustomOptionHolder.modifierSlueth.getSelection() }, - { RoleId.Specoality, CustomOptionHolder.modifierSpecoality.getSelection() }, - { RoleId.Tiebreaker, CustomOptionHolder.modifierTieBreaker.getSelection() }, - { RoleId.Torch, CustomOptionHolder.modifierTorch.getSelection() }, - { RoleId.Tunneler, CustomOptionHolder.modifierTunneler.getSelection() }, - { RoleId.Vip, CustomOptionHolder.modifierVip.getSelection() }, - { RoleId.Watcher, CustomOptionHolder.modifierWatcher.getSelection()} - }); - } -} diff --git a/TheOtherRoles/Roles/RoleHelpers.cs b/TheOtherRoles/Roles/RoleHelpers.cs index b29ddfb5..01c4b13f 100644 --- a/TheOtherRoles/Roles/RoleHelpers.cs +++ b/TheOtherRoles/Roles/RoleHelpers.cs @@ -1,5 +1,10 @@ using System; +using System.Collections.Generic; +using System.Linq; +using MonoMod.Utils; +using TheOtherRoles.CustomGameModes; using TheOtherRoles.Utilities; +using UnityEngine.Playables; using Random = System.Random; namespace TheOtherRoles.Roles; @@ -29,4 +34,246 @@ public static bool CanMultipleShots(PlayerControl dyingTarget) Doomsayer.CanShoot; } + public static Dictionary blockedRolePairings = new(); + + public static void blockRole() + { + blockedRolePairings.Clear(); + + blockedRolePairings.Add((byte)RoleId.Vampire, [(byte)RoleId.Warlock]); + blockedRolePairings.Add((byte)RoleId.Witch, [(byte)RoleId.Warlock]); + blockedRolePairings.Add((byte)RoleId.Warlock, [(byte)RoleId.Vampire]); + + if (CustomOptionHolder.pavlovsownerAndJackalAsWell.getBool()) + { + blockedRolePairings.Add((byte)RoleId.Jackal, [(byte)RoleId.Pavlovsowner]); + blockedRolePairings.Add((byte)RoleId.Pavlovsowner, [(byte)RoleId.Jackal]); + } + if (Executioner.promotesToLawyer) + { + blockedRolePairings.Add((byte)RoleId.Executioner, [(byte)RoleId.Lawyer]); + blockedRolePairings.Add((byte)RoleId.Lawyer, [(byte)RoleId.Executioner]); + } + + blockedRolePairings.Add((byte)RoleId.Vulture, [(byte)RoleId.Cleaner]); + blockedRolePairings.Add((byte)RoleId.Cleaner, [(byte)RoleId.Vulture]); + + blockedRolePairings.Add((byte)RoleId.Ninja, [(byte)RoleId.Swooper]); + blockedRolePairings.Add((byte)RoleId.Swooper, [(byte)RoleId.Ninja]); + } + + public static Dictionary RoleIsEnable = new(); + + public static void ResetRoleSelection() + { + RoleIsEnable.Clear(); + RoleIsEnable.AddRange(new() + { + { RoleId.Sheriff, CustomOptionHolder.sheriffSpawnRate.getSelection() }, + { RoleId.Deputy, CustomOptionHolder.deputySpawnRate.getSelection() }, + { RoleId.BodyGuard, CustomOptionHolder.bodyGuardSpawnRate.getSelection() }, + { RoleId.Balancer, CustomOptionHolder.balancerSpawnRate.getSelection() }, + { RoleId.Detective, CustomOptionHolder.detectiveSpawnRate.getSelection() }, + { RoleId.Engineer, CustomOptionHolder.engineerSpawnRate.getSelection() }, + { RoleId.Hacker, CustomOptionHolder.hackerSpawnRate.getSelection() }, + { RoleId.InfoSleuth, CustomOptionHolder.infoSleuthSpawnRate.getSelection() }, + { RoleId.Jumper, CustomOptionHolder.jumperSpawnRate.getSelection() }, + { RoleId.Mayor, CustomOptionHolder.mayorSpawnRate.getSelection() }, + { RoleId.Medic, CustomOptionHolder.medicSpawnRate.getSelection() }, + { RoleId.Medium, CustomOptionHolder.mediumSpawnRate.getSelection() }, + { RoleId.Portalmaker, CustomOptionHolder.portalmakerSpawnRate.getSelection() }, + { RoleId.Prophet, CustomOptionHolder.prophetSpawnRate.getSelection() }, + { RoleId.Prosecutor, CustomOptionHolder.prosecutorSpawnRate.getSelection() }, + { RoleId.SecurityGuard, CustomOptionHolder.securityGuardSpawnRate.getSelection() }, + { RoleId.Seer, CustomOptionHolder.seerSpawnRate.getSelection() }, + { RoleId.Snitch, CustomOptionHolder.snitchSpawnRate.getSelection() }, + { RoleId.Spy, CustomOptionHolder.spySpawnRate.getSelection() }, + { RoleId.Swapper, CustomOptionHolder.swapperSpawnRate.getSelection() }, + { RoleId.TimeMaster, CustomOptionHolder.timeMasterSpawnRate.getSelection() }, + { RoleId.Tracker, CustomOptionHolder.trackerSpawnRate.getSelection() }, + { RoleId.Trapper, CustomOptionHolder.trapperSpawnRate.getSelection() }, + { RoleId.Veteran, CustomOptionHolder.veteranSpawnRate.getSelection() }, + { RoleId.Vigilante, CustomOptionHolder.guesserSpawnRate.getSelection() }, + + { RoleId.Blackmailer, CustomOptionHolder.blackmailerSpawnRate.getSelection() }, + { RoleId.Bomber, CustomOptionHolder.bomberSpawnRate.getSelection() }, + { RoleId.BountyHunter, CustomOptionHolder.bountyHunterSpawnRate.getSelection() }, + { RoleId.Butcher, CustomOptionHolder.butcherSpawnRate.getSelection() }, + { RoleId.Camouflager, CustomOptionHolder.camouflagerSpawnRate.getSelection() }, + { RoleId.Cleaner, CustomOptionHolder.cleanerSpawnRate.getSelection() }, + { RoleId.Eraser, CustomOptionHolder.eraserSpawnRate.getSelection() }, + { RoleId.Escapist, CustomOptionHolder.escapistSpawnRate.getSelection() }, + { RoleId.EvilTrapper, CustomOptionHolder.evilTrapperSpawnRate.getSelection() }, + { RoleId.Gambler, CustomOptionHolder.gamblerSpawnRate.getSelection() }, + { RoleId.Mimic, CustomOptionHolder.mimicSpawnRate.getSelection() }, + { RoleId.Miner, CustomOptionHolder.minerSpawnRate.getSelection() }, + { RoleId.Morphling, CustomOptionHolder.morphlingSpawnRate.getSelection() }, + { RoleId.Ninja, CustomOptionHolder.ninjaSpawnRate.getSelection() }, + { RoleId.Poucher, CustomOptionHolder.poucherSpawnRate.getSelection() }, + { RoleId.Terrorist, CustomOptionHolder.terroristSpawnRate.getSelection() }, + { RoleId.Trickster, CustomOptionHolder.tricksterSpawnRate.getSelection() }, + { RoleId.Undertaker, CustomOptionHolder.undertakerSpawnRate.getSelection() }, + { RoleId.Vampire, CustomOptionHolder.vampireSpawnRate.getSelection() }, + { RoleId.Warlock, CustomOptionHolder.warlockSpawnRate.getSelection() }, + { RoleId.Witch, CustomOptionHolder.witchSpawnRate.getSelection() }, + { RoleId.Yoyo, CustomOptionHolder.yoyoSpawnRate.getSelection() }, + { RoleId.Grenadier, CustomOptionHolder.grenadierSpawnRate.getSelection() }, + + { RoleId.Akujo, CustomOptionHolder.akujoSpawnRate.getSelection() }, + { RoleId.Amnisiac, CustomOptionHolder.amnisiacSpawnRate.getSelection() }, + { RoleId.Arsonist, CustomOptionHolder.arsonistSpawnRate.getSelection() }, + { RoleId.Doomsayer, CustomOptionHolder.doomsayerSpawnRate.getSelection() }, + { RoleId.Executioner, CustomOptionHolder.executionerSpawnRate.getSelection() }, + { RoleId.Jackal, CustomOptionHolder.jackalSpawnRate.getSelection() }, + { RoleId.Sidekick, CustomOptionHolder.jackalSpawnRate.getSelection() }, + { RoleId.Jester, CustomOptionHolder.jesterSpawnRate.getSelection() }, + { RoleId.Juggernaut, CustomOptionHolder.juggernautSpawnRate.getSelection() }, + { RoleId.Lawyer, CustomOptionHolder.lawyerSpawnRate.getSelection() }, + { RoleId.PartTimer, CustomOptionHolder.partTimerSpawnRate.getSelection() }, + { RoleId.Pavlovsowner, CustomOptionHolder.pavlovsownerSpawnRate.getSelection() }, + { RoleId.Pavlovsdogs, CustomOptionHolder.pavlovsownerSpawnRate.getSelection() }, + { RoleId.Survivor, CustomOptionHolder.survivorSpawnRate.getSelection() }, + { RoleId.Swooper, CustomOptionHolder.swooperSpawnRate.getSelection() }, + { RoleId.Thief, CustomOptionHolder.thiefSpawnRate.getSelection() }, + { RoleId.Vulture, CustomOptionHolder.vultureSpawnRate.getSelection() }, + { RoleId.Werewolf, CustomOptionHolder.werewolfSpawnRate.getSelection() }, + { RoleId.Pursuer, CustomOptionHolder.lawyerSpawnRate.getSelection() + CustomOptionHolder.executionerSpawnRate.getSelection() }, + + { RoleId.Lover, CustomOptionHolder.modifierLover.getSelection() }, + { RoleId.Aftermath, CustomOptionHolder.modifierAftermath.getSelection() }, + { RoleId.AntiTeleport, CustomOptionHolder.modifierAntiTeleport.getSelection() }, + { RoleId.Assassin, CustomOptionHolder.modifierAssassin.getSelection() }, + { RoleId.Bait, CustomOptionHolder.modifierBait.getSelection() }, + { RoleId.Blind, CustomOptionHolder.modifierBlind.getSelection() }, + { RoleId.Bloody, CustomOptionHolder.modifierBloody.getSelection() }, + { RoleId.ButtonBarry, CustomOptionHolder.modifierButtonBarry.getSelection() }, + { RoleId.Chameleon, CustomOptionHolder.modifierChameleon.getSelection() }, + { RoleId.Cursed, CustomOptionHolder.modifierCursed.getSelection() }, + { RoleId.Disperser, CustomOptionHolder.modifierDisperser.getSelection() }, + { RoleId.Flash, CustomOptionHolder.modifierFlash.getSelection() }, + { RoleId.Giant, CustomOptionHolder.modifierGiant.getSelection() }, + { RoleId.Indomitable, CustomOptionHolder.modifierIndomitable.getSelection() }, + { RoleId.Invert, CustomOptionHolder.modifierInvert.getSelection() }, + { RoleId.LastImpostor, CustomOptionHolder.modifierLastImpostor.getSelection() }, + { RoleId.Mini, CustomOptionHolder.modifierMini.getSelection() }, + { RoleId.Multitasker, CustomOptionHolder.modifierMultitasker.getSelection() }, + { RoleId.Radar, CustomOptionHolder.modifierRadar.getSelection() }, + { RoleId.Shifter, CustomOptionHolder.modifierShifter.getSelection() }, + { RoleId.Slueth, CustomOptionHolder.modifierSlueth.getSelection() }, + { RoleId.Specoality, CustomOptionHolder.modifierSpecoality.getSelection() }, + { RoleId.Tiebreaker, CustomOptionHolder.modifierTieBreaker.getSelection() }, + { RoleId.Torch, CustomOptionHolder.modifierTorch.getSelection() }, + { RoleId.Tunneler, CustomOptionHolder.modifierTunneler.getSelection() }, + { RoleId.Vip, CustomOptionHolder.modifierVip.getSelection() }, + { RoleId.Watcher, CustomOptionHolder.modifierWatcher.getSelection()} + }); + } + + public static void clearAndReloadRoles() + { + Vigilante.clearAndReload(); + Jester.clearAndReload(); + Mayor.clearAndReload(); + Prosecutor.clearAndReload(); + Portalmaker.clearAndReload(); + Poucher.clearAndReload(); + Mimic.clearAndReload(); + Engineer.clearAndReload(); + Sheriff.clearAndReload(); + InfoSleuth.clearAndReload(); + Gambler.clearAndReload(); + Butcher.clearAndReload(); + Deputy.clearAndReload(); + Amnisiac.clearAndReload(); + Detective.clearAndReload(); + Werewolf.clearAndReload(); + TimeMaster.clearAndReload(); + BodyGuard.clearAndReload(); + Veteran.clearAndReload(); + Medic.clearAndReload(); + Shifter.clearAndReload(); + Swapper.clearAndReload(); + Lovers.clearAndReload(); + Seer.clearAndReload(); + Morphling.clearAndReload(); + Camouflager.clearAndReload(); + Hacker.clearAndReload(); + Tracker.clearAndReload(); + Vampire.clearAndReload(); + Snitch.clearAndReload(); + Jackal.clearAndReload(); + Sidekick.clearAndReload(); + Pavlovsdogs.clearAndReload(); + Eraser.clearAndReload(); + Spy.clearAndReload(); + Trickster.clearAndReload(); + Cleaner.clearAndReload(); + Undertaker.clearAndReload(); + Warlock.clearAndReload(); + SecurityGuard.clearAndReload(); + Arsonist.clearAndReload(); + BountyHunter.clearAndReload(); + Vulture.clearAndReload(); + Medium.clearAndReload(); + Bomber.clearAndReload(); + Lawyer.clearAndReload(); + Executioner.clearAndReload(); + Pursuer.clearAndReload(); + Witch.clearAndReload(); + Jumper.clearAndReload(); + Prophet.clearAndReload(); + Escapist.clearAndReload(); + Ninja.clearAndReload(); + Blackmailer.clearAndReload(); + Thief.clearAndReload(); + Miner.clearAndReload(); + Trapper.clearAndReload(); + Terrorist.clearAndReload(); + Juggernaut.clearAndReload(); + Doomsayer.clearAndReload(); + Swooper.clearAndReload(); + Balancer.clearAndReload(); + Akujo.clearAndReload(); + Yoyo.clearAndReload(); + EvilTrapper.clearAndReload(); + Survivor.clearAndReload(); + PartTimer.clearAndReload(); + Grenadier.clearAndReload(); + + // Modifier + Assassin.clearAndReload(); + Aftermath.clearAndReload(); + Bait.clearAndReload(); + Bloody.clearAndReload(); + AntiTeleport.clearAndReload(); + Tiebreaker.clearAndReload(); + Sunglasses.clearAndReload(); + Torch.clearAndReload(); + Flash.clearAndReload(); + Blind.clearAndReload(); + Watcher.clearAndReload(); + Radar.clearAndReload(); + Tunneler.clearAndReload(); + Multitasker.clearAndReload(); + Disperser.clearAndReload(); + Mini.clearAndReload(); + Giant.clearAndReload(); + Indomitable.clearAndReload(); + Slueth.clearAndReload(); + Cursed.clearAndReload(); + Vip.clearAndReload(); + Invert.clearAndReload(); + Chameleon.clearAndReload(); + ButtonBarry.clearAndReload(); + LastImpostor.clearAndReload(); + Specoality.clearAndReload(); + + // Gamemodes + HandleGuesser.clearAndReload(); + HideNSeek.clearAndReload(); + PropHunt.clearAndReload(); + + blockRole(); + ResetRoleSelection(); + } } \ No newline at end of file diff --git a/TheOtherRoles/Roles/RoleInfo.cs b/TheOtherRoles/Roles/RoleInfo.cs index e73c1a48..e460864e 100644 --- a/TheOtherRoles/Roles/RoleInfo.cs +++ b/TheOtherRoles/Roles/RoleInfo.cs @@ -7,7 +7,7 @@ namespace TheOtherRoles.Roles; -public class RoleInfo(string name, Color color, RoleId roleId, RoleTeam roleTeam, bool isGuessable = false) +public class RoleInfo(string name, Color color, RoleId roleId, RoleType roleTeam, bool isGuessable = false) { public string Name => getString(nameKey); public string IntroDescription => getString(nameKey + "IntroDesc"); @@ -16,117 +16,117 @@ public class RoleInfo(string name, Color color, RoleId roleId, RoleTeam roleTeam public Color color = color; public RoleId roleId = roleId; - public RoleTeam roleTeam = roleTeam; + public RoleType roleTeam = roleTeam; public bool isGuessable = isGuessable; private readonly string nameKey = name; - public static RoleInfo impostor = new("Impostor", Palette.ImpostorRed, RoleId.Impostor, RoleTeam.Impostor); - public static RoleInfo morphling = new("Morphling", Morphling.color, RoleId.Morphling, RoleTeam.Impostor); - public static RoleInfo bomber = new("Bomber", Bomber.color, RoleId.Bomber, RoleTeam.Impostor); - public static RoleInfo poucher = new("Poucher", Poucher.color, RoleId.Poucher, RoleTeam.Impostor); - public static RoleInfo butcher = new("Butcher", Eraser.color, RoleId.Butcher, RoleTeam.Impostor); - public static RoleInfo mimic = new("Mimic", Mimic.color, RoleId.Mimic, RoleTeam.Impostor); - public static RoleInfo camouflager = new("Camouflager", Camouflager.color, RoleId.Camouflager, RoleTeam.Impostor); - public static RoleInfo miner = new("Miner", Miner.color, RoleId.Miner, RoleTeam.Impostor); - public static RoleInfo eraser = new("Eraser", Eraser.color, RoleId.Eraser, RoleTeam.Impostor); - public static RoleInfo vampire = new("Vampire", Vampire.color, RoleId.Vampire, RoleTeam.Impostor); - public static RoleInfo cleaner = new("Cleaner", Cleaner.color, RoleId.Cleaner, RoleTeam.Impostor); - public static RoleInfo undertaker = new("Undertaker", Undertaker.color, RoleId.Undertaker, RoleTeam.Impostor); - public static RoleInfo escapist = new("Escapist", Escapist.color, RoleId.Escapist, RoleTeam.Impostor); - public static RoleInfo warlock = new("Warlock", Warlock.color, RoleId.Warlock, RoleTeam.Impostor); - public static RoleInfo trickster = new("Trickster", Trickster.color, RoleId.Trickster, RoleTeam.Impostor); - public static RoleInfo bountyHunter = new("BountyHunter", BountyHunter.color, RoleId.BountyHunter, RoleTeam.Impostor); - public static RoleInfo terrorist = new("Terrorist", Terrorist.color, RoleId.Terrorist, RoleTeam.Impostor); - public static RoleInfo blackmailer = new("Blackmailer", Blackmailer.color, RoleId.Blackmailer, RoleTeam.Impostor); - public static RoleInfo witch = new("Witch", Witch.color, RoleId.Witch, RoleTeam.Impostor); - public static RoleInfo ninja = new("Ninja", Ninja.color, RoleId.Ninja, RoleTeam.Impostor); - public static RoleInfo yoyo = new("Yoyo", Yoyo.color, RoleId.Yoyo, RoleTeam.Impostor); - public static RoleInfo evilTrapper = new("EvilTrapper", EvilTrapper.color, RoleId.EvilTrapper, RoleTeam.Impostor); - public static RoleInfo gambler = new("Gambler", Gambler.color, RoleId.Gambler, RoleTeam.Impostor); - public static RoleInfo grenadier = new("Grenadier", Grenadier.color, RoleId.Grenadier, RoleTeam.Impostor); + public static RoleInfo impostor = new("Impostor", Palette.ImpostorRed, RoleId.Impostor, RoleType.Impostor); + public static RoleInfo morphling = new("Morphling", Morphling.color, RoleId.Morphling, RoleType.Impostor); + public static RoleInfo bomber = new("Bomber", Bomber.color, RoleId.Bomber, RoleType.Impostor); + public static RoleInfo poucher = new("Poucher", Poucher.color, RoleId.Poucher, RoleType.Impostor); + public static RoleInfo butcher = new("Butcher", Eraser.color, RoleId.Butcher, RoleType.Impostor); + public static RoleInfo mimic = new("Mimic", Mimic.color, RoleId.Mimic, RoleType.Impostor); + public static RoleInfo camouflager = new("Camouflager", Camouflager.color, RoleId.Camouflager, RoleType.Impostor); + public static RoleInfo miner = new("Miner", Miner.color, RoleId.Miner, RoleType.Impostor); + public static RoleInfo eraser = new("Eraser", Eraser.color, RoleId.Eraser, RoleType.Impostor); + public static RoleInfo vampire = new("Vampire", Vampire.color, RoleId.Vampire, RoleType.Impostor); + public static RoleInfo cleaner = new("Cleaner", Cleaner.color, RoleId.Cleaner, RoleType.Impostor); + public static RoleInfo undertaker = new("Undertaker", Undertaker.color, RoleId.Undertaker, RoleType.Impostor); + public static RoleInfo escapist = new("Escapist", Escapist.color, RoleId.Escapist, RoleType.Impostor); + public static RoleInfo warlock = new("Warlock", Warlock.color, RoleId.Warlock, RoleType.Impostor); + public static RoleInfo trickster = new("Trickster", Trickster.color, RoleId.Trickster, RoleType.Impostor); + public static RoleInfo bountyHunter = new("BountyHunter", BountyHunter.color, RoleId.BountyHunter, RoleType.Impostor); + public static RoleInfo terrorist = new("Terrorist", Terrorist.color, RoleId.Terrorist, RoleType.Impostor); + public static RoleInfo blackmailer = new("Blackmailer", Blackmailer.color, RoleId.Blackmailer, RoleType.Impostor); + public static RoleInfo witch = new("Witch", Witch.color, RoleId.Witch, RoleType.Impostor); + public static RoleInfo ninja = new("Ninja", Ninja.color, RoleId.Ninja, RoleType.Impostor); + public static RoleInfo yoyo = new("Yoyo", Yoyo.color, RoleId.Yoyo, RoleType.Impostor); + public static RoleInfo evilTrapper = new("EvilTrapper", EvilTrapper.color, RoleId.EvilTrapper, RoleType.Impostor); + public static RoleInfo gambler = new("Gambler", Gambler.color, RoleId.Gambler, RoleType.Impostor); + public static RoleInfo grenadier = new("Grenadier", Grenadier.color, RoleId.Grenadier, RoleType.Impostor); - public static RoleInfo survivor = new("Survivor", Survivor.color, RoleId.Survivor, RoleTeam.Neutral); - public static RoleInfo amnisiac = new("Amnisiac", Amnisiac.color, RoleId.Amnisiac, RoleTeam.Neutral); - public static RoleInfo jester = new("Jester", Jester.color, RoleId.Jester, RoleTeam.Neutral); - public static RoleInfo vulture = new("Vulture", Vulture.color, RoleId.Vulture, RoleTeam.Neutral); - public static RoleInfo lawyer = new("Lawyer", Lawyer.color, RoleId.Lawyer, RoleTeam.Neutral); - public static RoleInfo executioner = new("Executioner", Executioner.color, RoleId.Executioner, RoleTeam.Neutral); - public static RoleInfo pursuer = new("Pursuer", Pursuer.color, RoleId.Pursuer, RoleTeam.Neutral); - public static RoleInfo partTimer = new("PartTimer", PartTimer.color, RoleId.PartTimer, RoleTeam.Neutral); - public static RoleInfo jackal = new("Jackal", Jackal.color, RoleId.Jackal, RoleTeam.Neutral); - public static RoleInfo sidekick = new("Sidekick", Sidekick.color, RoleId.Sidekick, RoleTeam.Neutral); - public static RoleInfo pavlovsowner = new("Pavlovsowner", Pavlovsdogs.color, RoleId.Pavlovsowner, RoleTeam.Neutral); - public static RoleInfo pavlovsdogs = new("Pavlovsdogs", Pavlovsdogs.color, RoleId.Pavlovsdogs, RoleTeam.Neutral); - public static RoleInfo swooper = new("Swooper", Swooper.color, RoleId.Swooper, RoleTeam.Neutral); - public static RoleInfo arsonist = new("Arsonist", Arsonist.color, RoleId.Arsonist, RoleTeam.Neutral); - public static RoleInfo werewolf = new("Werewolf", Werewolf.color, RoleId.Werewolf, RoleTeam.Neutral); - public static RoleInfo thief = new("Thief", Thief.color, RoleId.Thief, RoleTeam.Neutral); - public static RoleInfo juggernaut = new("Juggernaut", Juggernaut.color, RoleId.Juggernaut, RoleTeam.Neutral); - public static RoleInfo doomsayer = new("Doomsayer", Doomsayer.color, RoleId.Doomsayer, RoleTeam.Neutral); - public static RoleInfo akujo = new("Akujo", Akujo.color, RoleId.Akujo, RoleTeam.Neutral); + public static RoleInfo survivor = new("Survivor", Survivor.color, RoleId.Survivor, RoleType.Neutral); + public static RoleInfo amnisiac = new("Amnisiac", Amnisiac.color, RoleId.Amnisiac, RoleType.Neutral); + public static RoleInfo jester = new("Jester", Jester.color, RoleId.Jester, RoleType.Neutral); + public static RoleInfo vulture = new("Vulture", Vulture.color, RoleId.Vulture, RoleType.Neutral); + public static RoleInfo lawyer = new("Lawyer", Lawyer.color, RoleId.Lawyer, RoleType.Neutral); + public static RoleInfo executioner = new("Executioner", Executioner.color, RoleId.Executioner, RoleType.Neutral); + public static RoleInfo pursuer = new("Pursuer", Pursuer.color, RoleId.Pursuer, RoleType.Neutral); + public static RoleInfo partTimer = new("PartTimer", PartTimer.color, RoleId.PartTimer, RoleType.Neutral); + public static RoleInfo jackal = new("Jackal", Jackal.color, RoleId.Jackal, RoleType.Neutral); + public static RoleInfo sidekick = new("Sidekick", Sidekick.color, RoleId.Sidekick, RoleType.Neutral); + public static RoleInfo pavlovsowner = new("Pavlovsowner", Pavlovsdogs.color, RoleId.Pavlovsowner, RoleType.Neutral); + public static RoleInfo pavlovsdogs = new("Pavlovsdogs", Pavlovsdogs.color, RoleId.Pavlovsdogs, RoleType.Neutral); + public static RoleInfo swooper = new("Swooper", Swooper.color, RoleId.Swooper, RoleType.Neutral); + public static RoleInfo arsonist = new("Arsonist", Arsonist.color, RoleId.Arsonist, RoleType.Neutral); + public static RoleInfo werewolf = new("Werewolf", Werewolf.color, RoleId.Werewolf, RoleType.Neutral); + public static RoleInfo thief = new("Thief", Thief.color, RoleId.Thief, RoleType.Neutral); + public static RoleInfo juggernaut = new("Juggernaut", Juggernaut.color, RoleId.Juggernaut, RoleType.Neutral); + public static RoleInfo doomsayer = new("Doomsayer", Doomsayer.color, RoleId.Doomsayer, RoleType.Neutral); + public static RoleInfo akujo = new("Akujo", Akujo.color, RoleId.Akujo, RoleType.Neutral); - public static RoleInfo crewmate = new("Crewmate", Color.white, RoleId.Crewmate, RoleTeam.Crewmate); - public static RoleInfo vigilante = new("Vigilante", Vigilante.color, RoleId.Vigilante, RoleTeam.Crewmate); - public static RoleInfo mayor = new("Mayor", Mayor.color, RoleId.Mayor, RoleTeam.Crewmate); - public static RoleInfo prosecutor = new("Prosecutor", Prosecutor.color, RoleId.Prosecutor, RoleTeam.Crewmate); - public static RoleInfo portalmaker = new("Portalmaker", Portalmaker.color, RoleId.Portalmaker, RoleTeam.Crewmate); - public static RoleInfo engineer = new("Engineer", Engineer.color, RoleId.Engineer, RoleTeam.Crewmate); - public static RoleInfo sheriff = new("Sheriff", Sheriff.color, RoleId.Sheriff, RoleTeam.Crewmate); - public static RoleInfo deputy = new("Deputy", Deputy.color, RoleId.Deputy, RoleTeam.Crewmate); - public static RoleInfo bodyguard = new("BodyGuard", BodyGuard.color, RoleId.BodyGuard, RoleTeam.Crewmate); - public static RoleInfo jumper = new("Jumper", Jumper.color, RoleId.Jumper, RoleTeam.Crewmate); - public static RoleInfo detective = new("Detective", Detective.color, RoleId.Detective, RoleTeam.Crewmate); - public static RoleInfo timeMaster = new("TimeMaster", TimeMaster.color, RoleId.TimeMaster, RoleTeam.Crewmate); - public static RoleInfo veteran = new("Veteran", Veteran.color, RoleId.Veteran, RoleTeam.Crewmate); - public static RoleInfo medic = new("Medic", Medic.color, RoleId.Medic, RoleTeam.Crewmate); - public static RoleInfo swapper = new("Swapper", Swapper.color, RoleId.Swapper, RoleTeam.Crewmate); - public static RoleInfo seer = new("Seer", Seer.color, RoleId.Seer, RoleTeam.Crewmate); - public static RoleInfo hacker = new("Hacker", Hacker.color, RoleId.Hacker, RoleTeam.Crewmate); - public static RoleInfo tracker = new("Tracker", Tracker.color, RoleId.Tracker, RoleTeam.Crewmate); - public static RoleInfo snitch = new("Snitch", Snitch.color, RoleId.Snitch, RoleTeam.Crewmate); - public static RoleInfo prophet = new("Prophet", Prophet.color, RoleId.Prophet, RoleTeam.Crewmate); - public static RoleInfo infoSleuth = new("InfoSleuth", InfoSleuth.color, RoleId.InfoSleuth, RoleTeam.Crewmate); - public static RoleInfo spy = new("Spy", Spy.color, RoleId.Spy, RoleTeam.Crewmate); - public static RoleInfo securityGuard = new("SecurityGuard", SecurityGuard.color, RoleId.SecurityGuard, RoleTeam.Crewmate); - public static RoleInfo medium = new("Medium", Medium.color, RoleId.Medium, RoleTeam.Crewmate); - public static RoleInfo trapper = new("Trapper", Trapper.color, RoleId.Trapper, RoleTeam.Crewmate); - public static RoleInfo balancer = new("Balancer", Balancer.color, RoleId.Balancer, RoleTeam.Crewmate); + public static RoleInfo crewmate = new("Crewmate", Color.white, RoleId.Crewmate, RoleType.Crewmate); + public static RoleInfo vigilante = new("Vigilante", Vigilante.color, RoleId.Vigilante, RoleType.Crewmate); + public static RoleInfo mayor = new("Mayor", Mayor.color, RoleId.Mayor, RoleType.Crewmate); + public static RoleInfo prosecutor = new("Prosecutor", Prosecutor.color, RoleId.Prosecutor, RoleType.Crewmate); + public static RoleInfo portalmaker = new("Portalmaker", Portalmaker.color, RoleId.Portalmaker, RoleType.Crewmate); + public static RoleInfo engineer = new("Engineer", Engineer.color, RoleId.Engineer, RoleType.Crewmate); + public static RoleInfo sheriff = new("Sheriff", Sheriff.color, RoleId.Sheriff, RoleType.Crewmate); + public static RoleInfo deputy = new("Deputy", Deputy.color, RoleId.Deputy, RoleType.Crewmate); + public static RoleInfo bodyguard = new("BodyGuard", BodyGuard.color, RoleId.BodyGuard, RoleType.Crewmate); + public static RoleInfo jumper = new("Jumper", Jumper.color, RoleId.Jumper, RoleType.Crewmate); + public static RoleInfo detective = new("Detective", Detective.color, RoleId.Detective, RoleType.Crewmate); + public static RoleInfo timeMaster = new("TimeMaster", TimeMaster.color, RoleId.TimeMaster, RoleType.Crewmate); + public static RoleInfo veteran = new("Veteran", Veteran.color, RoleId.Veteran, RoleType.Crewmate); + public static RoleInfo medic = new("Medic", Medic.color, RoleId.Medic, RoleType.Crewmate); + public static RoleInfo swapper = new("Swapper", Swapper.color, RoleId.Swapper, RoleType.Crewmate); + public static RoleInfo seer = new("Seer", Seer.color, RoleId.Seer, RoleType.Crewmate); + public static RoleInfo hacker = new("Hacker", Hacker.color, RoleId.Hacker, RoleType.Crewmate); + public static RoleInfo tracker = new("Tracker", Tracker.color, RoleId.Tracker, RoleType.Crewmate); + public static RoleInfo snitch = new("Snitch", Snitch.color, RoleId.Snitch, RoleType.Crewmate); + public static RoleInfo prophet = new("Prophet", Prophet.color, RoleId.Prophet, RoleType.Crewmate); + public static RoleInfo infoSleuth = new("InfoSleuth", InfoSleuth.color, RoleId.InfoSleuth, RoleType.Crewmate); + public static RoleInfo spy = new("Spy", Spy.color, RoleId.Spy, RoleType.Crewmate); + public static RoleInfo securityGuard = new("SecurityGuard", SecurityGuard.color, RoleId.SecurityGuard, RoleType.Crewmate); + public static RoleInfo medium = new("Medium", Medium.color, RoleId.Medium, RoleType.Crewmate); + public static RoleInfo trapper = new("Trapper", Trapper.color, RoleId.Trapper, RoleType.Crewmate); + public static RoleInfo balancer = new("Balancer", Balancer.color, RoleId.Balancer, RoleType.Crewmate); // Modifier - public static RoleInfo assassin = new("Assassin", Assassin.color, RoleId.Assassin, RoleTeam.Modifier); - public static RoleInfo lover = new("Lover", Lovers.color, RoleId.Lover, RoleTeam.Modifier, true); - public static RoleInfo disperser = new("Disperser", Disperser.color, RoleId.Disperser, RoleTeam.Modifier, true); - public static RoleInfo specoality = new("Specoality", Specoality.color, RoleId.Specoality, RoleTeam.Modifier); - public static RoleInfo poucherModifier = new("Poucher", Poucher.color, RoleId.PoucherModifier, RoleTeam.Modifier); - public static RoleInfo lastImpostor = new("LastImpostor", LastImpostor.color, RoleId.LastImpostor, RoleTeam.Modifier); - public static RoleInfo bloody = new("Bloody", Color.yellow, RoleId.Bloody, RoleTeam.Modifier, true); - public static RoleInfo antiTeleport = new("AntiTeleport", Color.yellow, RoleId.AntiTeleport, RoleTeam.Modifier); - public static RoleInfo tiebreaker = new("TieBreaker", Color.yellow, RoleId.Tiebreaker, RoleTeam.Modifier, true); - public static RoleInfo aftermath = new("Aftermath", Color.yellow, RoleId.Aftermath, RoleTeam.Modifier, true); - public static RoleInfo bait = new("Bait", Color.yellow, RoleId.Bait, RoleTeam.Modifier, true); - public static RoleInfo sunglasses = new("Sunglasses", Color.yellow, RoleId.Sunglasses, RoleTeam.Modifier); - public static RoleInfo torch = new("Torch", Color.yellow, RoleId.Torch, RoleTeam.Modifier, true); - public static RoleInfo flash = new("Flash", Color.yellow, RoleId.Flash, RoleTeam.Modifier); - public static RoleInfo multitasker = new("Multitasker", Color.yellow, RoleId.Multitasker, RoleTeam.Modifier, true); - public static RoleInfo giant = new("Giant", Color.yellow, RoleId.Giant, RoleTeam.Modifier); - public static RoleInfo mini = new("Mini", Color.yellow, RoleId.Mini, RoleTeam.Modifier); - public static RoleInfo vip = new("Vip", Color.yellow, RoleId.Vip, RoleTeam.Modifier, true); - public static RoleInfo indomitable = new("Indomitable", Color.yellow, RoleId.Indomitable, RoleTeam.Modifier); - public static RoleInfo slueth = new("Slueth", Color.yellow, RoleId.Slueth, RoleTeam.Modifier, true); - public static RoleInfo cursed = new("Cursed", Color.yellow, RoleId.Cursed, RoleTeam.Modifier, true); - public static RoleInfo invert = new("Invert", Color.yellow, RoleId.Invert, RoleTeam.Modifier); - public static RoleInfo blind = new("Blind", Color.yellow, RoleId.Blind, RoleTeam.Modifier); - public static RoleInfo watcher = new("Watcher", Color.yellow, RoleId.Watcher, RoleTeam.Modifier, true); - public static RoleInfo radar = new("Radar", Color.yellow, RoleId.Radar, RoleTeam.Modifier, true); - public static RoleInfo tunneler = new("Tunneler", Color.yellow, RoleId.Tunneler, RoleTeam.Modifier, true); - public static RoleInfo buttonBarry = new("ButtonBarry", Color.yellow, RoleId.ButtonBarry, RoleTeam.Modifier); - public static RoleInfo chameleon = new("Chameleon", Color.yellow, RoleId.Chameleon, RoleTeam.Modifier); - public static RoleInfo shifter = new("Shifter", Color.yellow, RoleId.Shifter, RoleTeam.Modifier); + public static RoleInfo assassin = new("Assassin", Assassin.color, RoleId.Assassin, RoleType.Modifier); + public static RoleInfo lover = new("Lover", Lovers.color, RoleId.Lover, RoleType.Modifier, true); + public static RoleInfo disperser = new("Disperser", Disperser.color, RoleId.Disperser, RoleType.Modifier, true); + public static RoleInfo specoality = new("Specoality", Specoality.color, RoleId.Specoality, RoleType.Modifier); + public static RoleInfo poucherModifier = new("Poucher", Poucher.color, RoleId.PoucherModifier, RoleType.Modifier); + public static RoleInfo lastImpostor = new("LastImpostor", LastImpostor.color, RoleId.LastImpostor, RoleType.Modifier); + public static RoleInfo bloody = new("Bloody", Color.yellow, RoleId.Bloody, RoleType.Modifier, true); + public static RoleInfo antiTeleport = new("AntiTeleport", Color.yellow, RoleId.AntiTeleport, RoleType.Modifier); + public static RoleInfo tiebreaker = new("TieBreaker", Color.yellow, RoleId.Tiebreaker, RoleType.Modifier, true); + public static RoleInfo aftermath = new("Aftermath", Color.yellow, RoleId.Aftermath, RoleType.Modifier, true); + public static RoleInfo bait = new("Bait", Color.yellow, RoleId.Bait, RoleType.Modifier, true); + public static RoleInfo sunglasses = new("Sunglasses", Color.yellow, RoleId.Sunglasses, RoleType.Modifier); + public static RoleInfo torch = new("Torch", Color.yellow, RoleId.Torch, RoleType.Modifier, true); + public static RoleInfo flash = new("Flash", Color.yellow, RoleId.Flash, RoleType.Modifier); + public static RoleInfo multitasker = new("Multitasker", Color.yellow, RoleId.Multitasker, RoleType.Modifier, true); + public static RoleInfo giant = new("Giant", Color.yellow, RoleId.Giant, RoleType.Modifier); + public static RoleInfo mini = new("Mini", Color.yellow, RoleId.Mini, RoleType.Modifier); + public static RoleInfo vip = new("Vip", Color.yellow, RoleId.Vip, RoleType.Modifier, true); + public static RoleInfo indomitable = new("Indomitable", Color.yellow, RoleId.Indomitable, RoleType.Modifier); + public static RoleInfo slueth = new("Slueth", Color.yellow, RoleId.Slueth, RoleType.Modifier, true); + public static RoleInfo cursed = new("Cursed", Color.yellow, RoleId.Cursed, RoleType.Modifier, true); + public static RoleInfo invert = new("Invert", Color.yellow, RoleId.Invert, RoleType.Modifier); + public static RoleInfo blind = new("Blind", Color.yellow, RoleId.Blind, RoleType.Modifier); + public static RoleInfo watcher = new("Watcher", Color.yellow, RoleId.Watcher, RoleType.Modifier, true); + public static RoleInfo radar = new("Radar", Color.yellow, RoleId.Radar, RoleType.Modifier, true); + public static RoleInfo tunneler = new("Tunneler", Color.yellow, RoleId.Tunneler, RoleType.Modifier, true); + public static RoleInfo buttonBarry = new("ButtonBarry", Color.yellow, RoleId.ButtonBarry, RoleType.Modifier); + public static RoleInfo chameleon = new("Chameleon", Color.yellow, RoleId.Chameleon, RoleType.Modifier); + public static RoleInfo shifter = new("Shifter", Color.yellow, RoleId.Shifter, RoleType.Modifier); //躲猫猫 - public static RoleInfo hunter = new("Hunter", Palette.ImpostorRed, RoleId.Impostor, RoleTeam.Impostor); - public static RoleInfo hunted = new("Hunted", Color.white, RoleId.Crewmate, RoleTeam.Crewmate); - public static RoleInfo prop = new("Prop", Color.white, RoleId.Crewmate, RoleTeam.Crewmate); + public static RoleInfo hunter = new("Hunter", Palette.ImpostorRed, RoleId.Impostor, RoleType.Impostor); + public static RoleInfo hunted = new("Hunted", Color.white, RoleId.Crewmate, RoleType.Crewmate); + public static RoleInfo prop = new("Prop", Color.white, RoleId.Crewmate, RoleType.Crewmate); public static List allRoleInfos = [ @@ -372,7 +372,7 @@ public static string GetRolesString(PlayerControl p, bool useColors, bool showMo if (p == Jackal.jackal && Jackal.canSwoop) roleName += "JackalIsSwooperInfo".Translate(); - if (HandleGuesser.isGuesserGm && HandleGuesser.isGuesser(p.PlayerId)) roleName += "GuessserGMInfo".Translate(); + if (HandleGuesser.isGuesserGm && HandleGuesser.isGuesser(p.PlayerId) && p != Specoality.specoality && p != Doomsayer.doomsayer) roleName += "GuessserGMInfo".Translate(); if (!suppressGhostInfo && p != null) { @@ -403,8 +403,8 @@ public static string GetRolesString(PlayerControl p, bool useColors, bool showMo roleName = cs(Witch.color, "☆ ") + roleName; if (BountyHunter.bounty == p) roleName = cs(BountyHunter.color, "(被悬赏) ") + roleName; - if (Arsonist.dousedPlayers.Contains(p)) - roleName = cs(Arsonist.color, "♨ ") + roleName; + //if (Arsonist.dousedPlayers.Contains(p)) + // roleName = cs(Arsonist.color, "♨ ") + roleName; if (p == Arsonist.arsonist) roleName += cs(Arsonist.color, $" (剩余 {CachedPlayer.AllPlayers.Count(x => { return x.PlayerControl != Arsonist.arsonist && !x.Data.IsDead && !x.Data.Disconnected && !Arsonist.dousedPlayers.Any(y => y.PlayerId == x.PlayerId); })} )"); diff --git a/TheOtherRoles/TheOtherRoles.csproj b/TheOtherRoles/TheOtherRoles.csproj index 3d54de49..6769f2f5 100644 --- a/TheOtherRoles/TheOtherRoles.csproj +++ b/TheOtherRoles/TheOtherRoles.csproj @@ -1,14 +1,14 @@  net6.0 - 1.0.9.0 + 1.0.9.3 TheOtherUs mxyx-club latest true true embedded - Debug;Release;Sunday;mxyx-club;Beta + Debug;Release;mxyx-club;Beta