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]; } } }