/// <summary> /// Initializes the skirmish game. /// </summary> public void InitializeSkirmishGame() { var playerNames = Game.Scene3D.MapFile.SidesList.Players.Select(p => p.Properties.GetPropOrNull("playerName")?.Value.ToString()).ToArray(); _playerScripts = new ScriptList[Game.Scene3D.Players.Count + 1]; // + 1 for neutral player @ index 0 CopyScripts(Game.Scene3D.PlayerScripts, playerNames, string.Empty, 0, appendIndex: false); // neutral CopyScripts(Game.Scene3D.PlayerScripts, playerNames, Game.CivilianPlayer.Name, 1, appendIndex: false); // Civilian var skirmishScriptsEntry = Game.ContentManager.GetScriptEntry(@"Data\Scripts\SkirmishScripts.scb"); if (skirmishScriptsEntry != null) { using (var stream = skirmishScriptsEntry.Open()) { var skirmishScripts = ScbFile.FromStream(stream); // skip civilian player for (int i = 1; i < Game.Scene3D.Players.Count; i++) { var player = Game.Scene3D.Players[i]; if (player.IsHuman) { // copy the scripts from the civilian player to all human players CopyScripts(skirmishScripts.PlayerScripts.ScriptLists, skirmishScripts.Players.PlayerNames, Game.CivilianPlayer.Name, i + 1, appendIndex: true); } else { // copy the scripts from the according skirmish player for all AI players CopyScripts(skirmishScripts.PlayerScripts.ScriptLists, skirmishScripts.Players.PlayerNames, "Skirmish" + player.Side, i + 1, appendIndex: true); } } } } }
public void CanRoundtripScbFiles() { InstalledFilesTestData.ReadFiles(".scb", _output, entry => { using (var fileStream = entry.Open()) { TestUtility.DoRoundtripTest( () => MapFile.Decompress(fileStream), stream => ScbFile.FromStream(stream), (scbFile, stream) => scbFile.WriteTo(stream)); } }); }
private static void SetupSkirmishGameSides( Game game, MapFile mapFile, PlayerSetting[] playerSettings, GameType gameType, List <Player> mapPlayers, List <Team> mapTeams, List <ScriptList> mapScriptLists) { var originalMapPlayers = mapFile.SidesList.Players; // Neutral player. mapPlayers.Add(originalMapPlayers[0]); // Civilian player. It isn't necessarily the second player. // TODO: There might be more than one civilian player. mapPlayers.Add(originalMapPlayers.FirstOrDefault(x => (string)x.Properties["playerFaction"].Value == "FactionCivilian")); //var hasAIPlayer = false; for (var i = 0; i < playerSettings.Length; i++) { var playerSetting = playerSettings[i]; var factionPlayer = originalMapPlayers.Single(x => (string)x.Properties["playerFaction"].Value == playerSetting.SideName); var isHuman = playerSetting.Owner == PlayerOwner.Player; var playerName = isHuman ? $"player{i}" : $"{factionPlayer.Properties["playerName"].Value}{i}"; //if (!isHuman) //{ // hasAIPlayer = true; //} var playerProperties = new AssetPropertyCollection(); playerProperties.AddAsciiString("playerFaction", (string)factionPlayer.Properties["playerFaction"].Value); playerProperties.AddAsciiString("playerName", playerName); playerProperties.AddAsciiString("playerDisplayName", (string)factionPlayer.Properties["playerDisplayName"].Value); playerProperties.AddBoolean("playerIsHuman", isHuman); playerProperties.AddInteger("playerColor", playerSetting.Color.ToUInt32()); // TODO: Other player properties. mapPlayers.Add(new Player { Properties = playerProperties, BuildList = factionPlayer.BuildList, }); } // Setup player relationships. var playerAllies = new string[playerSettings.Length]; var playerEnemies = new string[playerSettings.Length]; for (var i = 0; i < playerSettings.Length; i++) { playerAllies[i] = ""; playerEnemies[i] = ""; } for (var i = 0; i < playerSettings.Length; i++) { var outerPlayer = playerSettings[i]; for (var j = i + 1; j < playerSettings.Length; j++) { var innerPlayer = playerSettings[j]; if (outerPlayer.Team == innerPlayer.Team && outerPlayer.Team != 0) { playerAllies[i] += mapPlayers[j + 2].Properties["playerName"].Value + " "; playerAllies[j] += mapPlayers[i + 2].Properties["playerName"].Value + " "; } else { playerEnemies[i] += mapPlayers[j + 2].Properties["playerName"].Value + " "; playerEnemies[j] += mapPlayers[i + 2].Properties["playerName"].Value + " "; } } } for (var i = 0; i < playerSettings.Length; i++) { mapPlayers[i + 2].Properties.AddAsciiString("playerAllies", playerAllies[i]); mapPlayers[i + 2].Properties.AddAsciiString("playerEnemies", playerEnemies[i]); } var originalMapScriptLists = mapFile.SidesList.PlayerScripts.ScriptLists; var playerNames = mapPlayers .Select(p => p.Properties.GetPropOrNull("playerName")?.Value.ToString()) .ToArray(); while (mapScriptLists.Count < mapPlayers.Count) { mapScriptLists.Add(null); } // Copy neutral player scripts. var neutralPlayerName = (string)mapPlayers[0].Properties["playerName"].Value; CopyScripts( originalMapScriptLists, playerNames, neutralPlayerName, mapScriptLists, 0, appendIndex: false); // Copy civilian player scripts. var civilianPlayerName = (string)mapPlayers[1].Properties["playerName"].Value; CopyScripts( originalMapScriptLists, playerNames, civilianPlayerName, mapScriptLists, 1, appendIndex: false); var skirmishScriptsEntry = game.ContentManager.GetScriptEntry(@"Data\Scripts\SkirmishScripts.scb"); // TODO: Generals and ZH use SkirmishScripts.scb, // but later games use "libraries". if (skirmishScriptsEntry != null) { using var stream = skirmishScriptsEntry.Open(); var skirmishScripts = ScbFile.FromStream(stream); // This probably isn't right, but it does make the teams match those in .sav files. // We first add human player(s) teams, then the replay observer team, // then neutral and civilian teams, and then finally AI skirmish players. var skirmishScriptsPlayerNames = skirmishScripts.ScriptsPlayers.Players.Select(p => p.Name).ToArray(); // Skip neutral and civilian players. for (var i = 2; i < mapPlayers.Count; i++) { if ((bool)mapPlayers[i].Properties["playerIsHuman"].Value) { // Copy the scripts from the civilian player to all human players. CopyScripts( skirmishScripts.PlayerScripts.ScriptLists, skirmishScriptsPlayerNames, civilianPlayerName, mapScriptLists, i, appendIndex: true); mapTeams.Add(CreateDefaultTeam((string)mapPlayers[i].Properties["playerName"].Value)); } } mapTeams.Add(CreateDefaultTeam("ReplayObserver")); mapTeams.Add(CreateDefaultTeam(neutralPlayerName)); mapTeams.Add(CreateDefaultTeam(civilianPlayerName)); // Skip neutral and civilian players. for (var i = 2; i < mapPlayers.Count; i++) { if (!(bool)mapPlayers[i].Properties["playerIsHuman"].Value) { var playerSide = game.AssetStore.PlayerTemplates.GetByName(playerSettings[i - 2].SideName).Side; var sourcePlayerName = $"Skirmish{playerSide}"; // Copy the scripts from the according skirmish player for all AI players. CopyScripts( skirmishScripts.PlayerScripts.ScriptLists, skirmishScriptsPlayerNames, sourcePlayerName, mapScriptLists, i, appendIndex: true); // TODO: Not sure about the order the teams are added. foreach (var team in skirmishScripts.Teams.Teams) { var teamOwner = (string)team.Properties["teamOwner"].Value; if (teamOwner == sourcePlayerName) { var teamName = $"{team.Properties["teamName"].Value}{i}"; mapTeams.Add(CreateTeam( teamName, (string)mapPlayers[i].Properties["playerName"].Value, (bool)team.Properties["teamIsSingleton"].Value)); } } } } } if (playerSettings.Length > 1) { var multiplayerScriptsEntry = game.ContentManager.GetScriptEntry(@"Data\Scripts\MultiplayerScripts.scb"); if (multiplayerScriptsEntry != null) { using var stream = multiplayerScriptsEntry.Open(); var multiplayerScripts = ScbFile.FromStream(stream); // TODO: This is a bit hardcoded. mapScriptLists[0] = multiplayerScripts.PlayerScripts.ScriptLists[0]; } } }
private static void SetupSkirmishGameSides( Game game, MapFile mapFile, PlayerSetting[] playerSettings, GameType gameType, List <Player> mapPlayers, List <Team> mapTeams, List <ScriptList> mapScriptLists) { var originalMapPlayers = mapFile.SidesList.Players; // Neutral player. mapPlayers.Add(originalMapPlayers[0]); // Civilian player. It isn't necessarily the second player. // TODO: There might be more than one civilian player. mapPlayers.Add(originalMapPlayers.FirstOrDefault(x => (string)x.Properties["playerFaction"].Value == "FactionCivilian")); //var hasAIPlayer = false; for (var i = 0; i < playerSettings.Length; i++) { var playerSetting = playerSettings[i]; var factionPlayer = originalMapPlayers.First(x => (string)x.Properties["playerFaction"].Value == playerSetting.SideName); var isHuman = playerSetting.Owner == PlayerOwner.Player; var playerName = isHuman ? $"player{i}" : $"{factionPlayer.Properties["playerName"].Value}{i}"; //if (!isHuman) //{ // hasAIPlayer = true; //} var playerProperties = new AssetPropertyCollection(); playerProperties.AddAsciiString("playerFaction", (string)factionPlayer.Properties["playerFaction"].Value); playerProperties.AddAsciiString("playerName", playerName); playerProperties.AddAsciiString("playerDisplayName", (string)factionPlayer.Properties["playerDisplayName"].Value); playerProperties.AddBoolean("playerIsHuman", isHuman); playerProperties.AddInteger("playerColor", playerSetting.Color.ToUInt32()); // TODO: Other player properties. mapPlayers.Add(new Player { Properties = playerProperties, BuildList = factionPlayer.BuildList, }); } // Setup player relationships. var playerAllies = new string[playerSettings.Length]; var playerEnemies = new string[playerSettings.Length]; for (var i = 0; i < playerSettings.Length; i++) { playerAllies[i] = ""; playerEnemies[i] = ""; } for (var i = 0; i < playerSettings.Length; i++) { var outerPlayer = playerSettings[i]; for (var j = i + 1; j < playerSettings.Length; j++) { var innerPlayer = playerSettings[j]; if (outerPlayer.Team == innerPlayer.Team && outerPlayer.Team != 0) { playerAllies[i] += mapPlayers[j + 2].Properties["playerName"].Value + " "; playerAllies[j] += mapPlayers[i + 2].Properties["playerName"].Value + " "; } else { playerEnemies[i] += mapPlayers[j + 2].Properties["playerName"].Value + " "; playerEnemies[j] += mapPlayers[i + 2].Properties["playerName"].Value + " "; } } } for (var i = 0; i < playerSettings.Length; i++) { mapPlayers[i + 2].Properties.AddAsciiString("playerAllies", playerAllies[i]); mapPlayers[i + 2].Properties.AddAsciiString("playerEnemies", playerEnemies[i]); } var originalMapScriptLists = mapFile.GetPlayerScriptsList().ScriptLists; var playerNames = mapPlayers .Select(p => p.Properties.GetPropOrNull("playerName")?.Value.ToString()) .ToArray(); while (mapScriptLists.Count < mapPlayers.Count) { mapScriptLists.Add(null); } // Copy neutral player scripts. var neutralPlayerName = (string)mapPlayers[0].Properties["playerName"].Value; CopyScripts( originalMapScriptLists, playerNames, neutralPlayerName, mapScriptLists, 0, appendIndex: false); // Copy civilian player scripts. var civilianPlayerName = (string)mapPlayers[1].Properties["playerName"].Value; CopyScripts( originalMapScriptLists, playerNames, civilianPlayerName, mapScriptLists, 1, appendIndex: false); switch (game.SageGame) { case SageGame.CncGenerals: case SageGame.CncGeneralsZeroHour: CreateTeamsFromScbFile(game, mapPlayers, mapTeams, mapScriptLists, playerSettings, neutralPlayerName, civilianPlayerName); break; case SageGame.Bfme: case SageGame.Bfme2: case SageGame.Bfme2Rotwk: mapTeams.AddRange(mapFile.GetTeams()); break; } if (playerSettings.Length > 1) { var multiplayerScriptsEntry = game.ContentManager.GetScriptEntry(@"Data\Scripts\MultiplayerScripts.scb"); if (multiplayerScriptsEntry != null) { using var stream = multiplayerScriptsEntry.Open(); var multiplayerScripts = ScbFile.FromStream(stream); // TODO: This is a bit hardcoded. mapScriptLists[0] = multiplayerScripts.PlayerScripts.ScriptLists[0]; } } }
private static void CreateTeamsFromScbFile( Game game, List <Player> mapPlayers, List <Team> mapTeams, List <ScriptList> mapScriptLists, PlayerSetting[] playerSettings, string neutralPlayerName, string civilianPlayerName) { var skirmishScriptsEntry = game.ContentManager.GetScriptEntry(@"Data\Scripts\SkirmishScripts.scb"); using var stream = skirmishScriptsEntry.Open(); var skirmishScripts = ScbFile.FromStream(stream); // This probably isn't right, but it does make the teams match those in .sav files. // We first add human player(s) teams, then the replay observer team, // then neutral and civilian teams, and then finally AI skirmish players. var skirmishScriptsPlayerNames = skirmishScripts.ScriptsPlayers.Players.Select(p => p.Name).ToArray(); // Skip neutral and civilian players. for (var i = 2; i < mapPlayers.Count; i++) { if ((bool)mapPlayers[i].Properties["playerIsHuman"].Value) { // Copy the scripts from the civilian player to all human players. CopyScripts( skirmishScripts.PlayerScripts.ScriptLists, skirmishScriptsPlayerNames, civilianPlayerName, mapScriptLists, i, appendIndex: true); mapTeams.Add(CreateDefaultTeam((string)mapPlayers[i].Properties["playerName"].Value)); } } mapTeams.Add(CreateDefaultTeam("ReplayObserver")); mapTeams.Add(CreateDefaultTeam(neutralPlayerName)); mapTeams.Add(CreateDefaultTeam(civilianPlayerName)); // Skip neutral and civilian players. for (var i = 2; i < mapPlayers.Count; i++) { if (!(bool)mapPlayers[i].Properties["playerIsHuman"].Value) { var playerSide = game.AssetStore.PlayerTemplates.GetByName(playerSettings[i - 2].SideName).Side; var sourcePlayerName = $"Skirmish{playerSide}"; // Copy the scripts from the according skirmish player for all AI players. CopyScripts( skirmishScripts.PlayerScripts.ScriptLists, skirmishScriptsPlayerNames, sourcePlayerName, mapScriptLists, i, appendIndex: true); // TODO: Not sure about the order the teams are added. foreach (var team in skirmishScripts.Teams.Teams) { var teamOwner = (string)team.Properties["teamOwner"].Value; if (teamOwner == sourcePlayerName) { var teamName = $"{team.Properties["teamName"].Value}{i}"; mapTeams.Add(CreateTeam( teamName, (string)mapPlayers[i].Properties["playerName"].Value, (bool)team.Properties["teamIsSingleton"].Value)); } } } } }