From 364fb870f0292d864cd4ed854b11b020e5225525 Mon Sep 17 00:00:00 2001 From: ZsFabTest Date: Sat, 10 Feb 2024 18:10:59 +0800 Subject: [PATCH] 1060 --- Nebula/CustomOptionHolder.cs | 2 +- Nebula/Module/CustomOption.cs | 3 +- Nebula/Nebula.cs | 8 +- Nebula/Patches/EndGamePatch.cs | 6 +- Nebula/Patches/MeetingPatch.cs | 2 +- Nebula/Patches/UpdatePatch.cs | 4 +- Nebula/RPC.cs | 15 +++- Nebula/Resources/Languages/SChinese.dat | 14 +++ Nebula/Resources/Logo.png | Bin 15779 -> 3596 bytes Nebula/Roles/CompeteRoles/BlueTeam.cs | 21 +++-- Nebula/Roles/CompeteRoles/RedTeam.cs | 20 +++-- Nebula/Roles/ComplexRoles/Guesser.cs | 2 +- Nebula/Roles/ExtraRoles/Lover.cs | 2 +- Nebula/Roles/ExtremeRoles/Deadbeat.cs | 99 +++++++++++++++++++++ Nebula/Roles/ExtremeRoles/FakeLover.cs | 2 +- Nebula/Roles/ExtremeRoles/Kotwal.cs | 4 +- Nebula/Roles/ExtremeRoles/SoulEater.cs | 105 +++++++++++++++++++++++ Nebula/Roles/ExtremeRoles/Transporter.cs | 4 +- Nebula/Roles/Roles.cs | 5 +- Nebula/Roles/Side.cs | 6 +- 20 files changed, 288 insertions(+), 36 deletions(-) create mode 100644 Nebula/Roles/ExtremeRoles/Deadbeat.cs create mode 100644 Nebula/Roles/ExtremeRoles/SoulEater.cs diff --git a/Nebula/CustomOptionHolder.cs b/Nebula/CustomOptionHolder.cs index 016183f..136f85f 100644 --- a/Nebula/CustomOptionHolder.cs +++ b/Nebula/CustomOptionHolder.cs @@ -592,7 +592,7 @@ MetaScreenContent getSuitableContent() limiterOptions = CustomOption.Create(Color.white, "option.limitOptions", false, null, true, false, "", CustomOptionTab.Settings).SetGameMode(CustomGameMode.ActuallyAll); CustomOption.RegisterTopOption(limiterOptions); - timeLimitOption = CustomOption.Create(Color.white, "option.timeLimitOption", 20f, 1f, 80f, 1f, limiterOptions).SetGameMode(CustomGameMode.ActuallyAll); + timeLimitOption = CustomOption.Create(Color.white, "option.timeLimitOption", 20f, 0f, 80f, 1f, limiterOptions).SetGameMode(CustomGameMode.ActuallyAll); timeLimitSecondOption = CustomOption.Create(Color.white, "option.timeLimitSecondOption", 0f, 0f, 55f, 5f, limiterOptions).SetGameMode(CustomGameMode.ActuallyAll); timeLimitOption.suffix = "minute"; timeLimitSecondOption.suffix = "second"; diff --git a/Nebula/Module/CustomOption.cs b/Nebula/Module/CustomOption.cs index 4c751ab..86c07da 100644 --- a/Nebula/Module/CustomOption.cs +++ b/Nebula/Module/CustomOption.cs @@ -22,7 +22,8 @@ public enum CustomGameMode Battle = 16, ActuallyAll = 127, VirusCrisis = 32, - Compete = 64 + Compete = 64, + ExceptCompete = 63 } [Flags] diff --git a/Nebula/Nebula.cs b/Nebula/Nebula.cs index 2ba0ceb..daf3898 100644 --- a/Nebula/Nebula.cs +++ b/Nebula/Nebula.cs @@ -43,14 +43,14 @@ public class NebulaPlugin : BasePlugin public const string AmongUsVersion = "2023.3.28"; public const string PluginGuid = "cn.zsfabtest.amongus.nebular"; public const string PluginName = "TheNebula-R-LTS"; - public const string PluginVersion = "1.0.5.7"; + public const string PluginVersion = "1.0.6.0"; public const bool IsSnapshot = false; - public static string PluginVisualVersion = (IsSnapshot ? ("24.02.09" + " - ") : "") + PluginVersion; + public static string PluginVisualVersion = (IsSnapshot ? ("24.02.10" + " - ") : "") + PluginVersion; public static string PluginStage = IsSnapshot ? "Snapshot" : ""; - public const string PluginVersionForFetch = "1.0.5.7"; - public byte[] PluginVersionData = new byte[] { 1, 0, 5, 7 }; + public const string PluginVersionForFetch = "1.0.6.0"; + public byte[] PluginVersionData = new byte[] { 1, 0, 6, 0 }; public static NebulaPlugin Instance; diff --git a/Nebula/Patches/EndGamePatch.cs b/Nebula/Patches/EndGamePatch.cs index 1f3aa96..a4b54ad 100644 --- a/Nebula/Patches/EndGamePatch.cs +++ b/Nebula/Patches/EndGamePatch.cs @@ -28,7 +28,7 @@ public class EndCondition public static EndCondition TrilemmaWin = new EndCondition(25, new Color(209f / 255f, 63f / 255f, 138f / 255f), "trilemma", 0, Module.CustomGameMode.Standard); public static EndCondition SantaWin = new EndCondition(26, Roles.NeutralRoles.SantaClaus.RoleColor, "santa", 4, Module.CustomGameMode.Standard); - public static EndCondition NobodyWin = new EndCondition(48, new Color(72f / 255f, 78f / 255f, 84f / 255f), "nobody", 0, Module.CustomGameMode.ActuallyAll).SetNoBodyWin(true); + public static EndCondition NobodyWin = new EndCondition(48, new Color(72f / 255f, 78f / 255f, 84f / 255f), "nobody", 0, Module.CustomGameMode.ExceptCompete).SetNoBodyWin(true); public static EndCondition NobodySkeldWin = new EndCondition(49, new Color(72f / 255f, 78f / 255f, 84f / 255f), "nobody.skeld", 32, Module.CustomGameMode.ActuallyAll).SetNoBodyWin(true); public static EndCondition NobodyMiraWin = new EndCondition(50, new Color(72f / 255f, 78f / 255f, 84f / 255f), "nobody.mira", 32, Module.CustomGameMode.ActuallyAll).SetNoBodyWin(true); public static EndCondition NobodyPolusWin = new EndCondition(51, new Color(72f / 255f, 78f / 255f, 84f / 255f), "nobody.polus", 32, Module.CustomGameMode.ActuallyAll).SetNoBodyWin(true); @@ -55,7 +55,7 @@ public class EndCondition public static EndCondition UndeadMasterWin = new EndCondition(144,Roles.NeutralRoles.UndeadMaster.RoleColor,"undeadMaster",1,Module.CustomGameMode.Standard); public static EndCondition RedTeamWin = new EndCondition(145, Color.red, "redTeam", 1, Module.CustomGameMode.Compete); public static EndCondition BlueTeamWin = new EndCondition(146, Color.blue, "blueTeam", 1, Module.CustomGameMode.Compete); - public static EndCondition Tie = new EndCondition(64, new Color(72f / 255f, 78f / 255f, 84f / 255f), "tie", 0, Module.CustomGameMode.ActuallyAll).SetNoBodyWin(true); + public static EndCondition Tie = new EndCondition(147, new Color(72f / 255f, 78f / 255f, 84f / 255f), "tie", 32, Module.CustomGameMode.ActuallyAll).SetNoBodyWin(true); public static HashSet AllEnds = new HashSet() { CrewmateWinByVote ,CrewmateWinByTask,CrewmateWinDisconnect, @@ -65,7 +65,7 @@ public class EndCondition LoversWin,TrilemmaWin,AvengerWin, NoGame,NobodyWin,NobodySkeldWin,NobodyMiraWin,NobodyPolusWin,NobodyAirshipWin, PavlovWin,MoriartyWin,MoriartyWinByKillHolmes,CascrubinterWin,GuesserWin,YandereWin,WerewolfWin,ChallengerWin,OracleWin,GhostWin,PuppeteerWin,YellowTeamWin,GreenTeamWin,InfectedWin,SurvivalWin, - HighRollerWin,RedTeamWin,BlueTeamWin + HighRollerWin,RedTeamWin,BlueTeamWin,Tie }; public static EndCondition GetEndCondition(GameOverReason gameOverReason) diff --git a/Nebula/Patches/MeetingPatch.cs b/Nebula/Patches/MeetingPatch.cs index f158cce..c6a713e 100644 --- a/Nebula/Patches/MeetingPatch.cs +++ b/Nebula/Patches/MeetingPatch.cs @@ -35,7 +35,7 @@ static bool Prefix(MeetingHud __instance, [HarmonyArgument(0)] byte srcPlayerId, { GameData.PlayerInfo playerById = GameData.Instance.GetPlayerById(srcPlayerId); GameData.PlayerInfo playerById2 = GameData.Instance.GetPlayerById(suspectPlayerId); - __instance.logger.Debug(playerById.PlayerName + " has voted for " + ((playerById2 != null) ? playerById2.PlayerName : "No one"), null); + Debug.Log(playerById.PlayerName + " has voted for " + ((playerById2 != null) ? playerById2.PlayerName : "No one")); int num = __instance.playerStates.IndexOf((Il2CppSystem.Predicate)((PlayerVoteArea pv) => pv.TargetPlayerId == srcPlayerId)); PlayerVoteArea playerVoteArea = __instance.playerStates[num]; if (!playerVoteArea.AmDead && !playerVoteArea.DidVote) diff --git a/Nebula/Patches/UpdatePatch.cs b/Nebula/Patches/UpdatePatch.cs index bb88b18..56807ef 100644 --- a/Nebula/Patches/UpdatePatch.cs +++ b/Nebula/Patches/UpdatePatch.cs @@ -453,13 +453,13 @@ public static void Postfix(HudManager __instance) Objects.Ghost.Update(); - if (CustomOptionHolder.timeLimitOption.getBool()) Game.GameData.data.TimerUpdate(); + if (CustomOptionHolder.limiterOptions.getBool()) Game.GameData.data.TimerUpdate(); Module.Information.UpperInformationManager.Update(); if (Game.GameData.data.Ghost != null) Game.GameData.data.Ghost.Update(); } - catch (NullReferenceException excep) { UnityEngine.Debug.Log(excep.StackTrace); } + catch (NullReferenceException excep) { Debug.Log(excep.StackTrace); } } diff --git a/Nebula/RPC.cs b/Nebula/RPC.cs index 56188ee..22888b4 100644 --- a/Nebula/RPC.cs +++ b/Nebula/RPC.cs @@ -1865,8 +1865,17 @@ public static void Extort(byte playerId,float time){ public static void CompeteGetPoint(byte team) { - if (team == 0) Roles.CompeteRoles.RedTeam.Point++; - else Roles.CompeteRoles.BlueTeam.Point++; + if (team == 0) + { + Roles.Roles.RedTeam.Point++; + } + else + { + Roles.Roles.BlueTeam.Point++; + } + + Debug.Log($"Red: {Roles.Roles.RedTeam.Point}"); + Debug.Log($"Blue: {Roles.Roles.BlueTeam.Point}"); } } @@ -2971,7 +2980,7 @@ public static void Extort(PlayerControl p,float time){ public static void CompeteGetPoint(byte team) { - MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.Extort, Hazel.SendOption.Reliable, -1); + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.CompeteGetPoint, Hazel.SendOption.Reliable, -1); writer.Write(team); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCEvents.CompeteGetPoint(team); diff --git a/Nebula/Resources/Languages/SChinese.dat b/Nebula/Resources/Languages/SChinese.dat index eb1b866..4d613c6 100644 --- a/Nebula/Resources/Languages/SChinese.dat +++ b/Nebula/Resources/Languages/SChinese.dat @@ -2358,6 +2358,20 @@ "role.blueTeam.hint" : "击杀红队队员" "role.blueTeam.info" : "击杀红队队员。" +"role.soulEater.name" : "噬魂者" +"role.soulEater.short" : "噬" +"role.soulEater.description" : "悄无声息地击杀船员" +"role.soulEater.hint" : "夺取船员的灵魂" +"role.soulEater.info" : "噬魂者每轮只能刀一次。\n在指定时间内若没有开会,被标记对象会隐身,开会前暴毙。" +"role.soulEater.killCooldown" : "击杀冷却时间" +"role.soulEater.delayOption" : "延迟时间" + +"role.deadbeat.name" : "栽赃者" +"role.deadbeat.short" : "栽" +"role.deadbeat.description" : "借他人之手击杀船员" +"role.deadbeat.hint" : "指定击杀船员" +"role.deadbeat.info" : "栽赃者需要标记一个人。\n使用击杀后将由被标记的人击杀。\n栽赃者会瞬移,而被标记者不会。" + "option.display.random" : "随机" "side.paparazzo.name" : "摄影师" diff --git a/Nebula/Resources/Logo.png b/Nebula/Resources/Logo.png index b7162dca30ae0266dce21f0767cbe9156447d279..27beb755120784c242bc8a8e26529d553588d2f5 100644 GIT binary patch literal 3596 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 literal 15779 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

<>@t!>aJt5o#`vA& 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 T^KJ0fHH?CcigcBvNyz^JA1PAr diff --git a/Nebula/Roles/CompeteRoles/BlueTeam.cs b/Nebula/Roles/CompeteRoles/BlueTeam.cs index 567973c..0ae8183 100644 --- a/Nebula/Roles/CompeteRoles/BlueTeam.cs +++ b/Nebula/Roles/CompeteRoles/BlueTeam.cs @@ -1,8 +1,11 @@ -namespace Nebula.Roles.CompeteRoles; +using Reactor.Utilities.Extensions; +using TMPro; + +namespace Nebula.Roles.CompeteRoles; public class BlueTeam : Role { - public static int Point = 0; + public int Point = 0; public override void GlobalInitialize(PlayerControl __instance) { @@ -35,7 +38,7 @@ public override void ButtonInitialize(HudManager __instance) ).SetTimer(15f); killButton.MaxTimer = CustomOptionHolder.CompeteKillCooldownOption.getFloat(); killButton.SetButtonCoolDownOption(true); - Debug.LogError(killButton.MaxTimer); + //Debug.LogError(killButton.MaxTimer); } public override void CleanUp() @@ -56,17 +59,25 @@ public override void MyPlayerControlUpdate() public override void OnDied() { - Events.StandardEvent.SetEvent(() => { RPCEventInvoker.RevivePlayer(PlayerControl.LocalPlayer, true, false); },time:CustomOptionHolder.CompeteReviveDelayOption.getFloat()); + Events.StandardEvent.SetEvent(() => { RPCEventInvoker.RevivePlayer(PlayerControl.LocalPlayer, false, false); },time:CustomOptionHolder.CompeteReviveDelayOption.getFloat()); + } + + public override void EditOthersDisplayNameColor(byte playerId, ref Color displayColor) + { + if (Helpers.playerById(playerId).GetModData().role.side == Side.BlueTeam) displayColor = Color; + else displayColor = Color.red; } public BlueTeam() : base("BlueTeam","blueTeam",Color.blue,RoleCategory.Neutral,Side.BlueTeam,Side.BlueTeam, new HashSet { Side.BlueTeam },new HashSet() { Side.BlueTeam },new HashSet() { Patches.EndCondition.BlueTeamWin }, - false, VentPermission.CanUseUnlimittedVent, true, true, true) + true, VentPermission.CanUseUnlimittedVent, true, true, true) { canReport = false; CanCallEmergencyMeeting = false; ValidGamemode = Module.CustomGameMode.Compete; IsHideRole = true; + + Point = 0; } } \ No newline at end of file diff --git a/Nebula/Roles/CompeteRoles/RedTeam.cs b/Nebula/Roles/CompeteRoles/RedTeam.cs index 6a709f8..a270d7c 100644 --- a/Nebula/Roles/CompeteRoles/RedTeam.cs +++ b/Nebula/Roles/CompeteRoles/RedTeam.cs @@ -1,10 +1,12 @@ -using static Il2CppSystem.Globalization.CultureInfo; +using Reactor.Utilities.Extensions; +using TMPro; +using static Il2CppSystem.Globalization.CultureInfo; namespace Nebula.Roles.CompeteRoles; public class RedTeam : Role { - public static int Point = 0; + public int Point = 0; public override void GlobalInitialize(PlayerControl __instance) { @@ -37,7 +39,7 @@ public override void ButtonInitialize(HudManager __instance) ).SetTimer(15f); killButton.MaxTimer = CustomOptionHolder.CompeteKillCooldownOption.getFloat(); killButton.SetButtonCoolDownOption(true); - Debug.LogError(killButton.MaxTimer); + //Debug.LogError(killButton.MaxTimer); } public override void CleanUp() @@ -58,17 +60,25 @@ public override void MyPlayerControlUpdate() public override void OnDied() { - Events.StandardEvent.SetEvent(() => { RPCEventInvoker.RevivePlayer(PlayerControl.LocalPlayer, true, false); },time:CustomOptionHolder.CompeteReviveDelayOption.getFloat()); + Events.StandardEvent.SetEvent(() => { RPCEventInvoker.RevivePlayer(PlayerControl.LocalPlayer, false, false); },time:CustomOptionHolder.CompeteReviveDelayOption.getFloat()); + } + + public override void EditOthersDisplayNameColor(byte playerId, ref Color displayColor) + { + if (Helpers.playerById(playerId).GetModData().role.side == Side.RedTeam) displayColor = Color; + else displayColor = Color.blue; } public RedTeam() : base("RedTeam","redTeam",Color.red,RoleCategory.Neutral,Side.RedTeam,Side.RedTeam, new HashSet { Side.RedTeam },new HashSet() { Side.RedTeam },new HashSet() { Patches.EndCondition.RedTeamWin }, - false, VentPermission.CanUseUnlimittedVent, true, true, true) + true, VentPermission.CanUseUnlimittedVent, true, true, true) { canReport = false; CanCallEmergencyMeeting = false; ValidGamemode = Module.CustomGameMode.Compete; IsHideRole = true; + + Point = 0; } } \ No newline at end of file diff --git a/Nebula/Roles/ComplexRoles/Guesser.cs b/Nebula/Roles/ComplexRoles/Guesser.cs index 5e2ad21..b90c17b 100644 --- a/Nebula/Roles/ComplexRoles/Guesser.cs +++ b/Nebula/Roles/ComplexRoles/Guesser.cs @@ -362,7 +362,7 @@ static void guesserOnClick(int buttonTarget, MeetingHud __instance) actualRole == role || role.GetImplicateRoles().Contains(actualRole) || role.GetImplicateExtraRoles().Any((r) => focusedTargetData.HasExtraRole(r)) || - role == Roles.SchrodingersCat && (NeutralRoles.SchrodingersCat.AllCat.Contains(actualRole)) + role == Roles.SchrodingersCat && (NeutralRoles.SchrodingersCat.AllCat.Any((ro) => ro.id == actualRole.id)) ) ? focusedTarget : PlayerControl.LocalPlayer; diff --git a/Nebula/Roles/ExtraRoles/Lover.cs b/Nebula/Roles/ExtraRoles/Lover.cs index c464cdb..fd21c22 100644 --- a/Nebula/Roles/ExtraRoles/Lover.cs +++ b/Nebula/Roles/ExtraRoles/Lover.cs @@ -415,7 +415,7 @@ public override void CleanUp() } - public virtual bool IsSpawnable() + public override bool IsSpawnable() { if (maxPairsOption.getFloat() == 0f) return false; diff --git a/Nebula/Roles/ExtremeRoles/Deadbeat.cs b/Nebula/Roles/ExtremeRoles/Deadbeat.cs new file mode 100644 index 0000000..55187df --- /dev/null +++ b/Nebula/Roles/ExtremeRoles/Deadbeat.cs @@ -0,0 +1,99 @@ +namespace Nebula.Roles.ImpostorRoles; + +public class Deadbeat : Template.TImpostor +{ + private SpriteLoader AssassinMarkButtonSprite = new SpriteLoader("Nebula.Resources.AssassinMarkButton.png", 115f); + + public override void Initialize(PlayerControl __instance) + { + target = null; + } + + public override void LoadOptionData() + { + base.LoadOptionData(); + TopOption.tab = Module.CustomOptionTab.AdvancedSettings; + } + + private PlayerControl target; + private CustomButton markButton,killButton; + public override void ButtonInitialize(HudManager __instance) + { + if(markButton != null) + { + markButton.Destroy(); + } + markButton = new CustomButton( + () => + { + target = Game.GameData.data.myData.currentTarget; + }, + () => { return !PlayerControl.LocalPlayer.Data.IsDead; }, + () => { return PlayerControl.LocalPlayer.CanMove && Game.GameData.data.myData.currentTarget; }, + () => { target = null; }, + AssassinMarkButtonSprite.GetSprite(), + Expansion.GridArrangeExpansion.GridArrangeParameter.None, + __instance, + Module.NebulaInputManager.abilityInput.keyCode, + "button.label.mark" + ).SetTimer(0); + markButton.Timer = markButton.MaxTimer = 0; + + if(killButton != null) + { + killButton.Destroy(); + } + killButton = new CustomButton( + () => + { + RPCEventInvoker.FakeKill(PlayerControl.LocalPlayer,Game.GameData.data.myData.currentTarget); + Helpers.checkMuderAttemptAndKill(target,Game.GameData.data.myData.currentTarget,Game.PlayerData.PlayerStatus.Dead,showAnimation:false); + Game.GameData.data.myData.currentTarget = null; + killButton.Timer = killButton.MaxTimer; + }, + () => { return !PlayerControl.LocalPlayer.Data.IsDead; }, + () => { return PlayerControl.LocalPlayer.CanMove && Game.GameData.data.myData.currentTarget; }, + () => { killButton.Timer = killButton.MaxTimer; }, + __instance.KillButton.graphic.sprite, + Expansion.GridArrangeExpansion.GridArrangeParameter.AlternativeKillButtonContent, + __instance, + Module.NebulaInputManager.modKillInput.keyCode, + "button.label.kill" + ).SetTimer(CustomOptionHolder.InitialKillCoolDownOption.getFloat()); + killButton.MaxTimer = GameOptionsManager.Instance.CurrentGameOptions.GetFloat(FloatOptionNames.KillCooldown); + killButton.SetButtonCoolDownOption(true); + } + + public override void CleanUp() + { + if(markButton != null) + { + markButton.Destroy(); + markButton = null; + } + if(killButton != null) + { + killButton.Destroy(); + killButton = null; + } + target = null; + } + + public override void EditCoolDown(CoolDownType type, float count) + { + killButton.Timer -= count; + killButton.actionButton.ShowButtonText("+" + count + "s"); + } + + public override void MyPlayerControlUpdate() + { + Game.MyPlayerData data = Game.GameData.data.myData; + data.currentTarget = Patches.PlayerControlPatch.SetMyTarget((p) => !target || p.PlayerId != target.PlayerId); + Patches.PlayerControlPatch.SetPlayerOutline(data.currentTarget, Palette.ImpostorRed); + } + + public Deadbeat() : base("Deadbeat", "deadbeat", false) + { + HideKillButtonEvenImpostor = true; + } +} \ No newline at end of file diff --git a/Nebula/Roles/ExtremeRoles/FakeLover.cs b/Nebula/Roles/ExtremeRoles/FakeLover.cs index a823073..384fbef 100644 --- a/Nebula/Roles/ExtremeRoles/FakeLover.cs +++ b/Nebula/Roles/ExtremeRoles/FakeLover.cs @@ -39,7 +39,7 @@ public override void EditDescriptionString(ref string desctiption) private SpriteLoader buttonSprite = new SpriteLoader("Nebula.Resources.InvolveButton.png", 115f, "ui.button.lover.involve"); - public virtual bool IsSpawnable() + public override bool IsSpawnable() { return false; } diff --git a/Nebula/Roles/ExtremeRoles/Kotwal.cs b/Nebula/Roles/ExtremeRoles/Kotwal.cs index 3cece74..8d77521 100644 --- a/Nebula/Roles/ExtremeRoles/Kotwal.cs +++ b/Nebula/Roles/ExtremeRoles/Kotwal.cs @@ -65,9 +65,9 @@ public override void ButtonInitialize(HudManager __instance) { PlayerControl target = Game.GameData.data.myData.currentTarget; Events.LocalEvent.Activate(new KotwalEvent(target)); - RPCEventInvoker.AddAndUpdateRoleData(PlayerControl.LocalPlayer.PlayerId, appointDataId, -1); + appointDataId--; }, - () => { return !PlayerControl.LocalPlayer.Data.IsDead && Game.GameData.data.myData.getGlobalData().GetRoleData(appointDataId) > 0; }, + () => { return !PlayerControl.LocalPlayer.Data.IsDead && appointDataId > 0; }, () => { return Game.GameData.data.myData.currentTarget && PlayerControl.LocalPlayer.CanMove; }, () => { appoint.Timer = appoint.MaxTimer; }, buttonSprite.GetSprite(), diff --git a/Nebula/Roles/ExtremeRoles/SoulEater.cs b/Nebula/Roles/ExtremeRoles/SoulEater.cs new file mode 100644 index 0000000..c7ee09e --- /dev/null +++ b/Nebula/Roles/ExtremeRoles/SoulEater.cs @@ -0,0 +1,105 @@ +namespace Nebula.Roles.ImpostorRoles; + +public class SoulEater : Template.TImpostor +{ + private Module.CustomOption delayOption; + private Module.CustomOption killCooldownOption; + + private SpriteLoader pseudocideButtonSprite = new SpriteLoader("Nebula.Resources.BuskPseudocideButton.png", 115f); + + public override void LoadOptionData() + { + TopOption.tab = Module.CustomOptionTab.AdvancedSettings; + killCooldownOption = CreateOption(Color.white, "killCooldown", 20f, 2.5f, 45f, 2.5f); + delayOption = CreateOption(Color.white, "delayOption", 10f, 0f, 20f, 0.25f); + } + + private CustomButton killButton; + private PlayerControl target = null; + private bool canKill = false; + public override void ButtonInitialize(HudManager __instance) + { + if(killButton != null) + { + killButton.Destroy(); + } + killButton = new CustomButton( + () => + { + target = Game.GameData.data.myData.currentTarget; + }, + () => { return !PlayerControl.LocalPlayer.Data.IsDead; }, + () => { return !target && Game.GameData.data.myData.currentTarget; }, + () => { killButton.Timer = killButton.MaxTimer; canKill = false; }, + pseudocideButtonSprite.GetSprite(), + Expansion.GridArrangeExpansion.GridArrangeParameter.AlternativeKillButtonContent, + __instance, + Module.NebulaInputManager.modKillInput.keyCode, + true, + delayOption.getFloat(), + () => + { + if (!target.Data.IsDead && !MeetingHud.Instance) + { + RPCEventInvoker.UpdatePlayerVisibility(target.PlayerId, false); + RPCEventInvoker.EmitAttributeFactor(target, new Game.PlayerAttributeFactor(Game.PlayerAttribute.Invisible, 1145141919810f, 5, false)); + canKill = true; + } + else + { + target = null; + canKill = false; + } + }, + "button.label.eat" + ).SetTimer(CustomOptionHolder.InitialAbilityCoolDownOption.getFloat()); + killButton.MaxTimer = killCooldownOption.getFloat(); + } + + public override void OnMeetingStart() + { + if (target && canKill) + { + RPCEventInvoker.UncheckedMurderPlayer(PlayerControl.LocalPlayer.PlayerId,target.PlayerId,Game.PlayerData.PlayerStatus.Dead.Id,false); + target = null; + canKill = false; + } + } + + public override void CleanUp() + { + if (killButton != null) + { + killButton.Destroy(); + killButton = null; + } + target = null; + canKill = false; + } + + public override void Initialize(PlayerControl __instance) + { + target = null; + canKill = false; + } + + public override void EditCoolDown(CoolDownType type, float count) + { + killButton.Timer -= count; + killButton.actionButton.ShowButtonText("+" + count + "s"); + } + + public override void MyPlayerControlUpdate() + { + Game.MyPlayerData data = Game.GameData.data.myData; + data.currentTarget = Patches.PlayerControlPatch.SetMyTarget(true); + Patches.PlayerControlPatch.SetPlayerOutline(data.currentTarget, Palette.ImpostorRed); + } + + public SoulEater() : base("SoulEater", "soulEater", true) + { + target = null; + canKill = false; + HideKillButtonEvenImpostor = true; + } +} \ No newline at end of file diff --git a/Nebula/Roles/ExtremeRoles/Transporter.cs b/Nebula/Roles/ExtremeRoles/Transporter.cs index 2703c63..4ef9cb7 100644 --- a/Nebula/Roles/ExtremeRoles/Transporter.cs +++ b/Nebula/Roles/ExtremeRoles/Transporter.cs @@ -36,8 +36,8 @@ public class Transporter : Template.BilateralnessRole{ private SpriteLoader buttonSprite = new SpriteLoader("Nebula.Resources.ChainShiftButton.png", 115f); private SpriteLoader markSprite = new SpriteLoader("Nebula.Resources.AssassinMarkButton.png", 115f); - public override Assignable AssignableOnHelp => Roles.F_Mover; - public override HelpSprite[] helpSprite => Roles.F_Mover.helpSprite; + public override Assignable AssignableOnHelp => Roles.F_Transporter; + public override HelpSprite[] helpSprite => Roles.F_Transporter.helpSprite; PlayerControl target; diff --git a/Nebula/Roles/Roles.cs b/Nebula/Roles/Roles.cs index 571ed11..650f90a 100644 --- a/Nebula/Roles/Roles.cs +++ b/Nebula/Roles/Roles.cs @@ -253,6 +253,9 @@ public SideCommonRolesLoader() public static CompeteRoles.RedTeam RedTeam = new(); public static CompeteRoles.BlueTeam BlueTeam = new(); + public static ImpostorRoles.SoulEater SoulEater = new(); + public static ImpostorRoles.Deadbeat Deadbeat = new(); + //全てのロールはこの中に含まれている必要があります public static List AllRoles = new List() @@ -267,7 +270,7 @@ public SideCommonRolesLoader() GameMaster,F_Decider,EvilDecider,NiceDecider,F_Swapper,EvilSwapper,NiceSwapper,F_Mover,EvilMover,NiceMover,F_Transporter,EvilTransporter,NiceTransporter, Holmes,Kotwal,Necrophilic,Observer,/*OnlineCelebrity,*/Sanctifier,/*Transporter,*/Dictator,/*Bartender,*/LuckyMan,/*Superstar,*/ChivalrousExpert,Programmer,Minekeeper,Locksmith,Resurrectionist,Supporter,/*Detective,*/ZombieSidekick,TaoistPriest,WiseMan,Paranoiac,Officer,/*杀路无法意识,*/TimeManager,Enchanter/*,OppositeMan*/,VentBomber, - Assassin,/*Demagogue,*/Escapist,EvilBusker,SerialKiller,Vampire,InvisibleMan,Heretic,Moda,Marksman,Gambler,Plumber,ChainKiller,Terrorist,Dying,Retarder,Marker,HadarS,Zombie,BomberA,BomberB,Grenadier,Hitman,Extortionist, + Assassin,/*Demagogue,*/Escapist,EvilBusker,SerialKiller,Vampire,InvisibleMan,Heretic,Moda,Marksman,Gambler,Plumber,ChainKiller,Terrorist,Dying,Retarder,Marker,HadarS,Zombie,BomberA,BomberB,Grenadier,Hitman,Extortionist,SoulEater,Deadbeat, Madman,Pavlov,Dog,Moriarty,Moran,Cascrubinter,Amnesiac,Yandere,Mercenary,Werewolf,Challenger,OracleN,Ghost,Puppeteer,Follower,HighRoller, JackalMayor, SchrodingersCat,RedCat,BlueCat,WhiteCat,PavlovsCat,WerewolfsCat,OraclesCat, diff --git a/Nebula/Roles/Side.cs b/Nebula/Roles/Side.cs index c1d2c70..3c3e631 100644 --- a/Nebula/Roles/Side.cs +++ b/Nebula/Roles/Side.cs @@ -452,9 +452,9 @@ public enum IntroDisplayOption } else if(Game.GameData.data.GameMode == Module.CustomGameMode.Compete) { - int point1 = CompeteRoles.RedTeam.Point; - int point2 = CompeteRoles.BlueTeam.Point; - CompeteRoles.RedTeam.Point = CompeteRoles.BlueTeam.Point = 0; + int point1 = Roles.RedTeam.Point; + int point2 = Roles.BlueTeam.Point; + Roles.RedTeam.Point = Roles.BlueTeam.Point = 0; if (point1 > point2) return EndCondition.RedTeamWin; else if (point1 < point2) return EndCondition.BlueTeamWin; else return EndCondition.Tie;