diff --git a/MiraAPI.Example/ExampleEventHandlers.cs b/MiraAPI.Example/ExampleEventHandlers.cs index 618ea2f..2e8fdf2 100644 --- a/MiraAPI.Example/ExampleEventHandlers.cs +++ b/MiraAPI.Example/ExampleEventHandlers.cs @@ -1,5 +1,4 @@ using System.Linq; -using HarmonyLib; using MiraAPI.Events; using MiraAPI.Events.Mira; using MiraAPI.Events.Vanilla.Gameplay; @@ -43,7 +42,7 @@ public static class ExampleEventHandlers { if (plr.Data.Role is MayorRole) { - plr.GetVoteData().AddVotes(1); + plr.GetVoteData().IncreaseRemainingVotes(1); } } } @@ -52,9 +51,9 @@ public static class ExampleEventHandlers [RegisterEvent(15)] public static void HandleVoteEvent(HandleVoteEvent @event) { - if (@event.VoteData.Owner?.Data.Role is not NeutralKillerRole) return; + if (@event.VoteData.Owner.Data.Role is not NeutralKillerRole) return; - @event.VoteData.SetVotesRemaining(0); + @event.VoteData.SetRemainingVotes(0); for (var i = 0; i < 5; i++) { @@ -63,7 +62,7 @@ public static class ExampleEventHandlers foreach (var plr in PlayerControl.AllPlayerControls.ToArray().Where(player => player != @event.VoteData.Owner)) { - plr.GetVoteData().VotedPlayers.Clear(); + plr.GetVoteData().Votes.Clear(); plr.GetVoteData().VotesRemaining = 0; } diff --git a/MiraAPI/Events/Vanilla/Meeting/Voting/HandleVoteEvent.cs b/MiraAPI/Events/Vanilla/Meeting/Voting/HandleVoteEvent.cs index 9dc9659..a0c7f75 100644 --- a/MiraAPI/Events/Vanilla/Meeting/Voting/HandleVoteEvent.cs +++ b/MiraAPI/Events/Vanilla/Meeting/Voting/HandleVoteEvent.cs @@ -1,5 +1,4 @@ -using MiraAPI.Utilities; -using MiraAPI.Voting; +using MiraAPI.Voting; namespace MiraAPI.Events.Vanilla.Meeting.Voting; diff --git a/MiraAPI/Events/Vanilla/Meeting/Voting/MeetingSelectEvent.cs b/MiraAPI/Events/Vanilla/Meeting/Voting/MeetingSelectEvent.cs index 58f6eeb..71d8a23 100644 --- a/MiraAPI/Events/Vanilla/Meeting/Voting/MeetingSelectEvent.cs +++ b/MiraAPI/Events/Vanilla/Meeting/Voting/MeetingSelectEvent.cs @@ -1,5 +1,4 @@ -using MiraAPI.Utilities; -using MiraAPI.Voting; +using MiraAPI.Voting; namespace MiraAPI.Events.Vanilla.Meeting.Voting; diff --git a/MiraAPI/Networking/MiraRpc.cs b/MiraAPI/Networking/MiraRpc.cs index 1a3fa66..6d51e2a 100644 --- a/MiraAPI/Networking/MiraRpc.cs +++ b/MiraAPI/Networking/MiraRpc.cs @@ -39,6 +39,14 @@ public enum MiraRpc : uint /// Custom Game Over RPC. /// CustomGameOver, + + /// + /// Custom RPC to handle populating vote results. + /// PopulateResults, + + /// + /// Custom RPC to undo a player's vote. + /// RemoveVote, } diff --git a/MiraAPI/Patches/PlayerControlPatches.cs b/MiraAPI/Patches/PlayerControlPatches.cs index 6036209..feb2921 100644 --- a/MiraAPI/Patches/PlayerControlPatches.cs +++ b/MiraAPI/Patches/PlayerControlPatches.cs @@ -6,7 +6,6 @@ using MiraAPI.Events.Vanilla.Player; using MiraAPI.Hud; using MiraAPI.Modifiers; using MiraAPI.Roles; -using MiraAPI.Utilities; using MiraAPI.Voting; using Reactor.Utilities.Extensions; diff --git a/MiraAPI/Patches/Voting/MeetingHudPatches.cs b/MiraAPI/Patches/Voting/MeetingHudPatches.cs index f3db9cd..c437b36 100644 --- a/MiraAPI/Patches/Voting/MeetingHudPatches.cs +++ b/MiraAPI/Patches/Voting/MeetingHudPatches.cs @@ -10,7 +10,7 @@ using Reactor.Networking.Rpc; namespace MiraAPI.Patches.Voting; [HarmonyPatch(typeof(MeetingHud))] -public static class MeetingHudPatches +internal static class MeetingHudPatches { [HarmonyPostfix] [HarmonyPatch(nameof(MeetingHud.Start))] @@ -19,12 +19,12 @@ public static class MeetingHudPatches foreach (var plr in PlayerControl.AllPlayerControls) { var voteData = plr.GetVoteData(); - voteData.VotedPlayers.Clear(); - voteData.SetVotesRemaining(1); + voteData.Votes.Clear(); + voteData.SetRemainingVotes(1); if (plr.Data.IsDead || plr.Data.Disconnected) { - voteData.SetVotesRemaining(0); + voteData.SetRemainingVotes(0); } } var @event = new StartMeetingEvent(__instance); @@ -46,7 +46,7 @@ public static class MeetingHudPatches } var hasVotes = voteData.VotesRemaining > 0; - var hasVotedFor = voteData.VotedPlayers.Contains((byte)suspectStateIdx); + var hasVotedFor = voteData.VotedFor((byte)suspectStateIdx); return hasVotes && !hasVotedFor; } @@ -69,12 +69,12 @@ public static class MeetingHudPatches var pva = __instance.playerStates.First(pv => pv.TargetPlayerId == player.PlayerId); var voteData = player.GetVoteData(); - if (pva.AmDead || !voteData.VotedPlayers.Contains(pc.PlayerId)) + if (pva.AmDead || !voteData.VotedFor(pc.PlayerId)) { continue; } - voteData.VotedPlayers.Remove(pc.PlayerId); + voteData.Votes.RemoveAll(x=>x.Suspect==pc.PlayerId); voteData.VotesRemaining += 1; VotingUtils.RpcRemoveVote(PlayerControl.LocalPlayer, player.PlayerId, pc.PlayerId); @@ -104,7 +104,7 @@ public static class MeetingHudPatches var voteData = plr.Object.GetVoteData(); if (voteData == null || voteData.VotesRemaining == 0 || - voteData.VotedPlayers.Contains(suspectPlayerId)) + voteData.VotedFor(suspectPlayerId)) { return false; } @@ -135,7 +135,7 @@ public static class MeetingHudPatches if (!AmongUsClient.Instance.AmHost) { if (voteData == null || voteData.VotesRemaining == 0 || - voteData.VotedPlayers.Contains(suspectIdx)) + voteData.VotedFor(suspectIdx)) { return; } @@ -173,7 +173,7 @@ public static class MeetingHudPatches [HarmonyPatch(nameof(MeetingHud.CheckForEndVoting))] public static bool EndCheck(MeetingHud __instance) { - if (Helpers.GetAlivePlayers().Any(plr => plr.GetVoteData()!.VotesRemaining > 0)) + if (Helpers.GetAlivePlayers().Exists(plr => plr.GetVoteData()!.VotesRemaining > 0)) { return false; } @@ -193,7 +193,6 @@ public static class MeetingHudPatches return false; } - [HarmonyPrefix] [HarmonyPatch(nameof(MeetingHud.PopulateResults))] public static bool PopulateResultsPatch(MeetingHud __instance) @@ -204,7 +203,7 @@ public static class MeetingHudPatches } var votes = VotingUtils.CalculateVotes(); - Rpc.Instance.Send(votes.ToArray()); + Rpc.Instance.Send([.. votes]); return false; } diff --git a/MiraAPI/Voting/PlayerVoteData.cs b/MiraAPI/Voting/PlayerVoteData.cs index 0b0f099..023c83e 100644 --- a/MiraAPI/Voting/PlayerVoteData.cs +++ b/MiraAPI/Voting/PlayerVoteData.cs @@ -9,17 +9,17 @@ namespace MiraAPI.Voting; /// Handles player votes, and removing/adding additional votes. /// [RegisterInIl2Cpp] -public class PlayerVoteData(nint ptr) : MonoBehaviour(ptr) +public class PlayerVoteData(nint cppPtr) : MonoBehaviour(cppPtr) { /// /// Gets the owner of this component. /// - public PlayerControl? Owner { get; private set; } + public PlayerControl Owner { get; private set; } = null!; /// - /// Gets the players which the owner has voted for. + /// Gets the list of votes the owner has. /// - public List VotedPlayers { get; private set; } = []; + public List Votes { get; private set; } = []; /// /// Gets or sets the amount of votes the owner has left. @@ -43,29 +43,48 @@ public class PlayerVoteData(nint ptr) : MonoBehaviour(ptr) } /// - /// Adds the voted player to the list. + /// Returns whether the owner has voted for the specified player. /// /// The target's playerId. - public void VoteForPlayer(byte playerId) + /// True if the owner voted for the specified player, false otherwise. + public bool VotedFor(byte playerId) { - VotedPlayers.Add(playerId); + return Votes.Exists(x => x.Suspect == playerId); } /// - /// Removes the voted player from the list. + /// Adds the voted player to the list. + /// + /// The target's playerId. + /// The weight of the vote. + public void VoteForPlayer(byte playerId, float weight=1f) + { + Votes.Add(new CustomVote(Owner.PlayerId, playerId, weight)); + } + + /// + /// Removes the specified vote. + /// + /// The vote you would like to remove. + public void RemovePlayerVote(CustomVote vote) + { + Votes.Remove(vote); + } + + /// + /// Removes a single vote from the owner. /// /// The target's playerId. public void RemovePlayerVote(byte playerId) { - if (!VotedPlayers.Contains(playerId)) return; - VotedPlayers.Remove(playerId); + Votes.Remove(Votes.Find(x=>x.Suspect==playerId)); } /// /// Sets the player's votes remaining. /// /// The amount of votes you would like to set it to. - public void SetVotesRemaining(int votesRemaining) + public void SetRemainingVotes(int votesRemaining) { VotesRemaining = votesRemaining; } @@ -74,17 +93,17 @@ public class PlayerVoteData(nint ptr) : MonoBehaviour(ptr) /// Adds votes to the owner. /// /// The amount of votes you would like to add. - public void AddVotes(int amount) + public void IncreaseRemainingVotes(int amount) { - SetVotesRemaining(VotesRemaining + amount); + SetRemainingVotes(VotesRemaining + amount); } /// /// Removes votes from the owner. /// /// The amount of votes you would like to remove. - public void RemoveVotes(int amount) + public void DecreaseRemainingVotes(int amount) { - SetVotesRemaining(VotesRemaining - amount); + SetRemainingVotes(VotesRemaining - amount); } } diff --git a/MiraAPI/Voting/PopulateResultsRpc.cs b/MiraAPI/Voting/PopulateResultsRpc.cs index ea4963f..042fb43 100644 --- a/MiraAPI/Voting/PopulateResultsRpc.cs +++ b/MiraAPI/Voting/PopulateResultsRpc.cs @@ -1,5 +1,4 @@ -using System.Linq; -using Hazel; +using Hazel; using MiraAPI.Networking; using Reactor.Networking.Attributes; using Reactor.Networking.Rpc; @@ -29,6 +28,7 @@ public class PopulateResultsRpc(MiraApiPlugin plugin, uint id) : PlayerCustomRpc { writer.Write(t.Voter); writer.Write(t.Suspect); + writer.Write(t.Weight); } } @@ -39,7 +39,7 @@ public class PopulateResultsRpc(MiraApiPlugin plugin, uint id) : PlayerCustomRpc for (var i = 0; i < votes.Length; i++) { - votes[i] = new CustomVote(reader.ReadByte(), reader.ReadByte()); + votes[i] = new CustomVote(reader.ReadByte(), reader.ReadByte(), reader.ReadSingle()); } return votes; diff --git a/MiraAPI/Voting/VotingUtils.cs b/MiraAPI/Voting/VotingUtils.cs index f2fb6c0..d152589 100644 --- a/MiraAPI/Voting/VotingUtils.cs +++ b/MiraAPI/Voting/VotingUtils.cs @@ -23,7 +23,7 @@ public static class VotingUtils /// Who the player voted for. public static void HandleVote(PlayerVoteData voteData, byte suspectIdx) { - HandleVoteEvent @event = new HandleVoteEvent(voteData, suspectIdx); + var @event = new HandleVoteEvent(voteData, suspectIdx); MiraEventManager.InvokeEvent(@event); if (@event.IsCancelled) @@ -31,7 +31,7 @@ public static class VotingUtils return; } - voteData.RemoveVotes(1); + voteData.DecreaseRemainingVotes(1); voteData.VoteForPlayer(suspectIdx); } @@ -61,7 +61,7 @@ public static class VotingUtils if (!AmongUsClient.Instance.AmHost) { var voteData = PlayerControl.LocalPlayer.GetVoteData(); - voteData.RemoveVotes(1); + voteData.DecreaseRemainingVotes(1); voteData.RemovePlayerVote(votedFor); } @@ -100,9 +100,11 @@ public static class VotingUtils /// The list of votes. public static List CalculateVotes() { - return (from player in Helpers.GetAlivePlayers() - from vote in player.GetVoteData()!.VotedPlayers - select new CustomVote(player.PlayerId, vote)).ToList(); + return + [ + .. Helpers.GetAlivePlayers() + .SelectMany(player => player.GetVoteData().Votes) + ]; } ///