diff --git a/Si_CommManagement/CommanderApplications.cs b/Si_CommManagement/CommanderApplications.cs index 187e0e6..cabe1c5 100644 --- a/Si_CommManagement/CommanderApplications.cs +++ b/Si_CommManagement/CommanderApplications.cs @@ -143,6 +143,8 @@ public static void Postfix(MusicJukeboxHandler __instance, GameMode __0) { try { + Mutineer.ClearMutineerList(); + if (CommanderApplications.commanderApplicants == null || CommanderApplications.previousCommanders == null || promotedCommanders == null) { return; diff --git a/Si_CommManagement/Mutineer.cs b/Si_CommManagement/Mutineer.cs new file mode 100644 index 0000000..47cc851 --- /dev/null +++ b/Si_CommManagement/Mutineer.cs @@ -0,0 +1,143 @@ +/* +Silica Commander Management Mod +Copyright (C) 2023-2024 by databomb + +* License * +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#if NET6_0 +using Il2Cpp; +#endif + +using HarmonyLib; +using SilicaAdminMod; +using System; +using System.Collections.Generic; +using UnityEngine; +using MelonLoader; + +namespace Si_CommanderManagement +{ + public class Mutineer + { + public static void InitializeMutineerList() + { + CommanderManager.mutineerPlayers = new List[SiConstants.MaxPlayableTeams + 1]; + for (int i = 0; i < SiConstants.MaxPlayableTeams; i++) + { + CommanderManager.mutineerPlayers[i] = new List(); + } + } + + public static void ClearMutineerList() + { + for (int i = 0; i < SiConstants.MaxPlayableTeams; i++) + { + CommanderManager.mutineerPlayers[i].Clear(); + } + } + + public static void Command_Mutiny(Player? callerPlayer, String args) + { + if (callerPlayer == null) + { + HelperMethods.SendChatMessageToPlayer(callerPlayer, HelperMethods.chatPrefix, " Console not supported."); + return; + } + + if (callerPlayer.Team == null) + { + HelperMethods.SendChatMessageToPlayer(callerPlayer, HelperMethods.chatPrefix, " On invalid team."); + return; + } + + if (!GameMode.CurrentGameMode.GameOngoing) + { + HelperMethods.SendChatMessageToPlayer(callerPlayer, HelperMethods.chatPrefix, " Cannot mutiny at this time."); + return; + } + + if (callerPlayer.IsCommander) + { + HelperMethods.SendChatMessageToPlayer(callerPlayer, HelperMethods.chatPrefix, " Cannot mutiny when commader."); + return; + } + + MP_Strategy strategyInstance = GameObject.FindObjectOfType(); + if (strategyInstance.GetCommanderForTeam(callerPlayer.Team) == null) + { + HelperMethods.SendChatMessageToPlayer(callerPlayer, HelperMethods.chatPrefix, " Cannot mutiny when no one is commander."); + return; + } + + // did the player already vote for surrender? + if (CommanderManager.mutineerPlayers[callerPlayer.Team.Index].Contains(callerPlayer)) + { + HelperMethods.SendChatMessageToPlayer(callerPlayer, HelperMethods.chatPrefix, " Already voted to mutiny. ", MoreMutinyVotesNeeded(callerPlayer.Team).ToString(), " more players needed."); + return; + } + + CommanderManager.mutineerPlayers[callerPlayer.Team.Index].Add(callerPlayer); + + // if we haven't met the threshold then send a message to the teammates + if (CommanderManager.mutineerPlayers[callerPlayer.Team.Index].Count < TeammatesNeededForMutiny(callerPlayer.Team)) + { + HelperMethods.SendChatMessageToTeamNoCommander(callerPlayer.Team, HelperMethods.chatPrefix, HelperMethods.GetTeamColor(callerPlayer), " ", callerPlayer.PlayerName, " wants to mutiny. ", MoreMutinyVotesNeeded(callerPlayer.Team).ToString(), " more players needed."); + return; + } + + Mutiny(strategyInstance, callerPlayer.Team); + } + public static int TeammatesNeededForMutiny(Team team) + { + int playerCount = team.GetNumPlayers(); + + // don't count the commander as a player here + MP_Strategy strategyInstance = GameObject.FindObjectOfType(); + playerCount -= (strategyInstance.GetCommanderForTeam(team) != null ? 1 : 0); + + int teammatesNeeded = (int)Math.Ceiling(playerCount * 0.54f); + if (teammatesNeeded < 1) + { + return 1; + } + + return teammatesNeeded; + } + + public static int MoreMutinyVotesNeeded(Team team) + { + int teammatesNeeded = TeammatesNeededForMutiny(team); + int moreNeeded = teammatesNeeded - CommanderManager.mutineerPlayers[team.Index].Count; + if (moreNeeded < 1) + { + return 1; + } + + return moreNeeded; + } + + public static void Mutiny(MP_Strategy strategyInstance, Team team) + { + // notify all players + HelperMethods.ReplyToCommand(HelperMethods.GetTeamColor(team) + team.TeamShortName + " had a mutiny against the current commander."); + + CommanderPrimitives.DemoteTeamsCommander(strategyInstance, team); + + // clear all people who voted for a mutiny + ClearMutineerList(); + } + } +} \ No newline at end of file diff --git a/Si_CommManagement/Si_CommanderManager.cs b/Si_CommManagement/Si_CommanderManager.cs index c1d7c10..22b219a 100644 --- a/Si_CommManagement/Si_CommanderManager.cs +++ b/Si_CommManagement/Si_CommanderManager.cs @@ -32,8 +32,9 @@ You should have received a copy of the GNU General Public License using System; using SilicaAdminMod; using System.Linq; +using System.Collections.Generic; -[assembly: MelonInfo(typeof(CommanderManager), "Commander Management", "1.7.0", "databomb", "https://github.com/data-bomb/Silica")] +[assembly: MelonInfo(typeof(CommanderManager), "Commander Management", "1.8.0", "databomb", "https://github.com/data-bomb/Silica")] [assembly: MelonGame("Bohemia Interactive", "Silica")] [assembly: MelonOptionalDependencies("Admin Mod")] @@ -45,6 +46,8 @@ public class CommanderManager : MelonMod public static MelonPreferences_Entry _BlockRoundStartUntilEnoughApplicants = null!; public static MelonPreferences_Entry _TeamOnlyResponses = null!; + public static List[] mutineerPlayers = null!; + public override void OnInitializeMelon() { _modCategory ??= MelonPreferences.CreateCategory("Silica"); @@ -55,6 +58,7 @@ public override void OnInitializeMelon() { CommanderBans.InitializeList(); CommanderApplications.InitializeApplications(); + Mutineer.InitializeMutineerList(); } catch (Exception error) { @@ -80,6 +84,9 @@ public override void OnLateInitializeMelon() HelperMethods.CommandCallback commanderCallback = CommanderApplications.Command_Commander; HelperMethods.RegisterPlayerCommand("commander", commanderCallback, true); + HelperMethods.CommandCallback mutinyCallback = Mutineer.Command_Mutiny; + HelperMethods.RegisterPlayerCommand("mutiny", mutinyCallback, true); + // subscribe to the OnRequestCommander event Event_Roles.OnRequestCommander += OnRequestCommander; @@ -95,6 +102,10 @@ public override void OnLateInitializeMelon() QList.Options.AddOption(dontStartWithoutCommanders); #endif } + public override void OnSceneWasLoaded(int buildIndex, string sceneName) + { + Mutineer.ClearMutineerList(); + } public void OnRequestCommander(object? sender, OnRequestCommanderArgs args) {