mirror of
https://github.com/All-Of-Us-Mods/MiraAPI.git
synced 2026-10-20 01:46:15 +00:00
Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
878eab25b8 | ||
|
|
e4f15f2ed9 | ||
|
|
bdc9fa28ac | ||
|
|
64604aff98 | ||
|
|
3ba71d8f19 | ||
|
|
e5b6400eb8 | ||
|
|
0d1d1891a8 | ||
|
|
a3fc847d07 | ||
|
|
31ffe6274c | ||
|
|
f0e37daf0e | ||
|
|
be46ee7329 | ||
|
|
75a15dc090 | ||
|
|
cffb104392 |
No files matched your search
+2
-2
@@ -2,10 +2,10 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Reactor" Version="2.3.1" />
|
||||
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.697" Private="false" ExcludeAssets="runtime;native" />
|
||||
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2024.10.29" PrivateAssets="all" />
|
||||
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2025.3.25" PrivateAssets="all" />
|
||||
|
||||
<PackageReference Include="BepInEx.AutoPlugin" Version="1.1.0" PrivateAssets="all" />
|
||||
<PackageReference Include="BepInEx.IL2CPP.MSBuild" Version="2.0.1" PrivateAssets="all" ExcludeAssets="runtime" />
|
||||
<PackageReference Include="BepInEx.IL2CPP.MSBuild" Version="2.1.0-rc.1" PrivateAssets="all" ExcludeAssets="runtime" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="Copy" AfterTargets="Build" Condition="'$(AmongUs)' != ''">
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556" PrivateAssets="all" />
|
||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)\stylecop.json" Link="stylecop.json" Visible="false" />
|
||||
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.32.0.97167">
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.7.0.110445">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -24,6 +24,11 @@ public class HandleVoteEvent : MiraCancelableEvent
|
||||
/// </summary>
|
||||
public byte TargetId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether to prevent the vote from commencing.
|
||||
/// </summary>
|
||||
public bool PreventVote { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the player info of the target.
|
||||
/// </summary>
|
||||
@@ -39,6 +44,7 @@ public class HandleVoteEvent : MiraCancelableEvent
|
||||
VoteData = playerVoteData;
|
||||
Player = playerVoteData.Owner;
|
||||
TargetId = targetId;
|
||||
PreventVote = false;
|
||||
TargetPlayerInfo = GameData.Instance.GetPlayerById(targetId);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using HarmonyLib;
|
||||
using Il2CppInterop.Runtime.Attributes;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using Reactor.Utilities.Attributes;
|
||||
@@ -23,11 +24,19 @@ public class ModifierDisplayComponent(nint ptr) : MonoBehaviour(ptr)
|
||||
/// </summary>
|
||||
public static ModifierDisplayComponent? Instance { get; private set; }
|
||||
|
||||
private GameObject _children = null!;
|
||||
private RectTransform _children = null!;
|
||||
private GameObject _modTemplate = null!;
|
||||
private PassiveButton _toggleButton = null!;
|
||||
private TextMeshPro _toggleBtnText = null!;
|
||||
|
||||
private RectTransform _pagination = null!;
|
||||
private TextMeshPro _pageText = null!;
|
||||
private PassiveButton _nextButton = null!;
|
||||
private PassiveButton _backButton = null!;
|
||||
|
||||
private int _currentPage = 0;
|
||||
private const int _itemsPerPage = 3;
|
||||
|
||||
private readonly Dictionary<BaseModifier, ModifierUiComponent> _modifiers = [];
|
||||
|
||||
/// <summary>
|
||||
@@ -45,7 +54,7 @@ public class ModifierDisplayComponent(nint ptr) : MonoBehaviour(ptr)
|
||||
{
|
||||
Instance = this;
|
||||
|
||||
_children = transform.GetChild(0).gameObject;
|
||||
_children = transform.GetChild(0).GetComponent<RectTransform>();
|
||||
_modTemplate = transform.GetChild(2).gameObject;
|
||||
|
||||
_toggleButton = transform.GetChild(1).GetComponent<PassiveButton>();
|
||||
@@ -60,13 +69,49 @@ public class ModifierDisplayComponent(nint ptr) : MonoBehaviour(ptr)
|
||||
_toggleButton.HoverSound = HudManager.Instance.GameMenu.StreamerModeButton.GetComponent<PassiveButton>().HoverSound;
|
||||
_toggleButton.inactiveSprites = _toggleButton.transform.GetChild(1).gameObject;
|
||||
_toggleBtnText = _toggleButton.transform.GetChild(0).GetComponent<TextMeshPro>();
|
||||
_toggleBtnText.font = HudManager.Instance.TaskPanel.taskText.font;
|
||||
_toggleBtnText.fontMaterial = HudManager.Instance.TaskPanel.taskText.fontMaterial;
|
||||
|
||||
_pagination = _children.transform.GetChild(0).GetComponent<RectTransform>();
|
||||
_pageText = _pagination.transform.GetChild(0).GetComponent<TextMeshPro>();
|
||||
_nextButton = _pagination.transform.GetChild(1).GetComponent<PassiveButton>();
|
||||
_backButton = _pagination.transform.GetChild(2).GetComponent<PassiveButton>();
|
||||
|
||||
_toggleBtnText.font = _pageText.font = _nextButton.buttonText.font = _backButton.buttonText.font = HudManager.Instance.TaskPanel.taskText.font;
|
||||
_toggleBtnText.fontMaterial = _pageText.fontMaterial = _nextButton.buttonText.fontMaterial = _backButton.buttonText.fontMaterial = HudManager.Instance.TaskPanel.taskText.fontMaterial;
|
||||
|
||||
_nextButton.OnClick = new Button.ButtonClickedEvent();
|
||||
_nextButton.OnClick.AddListener((UnityAction)(() =>
|
||||
{
|
||||
_currentPage++;
|
||||
UpdatePage();
|
||||
}));
|
||||
|
||||
_backButton.OnClick = new Button.ButtonClickedEvent();
|
||||
_backButton.OnClick.AddListener((UnityAction)(() =>
|
||||
{
|
||||
_currentPage--;
|
||||
UpdatePage();
|
||||
}));
|
||||
|
||||
IsOpen = false;
|
||||
_children.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this to refresh the modifiers UI. Useful if you hide modifiers uis based on options.
|
||||
/// </summary>
|
||||
public void RefreshModifiers()
|
||||
{
|
||||
UpdateModifiersList([.. PlayerControl.LocalPlayer.GetModifierComponent().ActiveModifiers]);
|
||||
}
|
||||
|
||||
internal void DestroyComponent(ModifierUiComponent component)
|
||||
{
|
||||
_modifiers.Remove(component.Modifier!);
|
||||
component.gameObject.DestroyImmediate();
|
||||
|
||||
RefreshModifiers();
|
||||
}
|
||||
|
||||
[HideFromIl2Cpp]
|
||||
internal static ModifierDisplayComponent CreateDisplay()
|
||||
{
|
||||
@@ -82,20 +127,54 @@ public class ModifierDisplayComponent(nint ptr) : MonoBehaviour(ptr)
|
||||
newMod.transform.name = modifier.ModifierName;
|
||||
var comp = newMod.AddComponent<ModifierUiComponent>();
|
||||
comp.Modifier = modifier;
|
||||
newMod.gameObject.SetActive(true);
|
||||
return comp;
|
||||
}
|
||||
|
||||
private void UpdatePage()
|
||||
{
|
||||
var totalPages = Mathf.CeilToInt((float)_modifiers.Count / _itemsPerPage);
|
||||
_currentPage = Mathf.Clamp(_currentPage, 0, Mathf.Max(0, totalPages - 1));
|
||||
|
||||
if (_modifiers.Count <= _itemsPerPage)
|
||||
{
|
||||
_modifiers.Do(x => x.Value.gameObject.SetActive(true));
|
||||
_pagination.gameObject.SetActive(false);
|
||||
return;
|
||||
}
|
||||
|
||||
_pagination.gameObject.SetActive(true);
|
||||
if (_pageText != null)
|
||||
{
|
||||
_pageText.text = $"Page {_currentPage + 1}/{Mathf.Max(totalPages, 1)}";
|
||||
}
|
||||
|
||||
_nextButton.gameObject.SetActive(true);
|
||||
_backButton.gameObject.SetActive(true);
|
||||
|
||||
_modifiers.Do(x => x.Value.gameObject.SetActive(false));
|
||||
var start = _currentPage * _itemsPerPage;
|
||||
var end = Mathf.Min(start + _itemsPerPage, _modifiers.Count);
|
||||
var modifiers = _modifiers.ToArray();
|
||||
|
||||
for (var i = start; i < end; i++)
|
||||
{
|
||||
modifiers[i].Value.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
_pagination.SetAsLastSibling();
|
||||
}
|
||||
|
||||
[HideFromIl2Cpp]
|
||||
internal void UpdateModifiersList(List<BaseModifier> modifiers)
|
||||
{
|
||||
var filteredModifiers = modifiers.Where(x => !x.HideOnUi && x.GetDescription() != string.Empty).ToList();
|
||||
var modifiersToAdd = filteredModifiers.ToList();
|
||||
|
||||
foreach (var mod in _modifiers.ToArray())
|
||||
{
|
||||
if (filteredModifiers.Contains(mod.Key))
|
||||
if (modifiersToAdd.Contains(mod.Key))
|
||||
{
|
||||
filteredModifiers.Remove(mod.Key);
|
||||
modifiersToAdd.Remove(mod.Key);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -103,9 +182,9 @@ public class ModifierDisplayComponent(nint ptr) : MonoBehaviour(ptr)
|
||||
_modifiers.Remove(mod.Key);
|
||||
}
|
||||
|
||||
_toggleBtnText.text = $"Modifiers ({modifiers.Count})";
|
||||
_toggleBtnText.text = $"Modifiers ({filteredModifiers.Count})";
|
||||
|
||||
if (modifiers.Count == 0)
|
||||
if (filteredModifiers.Count == 0)
|
||||
{
|
||||
_toggleButton.gameObject.SetActive(false);
|
||||
return;
|
||||
@@ -113,9 +192,11 @@ public class ModifierDisplayComponent(nint ptr) : MonoBehaviour(ptr)
|
||||
|
||||
_toggleButton.gameObject.SetActive(true);
|
||||
|
||||
foreach (var mod in filteredModifiers)
|
||||
foreach (var mod in modifiersToAdd)
|
||||
{
|
||||
_modifiers.Add(mod, CreateForModifier(mod));
|
||||
}
|
||||
|
||||
UpdatePage();
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,12 @@ public class ModifierUiComponent(nint ptr) : MonoBehaviour(ptr)
|
||||
{
|
||||
if (Modifier == null || ModifierDisplayComponent.Instance == null || !ModifierDisplayComponent.Instance.IsOpen) return;
|
||||
|
||||
if (Modifier.HideOnUi || Modifier.GetDescription() == string.Empty)
|
||||
{
|
||||
ModifierDisplayComponent.Instance.DestroyComponent(this);
|
||||
return;
|
||||
}
|
||||
|
||||
nameText.text = Modifier.ModifierName;
|
||||
desc.text = Modifier.GetDescription();
|
||||
modBg.gameObject.SetActive(true);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using AmongUs.Data;
|
||||
using AmongUs.GameOptions;
|
||||
using Assets.CoreScripts;
|
||||
using BepInEx.Unity.IL2CPP.Utils;
|
||||
@@ -96,7 +97,7 @@ public static class CustomMurderRpc
|
||||
var flag = PlayerControl.LocalPlayer.Data.Role.Role == RoleTypes.GuardianAngel;
|
||||
if (flag && PlayerControl.LocalPlayer.Data.PlayerId == target.protectedByGuardianId)
|
||||
{
|
||||
StatsManager.Instance.IncrementStat(StringNames.StatsGuardianAngelCrewmatesProtected);
|
||||
DataManager.Player.Stats.IncrementStat(StatID.Role_GuardianAngel_CrewmatesProtected);
|
||||
AchievementManager.Instance.OnProtectACrewmate();
|
||||
}
|
||||
|
||||
@@ -127,14 +128,14 @@ public static class CustomMurderRpc
|
||||
DebugAnalytics.Instance.Analytics.Kill(target.Data, source.Data);
|
||||
if (source.AmOwner)
|
||||
{
|
||||
StatsManager.Instance.IncrementStat(
|
||||
DataManager.Player.Stats.IncrementStat(
|
||||
GameManager.Instance.IsHideAndSeek()
|
||||
? StringNames.StatsImpostorKills_HideAndSeek
|
||||
: StringNames.StatsImpostorKills);
|
||||
? StatID.HideAndSeek_ImpostorKills
|
||||
: StatID.ImpostorKills);
|
||||
|
||||
if (source.CurrentOutfitType == PlayerOutfitType.Shapeshifted)
|
||||
{
|
||||
StatsManager.Instance.IncrementStat(StringNames.StatsShapeshifterShiftedKills);
|
||||
DataManager.Player.Stats.IncrementStat(StatID.Role_Shapeshifter_ShiftedKills);
|
||||
}
|
||||
|
||||
if (Constants.ShouldPlaySfx() && playKillSound)
|
||||
@@ -152,7 +153,7 @@ public static class CustomMurderRpc
|
||||
target.gameObject.layer = LayerMask.NameToLayer("Ghost");
|
||||
if (target.AmOwner)
|
||||
{
|
||||
StatsManager.Instance.IncrementStat(StringNames.StatsTimesMurdered);
|
||||
DataManager.Player.Stats.IncrementStat(StatID.TimesMurdered);
|
||||
if (Minigame.Instance)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -44,4 +44,9 @@ public enum MiraRpc : uint
|
||||
/// Custom RPC to undo a player's vote.
|
||||
/// </summary>
|
||||
RemoveVote,
|
||||
|
||||
/// <summary>
|
||||
/// Custom RPC to replace Among Us CastVote
|
||||
/// </summary>
|
||||
CastVote,
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using HarmonyLib;
|
||||
|
||||
namespace MiraAPI.Patches;
|
||||
|
||||
[HarmonyPatch(typeof(Minigame), nameof(Minigame.Begin))]
|
||||
internal static class MinigameBeginErrorPatch
|
||||
{
|
||||
public static void Prefix(Minigame __instance)
|
||||
{
|
||||
__instance.logger ??= new Logger(Logger.Category.Gameplay, "Minigame");
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ namespace MiraAPI.Patches.Roles;
|
||||
/// <summary>
|
||||
/// Patches to return the correct role counts.
|
||||
/// </summary>
|
||||
[HarmonyPatch(typeof(RoleOptionsCollectionV08))]
|
||||
[HarmonyPatch(typeof(RoleOptionsCollectionV09))]
|
||||
public static class RoleOptionsCollectionPatch
|
||||
{
|
||||
/// <summary>
|
||||
@@ -16,7 +16,7 @@ public static class RoleOptionsCollectionPatch
|
||||
/// </summary>
|
||||
/// <returns>Return false to skip original method, true to not.</returns>
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(RoleOptionsCollectionV08.GetChancePerGame))]
|
||||
[HarmonyPatch(nameof(RoleOptionsCollectionV09.GetChancePerGame))]
|
||||
public static bool GetChancePrefix(RoleTypes role, ref int __result)
|
||||
{
|
||||
if (!CustomRoleManager.GetCustomRoleBehaviour(role, out var customRole) || customRole == null)
|
||||
@@ -46,7 +46,7 @@ public static class RoleOptionsCollectionPatch
|
||||
/// </summary>
|
||||
/// <returns>Return false to skip original method, true to not.</returns>
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(RoleOptionsCollectionV08.GetNumPerGame))]
|
||||
[HarmonyPatch(nameof(RoleOptionsCollectionV09.GetNumPerGame))]
|
||||
public static bool GetNumPrefix(RoleTypes role, ref int __result)
|
||||
{
|
||||
if (!CustomRoleManager.GetCustomRoleBehaviour(role, out var customRole) || customRole == null)
|
||||
|
||||
@@ -33,15 +33,4 @@ public static class MinigameStubs
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fixes the error when creating custom minigames. Credit to Submerged for discovering this fix.
|
||||
/// </summary>
|
||||
/// <param name="__instance">The Minigame instance.</param>
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(Minigame), nameof(Minigame.Begin))]
|
||||
public static void MinigameErrorFixPatch(Minigame __instance)
|
||||
{
|
||||
__instance.logger ??= new Logger("Minigame", Logger.Level.Info, Logger.Category.Gameplay);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using MiraAPI.Events.Vanilla.Meeting.Voting;
|
||||
using MiraAPI.Modifiers;
|
||||
using MiraAPI.Utilities;
|
||||
using MiraAPI.Voting;
|
||||
using Reactor.Utilities;
|
||||
|
||||
namespace MiraAPI.Patches.Voting;
|
||||
|
||||
@@ -140,84 +141,6 @@ internal static class MeetingHudPatches
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(MeetingHud.CastVote))]
|
||||
public static bool CastVotePatch(MeetingHud __instance, byte srcPlayerId, byte suspectPlayerId)
|
||||
{
|
||||
var plr = GameData.Instance.GetPlayerById(srcPlayerId);
|
||||
|
||||
if (plr == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var voteData = plr.Object.GetVoteData();
|
||||
if (voteData == null || voteData.VotesRemaining == 0 ||
|
||||
voteData.VotedFor(suspectPlayerId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
VotingUtils.HandleVote(voteData, suspectPlayerId);
|
||||
|
||||
__instance.SetDirtyBit(1U);
|
||||
__instance.CheckForEndVoting();
|
||||
|
||||
if (voteData.VotesRemaining != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
__instance.playerStates.First(x => x.TargetPlayerId == srcPlayerId).SetVote(suspectPlayerId);
|
||||
PlayerControl.LocalPlayer.RpcSendChatNote(srcPlayerId, ChatNoteTypes.DidVote);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(nameof(MeetingHud.CmdCastVote))]
|
||||
public static void CmdCastVotePatch(MeetingHud __instance, byte playerId, byte suspectIdx)
|
||||
{
|
||||
var plr = GameData.Instance.GetPlayerById(playerId);
|
||||
var voteData = plr.Object.GetVoteData();
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost)
|
||||
{
|
||||
if (voteData == null || voteData.VotesRemaining == 0 ||
|
||||
voteData.VotedFor(suspectIdx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
VotingUtils.HandleVote(voteData, suspectIdx);
|
||||
|
||||
if (voteData.VotesRemaining == 0)
|
||||
{
|
||||
__instance.playerStates.First(x => x.TargetPlayerId == playerId).SetVote(suspectIdx);
|
||||
}
|
||||
}
|
||||
|
||||
if (PlayerControl.LocalPlayer.PlayerId != playerId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SoundManager.Instance.PlaySound(__instance.VoteLockinSound, false);
|
||||
|
||||
foreach (var playerVoteArea in __instance.playerStates)
|
||||
{
|
||||
playerVoteArea.ClearButtons();
|
||||
}
|
||||
|
||||
__instance.SkipVoteButton.ClearButtons();
|
||||
|
||||
var localVoteData = PlayerControl.LocalPlayer.GetVoteData();
|
||||
if (localVoteData == null || localVoteData.VotesRemaining != 0) return;
|
||||
|
||||
__instance.SkipVoteButton.voteComplete = true;
|
||||
__instance.SkipVoteButton.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(MeetingHud.CheckForEndVoting))]
|
||||
public static bool EndCheck(MeetingHud __instance)
|
||||
@@ -280,12 +203,20 @@ internal static class MeetingHudPatches
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: figure out a way to do host-authorization since right now any player can send RpcCastVote
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(MeetingHud.CmdCastVote))]
|
||||
public static bool CmdCastVoteOverridePatch(MeetingHud __instance, byte playerId, byte suspectIdx)
|
||||
{
|
||||
VotingUtils.RpcCastVote(PlayerControl.LocalPlayer, playerId, suspectIdx);
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(MeetingHud.Confirm))]
|
||||
public static bool ConfirmPatch(MeetingHud __instance, [HarmonyArgument(0)] byte suspect)
|
||||
{
|
||||
__instance.CmdCastVote(PlayerControl.LocalPlayer.PlayerId, suspect);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -41,16 +41,26 @@ public static class VotingUtils
|
||||
/// </summary>
|
||||
/// <param name="voteData">The player's vote data.</param>
|
||||
/// <param name="suspectIdx">Who the player voted for.</param>
|
||||
public static void HandleVote(PlayerVoteData voteData, byte suspectIdx)
|
||||
/// <param name="cancelVote">Whether you want the vote to commence or not.</param>
|
||||
private static void HandleVote(PlayerVoteData voteData, byte suspectIdx, out bool cancelVote)
|
||||
{
|
||||
var @event = new HandleVoteEvent(voteData, suspectIdx);
|
||||
MiraEventManager.InvokeEvent(@event);
|
||||
|
||||
cancelVote = @event.PreventVote;
|
||||
|
||||
if (@event.IsCancelled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (voteData.VotesRemaining == 0 ||
|
||||
voteData.VotedFor(suspectIdx))
|
||||
{
|
||||
cancelVote = true;
|
||||
return;
|
||||
}
|
||||
|
||||
voteData.DecreaseRemainingVotes(1);
|
||||
voteData.VoteForPlayer(suspectIdx);
|
||||
}
|
||||
@@ -64,10 +74,7 @@ public static class VotingUtils
|
||||
[MethodRpc((uint)MiraRpc.RemoveVote)]
|
||||
public static void RpcRemoveVote(PlayerControl source, byte voterId, byte votedFor)
|
||||
{
|
||||
if (source.OwnerId != AmongUsClient.Instance.HostId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!source.IsHost()) return;
|
||||
|
||||
MeetingHud.Instance.playerStates.First(state => state.TargetPlayerId == voterId).UnsetVote();
|
||||
|
||||
@@ -94,6 +101,65 @@ public static class VotingUtils
|
||||
MeetingHud.Instance.SkipVoteButton.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Networks the casting of a vote. We replace the vanilla solution with a custom version that works for the use case.
|
||||
/// </summary>
|
||||
/// <param name="source">The player who sent this RPC.</param>
|
||||
/// <param name="srcPlayerId">The id of the player who casted the vote.</param>
|
||||
/// <param name="suspectPlayerId">The voted player's id.</param>
|
||||
[MethodRpc((uint)MiraRpc.CastVote)]
|
||||
public static void RpcCastVote(PlayerControl source, byte srcPlayerId, byte suspectPlayerId)
|
||||
{
|
||||
CustomCastVote(srcPlayerId, suspectPlayerId);
|
||||
}
|
||||
|
||||
private static void CustomCastVote(byte srcPlayerId, byte suspectPlayerId)
|
||||
{
|
||||
var plr = GameData.Instance.GetPlayerById(srcPlayerId);
|
||||
if (!plr) return;
|
||||
|
||||
var voteData = plr.Object.GetVoteData();
|
||||
if (!voteData) return;
|
||||
|
||||
HandleVote(voteData, suspectPlayerId, out var cancelVote);
|
||||
|
||||
// Handle local behaviour for the voter (for some reason checking AmOwner does not work for host)
|
||||
if (PlayerControl.LocalPlayer.PlayerId == srcPlayerId)
|
||||
{
|
||||
if (!cancelVote) SoundManager.Instance.PlaySound(MeetingHud.Instance.VoteLockinSound, false);
|
||||
|
||||
foreach (var playerVoteArea in MeetingHud.Instance.playerStates)
|
||||
{
|
||||
playerVoteArea.ClearButtons();
|
||||
}
|
||||
|
||||
MeetingHud.Instance.SkipVoteButton.ClearButtons();
|
||||
|
||||
var localVoteData = PlayerControl.LocalPlayer.GetVoteData();
|
||||
if (!localVoteData || localVoteData.VotesRemaining != 0) return;
|
||||
|
||||
MeetingHud.Instance.SkipVoteButton.voteComplete = true;
|
||||
MeetingHud.Instance.SkipVoteButton.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
if (cancelVote) return;
|
||||
|
||||
// If player has no more votes, then make it show that the player has used all their votes.
|
||||
if (voteData.VotesRemaining == 0)
|
||||
{
|
||||
MeetingHud.Instance.playerStates.First(x => x.TargetPlayerId == srcPlayerId).SetVote(suspectPlayerId);
|
||||
}
|
||||
|
||||
// If host, then check end voting, and set votes/send chat if applicable
|
||||
if (!PlayerControl.LocalPlayer.IsHost()) return;
|
||||
|
||||
MeetingHud.Instance.SetDirtyBit(1U);
|
||||
MeetingHud.Instance.CheckForEndVoting();
|
||||
|
||||
if (voteData.VotesRemaining != 0) return;
|
||||
PlayerControl.LocalPlayer.RpcSendChatNote(srcPlayerId, ChatNoteTypes.DidVote);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the total number of votes.
|
||||
/// </summary>
|
||||
|
||||
Reference in new issue
Block a user