From 9f398ff498c9d444fa3d5808a3cac9b0b8b882ec Mon Sep 17 00:00:00 2001 From: TImeMaster Date: Wed, 2 Oct 2024 03:02:27 +0200 Subject: [PATCH] Add option for ally bots in siege --- .../Configuration/GameConfig.cs | 1 + .../Forms/LauncherMainForm.Designer.cs | 59 ++++++++------ .../Forms/LauncherMainForm.cs | 78 ++++++++++++++++--- .../Forms/LauncherMainForm.resx | 24 +++--- .../GameFiles/Config/DefaultGame.cs | 26 ++++--- SingleplayerLauncher/GameLauncher.cs | 4 +- SingleplayerLauncher/Model/GameInfo.cs | 5 +- 7 files changed, 141 insertions(+), 56 deletions(-) diff --git a/SingleplayerLauncher/Configuration/GameConfig.cs b/SingleplayerLauncher/Configuration/GameConfig.cs index d5c8537..6e32e8c 100644 --- a/SingleplayerLauncher/Configuration/GameConfig.cs +++ b/SingleplayerLauncher/Configuration/GameConfig.cs @@ -19,6 +19,7 @@ public class GameConfig : IConfiguration public string Battleground { get; set; } public string SiegeBattleground { get; set; } public bool SiegeEnemyTeamAsBots { get; set; } + public bool SiegeAllyBots { get; set; } public string ExtraDifficulty { get; set; } public string SiegeBotDifficulty { get; set; } public bool GodMode { get; set; } diff --git a/SingleplayerLauncher/Forms/LauncherMainForm.Designer.cs b/SingleplayerLauncher/Forms/LauncherMainForm.Designer.cs index 8d888eb..6534411 100644 --- a/SingleplayerLauncher/Forms/LauncherMainForm.Designer.cs +++ b/SingleplayerLauncher/Forms/LauncherMainForm.Designer.cs @@ -56,6 +56,8 @@ private void InitializeComponent() chkNoTrapCap = new CheckBox(); chkGodMode = new CheckBox(); modsGroupBox = new GroupBox(); + label3 = new Label(); + labelOverrideLevels = new Label(); chkOverrideTrapTier = new CheckBox(); inputOverrideTrapTier = new NumericUpDown(); chkOverrideAccountLevel = new CheckBox(); @@ -295,8 +297,7 @@ private void InitializeComponent() comBoxSiegeLoadoutSlot5 = new ComboBox(); comBoxSiegeLoadoutSlot7 = new ComboBox(); comBoxSiegeLoadoutSlot6 = new ComboBox(); - labelOverrideLevels = new Label(); - label3 = new Label(); + chkSiegeAllyBots = new CheckBox(); battlegroundGroupBox.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)startingCoinInput).BeginInit(); modsGroupBox.SuspendLayout(); @@ -616,6 +617,28 @@ private void InitializeComponent() modsGroupBox.TabStop = false; modsGroupBox.Text = "Mods"; // + // label3 + // + label3.AutoSize = true; + label3.BackColor = System.Drawing.Color.Pink; + label3.Font = new System.Drawing.Font("Segoe UI", 9F); + label3.Location = new System.Drawing.Point(31, 19); + label3.Name = "label3"; + label3.Size = new System.Drawing.Size(319, 30); + label3.TabIndex = 81; + label3.Text = "Disclaimer: Using mods can lead to unexpected outcomes. \r\n Some of the mods won't work in multiplayer."; + // + // labelOverrideLevels + // + labelOverrideLevels.AutoSize = true; + labelOverrideLevels.BackColor = System.Drawing.Color.Thistle; + labelOverrideLevels.Font = new System.Drawing.Font("Segoe UI", 7F); + labelOverrideLevels.Location = new System.Drawing.Point(265, 276); + labelOverrideLevels.Name = "labelOverrideLevels"; + labelOverrideLevels.Size = new System.Drawing.Size(130, 48); + labelOverrideLevels.TabIndex = 80; + labelOverrideLevels.Text = "Account Level and Trap Tiers\r\nare auto adjusted to match \r\nthe enemy and map level. \r\nBut can be overriden here.\r\n"; + // // chkOverrideTrapTier // chkOverrideTrapTier.AutoSize = true; @@ -2250,6 +2273,7 @@ private void InitializeComponent() // // tabPage8 // + tabPage8.Controls.Add(chkSiegeAllyBots); tabPage8.Controls.Add(groupBox1); tabPage8.Controls.Add(label21); tabPage8.Controls.Add(maskedTextBoxSiegeHostGamePlayer8Loadout); @@ -3384,27 +3408,17 @@ private void InitializeComponent() comBoxSiegeLoadoutSlot6.TabIndex = 5; comBoxSiegeLoadoutSlot6.SelectedIndexChanged += comBoxSiegeLoadoutSlot6_SelectedIndexChanged; // - // labelOverrideLevels + // chkSiegeAllyBots // - labelOverrideLevels.AutoSize = true; - labelOverrideLevels.BackColor = System.Drawing.Color.Thistle; - labelOverrideLevels.Font = new System.Drawing.Font("Segoe UI", 7F); - labelOverrideLevels.Location = new System.Drawing.Point(265, 276); - labelOverrideLevels.Name = "labelOverrideLevels"; - labelOverrideLevels.Size = new System.Drawing.Size(130, 48); - labelOverrideLevels.TabIndex = 80; - labelOverrideLevels.Text = "Account Level and Trap Tiers\r\nare auto adjusted to match \r\nthe enemy and map level. \r\nBut can be overriden here.\r\n"; - // - // label3 - // - label3.AutoSize = true; - label3.BackColor = System.Drawing.Color.Pink; - label3.Font = new System.Drawing.Font("Segoe UI", 9F); - label3.Location = new System.Drawing.Point(31, 19); - label3.Name = "label3"; - label3.Size = new System.Drawing.Size(319, 30); - label3.TabIndex = 81; - label3.Text = "Disclaimer: Using mods can lead to unexpected outcomes. \r\n Some of the mods won't work in multiplayer."; + chkSiegeAllyBots.AutoSize = true; + chkSiegeAllyBots.Location = new System.Drawing.Point(190, 82); + chkSiegeAllyBots.Margin = new Padding(4, 3, 4, 3); + chkSiegeAllyBots.Name = "chkSiegeAllyBots"; + chkSiegeAllyBots.Size = new System.Drawing.Size(147, 19); + chkSiegeAllyBots.TabIndex = 98; + chkSiegeAllyBots.Text = "Fill Team with Ally Bots"; + chkSiegeAllyBots.UseVisualStyleBackColor = true; + chkSiegeAllyBots.CheckedChanged += chkSiegeAllyBots_CheckedChanged; // // LauncherMainForm // @@ -3732,6 +3746,7 @@ private void InitializeComponent() private NumericUpDown inputOverrideAccountLevel; private Label labelOverrideLevels; private Label label3; + private CheckBox chkSiegeAllyBots; } } diff --git a/SingleplayerLauncher/Forms/LauncherMainForm.cs b/SingleplayerLauncher/Forms/LauncherMainForm.cs index 743ec30..0ceaa8d 100644 --- a/SingleplayerLauncher/Forms/LauncherMainForm.cs +++ b/SingleplayerLauncher/Forms/LauncherMainForm.cs @@ -196,6 +196,7 @@ .. ComBoxSiegeLoadoutTrapSlots comBoxGameMode.SelectedItem = GameConfig.Instance.GameMode; // Siege Game settings + chkSiegeAllyBots.Visible = false; PopulateSlots([comBoxSiegeBattleground], [.. Model.Siege.SiegeBattlegrounds.Keys], addEmptyOption: false); comBoxSiegeBattleground.SelectedItem = comBoxSiegeBattleground.Items[0]; PopulateSlots([comBoxSiegeDifficulty], [.. BotDifficulty.BotDifficultiesByName.Keys], addEmptyOption: false, sort: false); @@ -1409,8 +1410,8 @@ private void btnJoinSiegeGame_Click(object sender, EventArgs e) private void btnSiegeLaunch_Click(object sender, EventArgs e) { bool isSiegeCoop = GameConfig.Instance.SiegeEnemyTeamAsBots; + bool isSiegeAllyBots = GameConfig.Instance.SiegeAllyBots; - GameLauncher.ApplyChanges(isHost: true, isSiege: true, isSiegeCoop: isSiegeCoop); SaveSettings(); string playerName = maskedTextBoxSiegePlayerName.Text; @@ -1430,8 +1431,10 @@ private void btnSiegeLaunch_Click(object sender, EventArgs e) return; } - ApplyAllSiegeLoadouts(isSiegeCoop); + ApplyAllSiegeLoadouts(isSiegeCoop, isSiegeAllyBots); GameInfo.PlayerCount = siegeLoadouts.Count(loadout => !string.IsNullOrWhiteSpace(loadout.Text)); + + GameLauncher.ApplyChanges(isHost: true, isSiege: true, isSiegeCoop: isSiegeCoop, isSiegeAllyBots: isSiegeAllyBots); // Must be run after ApplyAllSiegeLoadouts due to counting and preparing the ally bots loadouts GameLauncher.StartGame(GameInfo.SiegeLoadout.PlayerName, isHost: true, mapCode: GameInfo.SiegeBattleground.Map.UmapCode, playerCount: GameInfo.PlayerCount); } @@ -1441,16 +1444,20 @@ private void chkSiegeEnemyTeamAsBots_CheckedChanged(object sender, EventArgs e) if (comBoxSiegeDifficulty.Enabled) { + chkSiegeAllyBots.Visible = true; + siegeLoadoutsTeamAux.Clear(); - foreach (MaskedTextBox siegeLoadoutMaskedBox in siegeLoadoutsTeam2) + foreach (MaskedTextBox siegeLoadoutMaskedBox in siegeLoadoutsTeam2) { siegeLoadoutsTeamAux.Add(siegeLoadoutMaskedBox.Text); siegeLoadoutMaskedBox.Clear(); siegeLoadoutMaskedBox.Enabled = false; } - } + } else { + chkSiegeAllyBots.Visible = false; + foreach (MaskedTextBox siegeLoadoutMaskedBox in siegeLoadoutsTeam2) { if (siegeLoadoutsTeamAux.Count > 0) @@ -1467,6 +1474,14 @@ private void chkSiegeEnemyTeamAsBots_CheckedChanged(object sender, EventArgs e) GameConfig.Instance.Save(); } + + + private void chkSiegeAllyBots_CheckedChanged(object sender, EventArgs e) + { + GameConfig.Instance.SiegeAllyBots = chkSiegeAllyBots.Checked; + GameConfig.Instance.Save(); + } + private void comBoxSiegeDifficulty_SelectedIndexChanged(object sender, EventArgs e) { GameConfig.Instance.SiegeBotDifficulty = comBoxSiegeDifficulty.Text; @@ -1504,19 +1519,28 @@ private List ValidateAllSiegeLoadoutCodes() return invalidLoadouts; } - private void ApplyAllSiegeLoadouts(bool isSiegeCoop = false) + private void ApplyAllSiegeLoadouts(bool isSiegeCoop = false, bool isSiegeAllyBots = false) { bool randomBool = random.Next(0, 2) == 0; int team1 = randomBool ? 1 : 2; int team2 = randomBool ? 2 : 1; - foreach (var siegeLoadoutTextBox in siegeLoadoutsTeam1) + int team1Defenders = 0; + int team1PlayerCount = 0; + + foreach (var siegeLoadoutTextBox in siegeLoadoutsTeam1) { if (!string.IsNullOrWhiteSpace(siegeLoadoutTextBox.Text)) { + team1PlayerCount++; SiegeLoadout siegeLoadout = new(); - GameFiles.CharacterData.ApplySiegeLoadout((SiegeLoadout)siegeLoadout.Decode(siegeLoadoutTextBox.Text), team1); + siegeLoadout = (SiegeLoadout)siegeLoadout.Decode(siegeLoadoutTextBox.Text); + if (siegeLoadout.Role == SiegeRole.Defender) + { + team1Defenders++; + } + GameFiles.CharacterData.ApplySiegeLoadout(siegeLoadout, team1); } } @@ -1530,16 +1554,50 @@ private void ApplyAllSiegeLoadouts(bool isSiegeCoop = false) GameFiles.CharacterData.ApplySiegeLoadout((SiegeLoadout)siegeLoadout.Decode(siegeLoadoutTextBox.Text), team2); } } - } + } else { string difficultyName = comBoxSiegeDifficulty.Text; BotDifficulty botDifficulty = BotDifficulty.BotDifficultiesByName[difficultyName]; - foreach (SiegeLoadout loadout in botDifficulty.botLoadouts) { + foreach (SiegeLoadout loadout in botDifficulty.botLoadouts) + { GameFiles.CharacterData.ApplySiegeLoadout(loadout, team2, overrideTrapLevel: botDifficulty.TrapTier); } - } + if (isSiegeAllyBots) + { + GameInfo.AllyBotsLoadouts.Clear(); + int allyBotCount = 0; + foreach (SiegeLoadout loadout in botDifficulty.botLoadouts) + { + if (allyBotCount + team1PlayerCount < 5) + { + if (loadout.Role == SiegeRole.Defender && team1Defenders >= 2) + { + continue; + } + + int team1Attackers = allyBotCount + team1PlayerCount - team1Defenders; + if (loadout.Role == SiegeRole.Attacker && team1Attackers >= 3) + { + continue; + } + + allyBotCount++; + if (loadout.Role == SiegeRole.Defender) + { + team1Defenders++; + } + + SiegeLoadout allyBotLoadout = new(); + allyBotLoadout = (SiegeLoadout)allyBotLoadout.Decode(loadout.Encode()); + allyBotLoadout.PlayerName = allyBotLoadout.PlayerName + "_ALLY"; + GameFiles.CharacterData.ApplySiegeLoadout(allyBotLoadout, team1, overrideTrapLevel: botDifficulty.TrapTier); + GameInfo.AllyBotsLoadouts.Add(allyBotLoadout); + } + } + } + } } private void btnCopySiegeLoadoutToClipboard_Click(object sender, EventArgs e) diff --git a/SingleplayerLauncher/Forms/LauncherMainForm.resx b/SingleplayerLauncher/Forms/LauncherMainForm.resx index 7feff7c..ce2505f 100644 --- a/SingleplayerLauncher/Forms/LauncherMainForm.resx +++ b/SingleplayerLauncher/Forms/LauncherMainForm.resx @@ -123,6 +123,18 @@ 25 + + +How it works? + - Peer to peer, LAN supported + - Online multiplayer step by step guide to setup in our Discord + - Play online using VPN software such as Radmin + + +Looking for group? Join our discord community! + - We have dedicated roles and channels for LFG and matchmaking + + @@ -173,18 +185,6 @@ How it works? - Play online using VPN software such as Radmin -Looking for group? Join our discord community! - - We have dedicated roles and channels for LFG and matchmaking - - - - -How it works? - - Peer to peer, LAN supported - - Online multiplayer step by step guide to setup in our Discord - - Play online using VPN software such as Radmin - - Looking for group? Join our discord community! - We have dedicated roles and channels for LFG and matchmaking diff --git a/SingleplayerLauncher/GameFiles/Config/DefaultGame.cs b/SingleplayerLauncher/GameFiles/Config/DefaultGame.cs index 69280c8..d05d4f0 100644 --- a/SingleplayerLauncher/GameFiles/Config/DefaultGame.cs +++ b/SingleplayerLauncher/GameFiles/Config/DefaultGame.cs @@ -3,6 +3,7 @@ using SingleplayerLauncher.Utils; using System; using System.IO; +using System.Windows.Forms; namespace SingleplayerLauncher.GameFiles { @@ -10,8 +11,6 @@ public static class DefaultGame { // TODO: make singleton - private static readonly GameInfo GameInfo = GameInfo.Instance; - private const string RDisplayColorInfoSection = "SpitfireGame.RDisplayColorInfo"; private const string RGameReplicationInfoSection = "SpitfireGame.RGameReplicationInfo"; private const string RHUDBaseSection = "SpitfireGame.RHUDBase"; @@ -30,8 +29,8 @@ public static class DefaultGame public static void ApplySurvival() { - _ = GameInfo.SurvivalBattleground ?? throw new ArgumentNullException(nameof(Battleground), "Mandatory parameter"); - _ = GameInfo.SurvivalBattleground.Difficulty ?? throw new ArgumentNullException(nameof(Battleground.Difficulty), "Mandatory parameter"); + _ = GameInfo.Instance.SurvivalBattleground ?? throw new ArgumentNullException(nameof(Battleground), "Mandatory parameter"); + _ = GameInfo.Instance.SurvivalBattleground.Difficulty ?? throw new ArgumentNullException(nameof(Battleground.Difficulty), "Mandatory parameter"); _ = Mods.Mods.ShowTrapDamageFlyoffs ?? throw new ArgumentNullException(nameof(Mods.Mods.ShowTrapDamageFlyoffs), "Mandatory parameter"); _ = Mods.Mods.AccountLevelOverride ?? throw new ArgumentNullException(nameof(Mods.Mods.AccountLevelOverride), "Mandatory parameter"); @@ -39,11 +38,11 @@ public static void ApplySurvival() IniFile data = defaultGame.data; data.UpdateEntry(RHUDBaseSection, RHUDBaseKeyShowFlyoffsForTrapDamage, Mods.Mods.ShowTrapDamageFlyoffs.IsEnabled.ToString()); - data.UpdateEntry(RGameReplicationInfoSection, GameReplicationInfoKeyGameMode, GameInfo.SurvivalBattleground.GameMode.Id.ToString()); - data.UpdateEntry(RGameReplicationInfoSection, GameReplicationInfoKeyMapLevel, GameInfo.SurvivalBattleground.Difficulty.EnemyLevel.ToString()); - int accountLevel = Mods.Mods.AccountLevelOverride.IsEnabled ? Mods.Mods.AccountLevelOverride.Value : GameInfo.SurvivalBattleground.Difficulty.AccountLevel; + data.UpdateEntry(RGameReplicationInfoSection, GameReplicationInfoKeyGameMode, GameInfo.Instance.SurvivalBattleground.GameMode.Id.ToString()); + data.UpdateEntry(RGameReplicationInfoSection, GameReplicationInfoKeyMapLevel, GameInfo.Instance.SurvivalBattleground.Difficulty.EnemyLevel.ToString()); + int accountLevel = Mods.Mods.AccountLevelOverride.IsEnabled ? Mods.Mods.AccountLevelOverride.Value : GameInfo.Instance.SurvivalBattleground.Difficulty.AccountLevel; data.UpdateEntry(RGameReplicationInfoSection, GameReplicationInfoKeyPlayerLevel, accountLevel.ToString()); - data.UpdateEntry(RGameReplicationInfoSection, GameReplicationInfoKeyPlayerCount, GameInfo.SurvivalBattleground.Difficulty.PlayerCount.ToString()); + data.UpdateEntry(RGameReplicationInfoSection, GameReplicationInfoKeyPlayerCount, GameInfo.Instance.SurvivalBattleground.Difficulty.PlayerCount.ToString()); defaultGame.Write(); } @@ -60,7 +59,7 @@ public static void ApplySurvivalSettings() defaultGame.Write(); } - public static void ApplySiegeBots() + public static void ApplySiegeBots(bool isSiegeAllyBots = false) { _ = GameConfig.Instance.SiegeEnemyTeamAsBots ? true : throw new ArgumentNullException(nameof(GameConfig.Instance.SiegeEnemyTeamAsBots), "Mandatory parameter"); _ = GameConfig.Instance.SiegeBotDifficulty ?? throw new ArgumentNullException(nameof(GameConfig.Instance.SiegeBotDifficulty), "Mandatory parameter"); @@ -82,6 +81,15 @@ public static void ApplySiegeBots() botCount++; } + if (isSiegeAllyBots) + { + foreach (SiegeLoadout allyBotLoadout in GameInfo.Instance.AllyBotsLoadouts) + { + data.UpdateEntry(RGameStateSection, DebugBotPlayerIDs, allyBotLoadout.PlayerName, botCount); + botCount++; + } + } + defaultGame.Write(); } diff --git a/SingleplayerLauncher/GameLauncher.cs b/SingleplayerLauncher/GameLauncher.cs index 3a00537..c0efed6 100644 --- a/SingleplayerLauncher/GameLauncher.cs +++ b/SingleplayerLauncher/GameLauncher.cs @@ -11,7 +11,7 @@ class GameLauncher { private static readonly SpitfireGameUPK SpitfireGameUPK = new(); - public static void ApplyChanges(bool isHost, bool isSiege = false, int parTimeSeconds = 0, bool isSiegeCoop = false) + public static void ApplyChanges(bool isHost, bool isSiege = false, int parTimeSeconds = 0, bool isSiegeCoop = false, bool isSiegeAllyBots = false) { if (!isSiege) { @@ -36,7 +36,7 @@ public static void ApplyChanges(bool isHost, bool isSiege = false, int parTimeSe { if (isSiegeCoop) { - GameFiles.DefaultGame.ApplySiegeBots(); + GameFiles.DefaultGame.ApplySiegeBots(isSiegeAllyBots); } } diff --git a/SingleplayerLauncher/Model/GameInfo.cs b/SingleplayerLauncher/Model/GameInfo.cs index f47ec1b..026664c 100644 --- a/SingleplayerLauncher/Model/GameInfo.cs +++ b/SingleplayerLauncher/Model/GameInfo.cs @@ -1,4 +1,6 @@ -namespace SingleplayerLauncher.Model +using System.Collections.Generic; + +namespace SingleplayerLauncher.Model { public sealed class GameInfo { @@ -18,5 +20,6 @@ private GameInfo() { } public IBattleground SiegeBattleground { get; set; } = new Siege(); public int PlayerCount { get; set; } = 1; + public List AllyBotsLoadouts { get; set; } = []; } }