void LoadActors(IniFile file, string section) { foreach (var s in file.GetSection(section, true)) { // Structures: num=owner,type,health,location,turret-facing,trigger // Units: num=owner,type,health,location,facing,action,trigger // Infantry: num=owner,type,health,location,subcell,action,facing,trigger try { var parts = s.Value.Split(','); if (parts[0] == "") parts[0] = "Neutral"; if (!players.Contains(parts[0])) players.Add(parts[0]); var loc = Exts.ParseIntegerInvariant(parts[3]); var health = Exts.ParseIntegerInvariant(parts[2]) * 100 / 256; var facing = (section == "INFANTRY") ? Exts.ParseIntegerInvariant(parts[6]) : Exts.ParseIntegerInvariant(parts[4]); var actor = new ActorReference(parts[1].ToLowerInvariant()) { new LocationInit(new CPos(loc % mapSize, loc / mapSize)), new OwnerInit(parts[0]), }; var initDict = actor.InitDict; if (health != 100) initDict.Add(new HealthInit(health)); if (facing != 0) initDict.Add(new FacingInit(facing)); if (section == "INFANTRY") actor.Add(new SubCellInit(Exts.ParseIntegerInvariant(parts[4]))); if (!rules.Actors.ContainsKey(parts[1].ToLowerInvariant())) errorHandler("Ignoring unknown actor type: `{0}`".F(parts[1].ToLowerInvariant())); else map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, actor.Save())); } catch (Exception) { errorHandler("Malformed actor definition: `{0}`".F(s)); } } }
void ReadCncTrees(IniFile file) { var terrain = file.GetSection("TERRAIN", true); if (terrain == null) return; foreach (var kv in terrain) { var loc = Exts.ParseIntegerInvariant(kv.Key); var ar = new ActorReference(kv.Value.Split(',')[0].ToLowerInvariant()) { new LocationInit(new CPos(loc % mapSize, loc / mapSize)), new OwnerInit("Neutral") }; map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, ar.Save())); } }
void UnpackRAOverlayData(MemoryStream ms) { for (var j = 0; j < mapSize; j++) { for (var i = 0; i < mapSize; i++) { var o = ms.ReadUInt8(); var res = Pair.New((byte)0, (byte)0); if (o != 255 && overlayResourceMapping.ContainsKey(redAlertOverlayNames[o])) res = overlayResourceMapping[redAlertOverlayNames[o]]; var cell = new CPos(i, j); map.MapResources.Value[cell] = new ResourceTile(res.First, res.Second); if (o != 255 && overlayActorMapping.ContainsKey(redAlertOverlayNames[o])) { var ar = new ActorReference(overlayActorMapping[redAlertOverlayNames[o]]) { new LocationInit(cell), new OwnerInit("Neutral") }; map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, ar.Save())); } } } }
void ReadCncOverlay(IniFile file) { var overlay = file.GetSection("OVERLAY", true); if (overlay == null) return; foreach (var kv in overlay) { var loc = Exts.ParseIntegerInvariant(kv.Key); var cell = new CPos(loc % mapSize, loc / mapSize); var res = Pair.New((byte)0, (byte)0); if (overlayResourceMapping.ContainsKey(kv.Value.ToLower())) res = overlayResourceMapping[kv.Value.ToLower()]; map.MapResources.Value[cell] = new ResourceTile(res.First, res.Second); if (overlayActorMapping.ContainsKey(kv.Value.ToLower())) { var ar = new ActorReference(overlayActorMapping[kv.Value.ToLower()]) { new LocationInit(cell), new OwnerInit("Neutral") }; map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, ar.Save())); } } }
enum IniMapFormat { RedAlert = 3 } // otherwise, cnc (2 variants exist, we don't care to differentiate) public void ConvertIniMap(string iniFile) { using (var stream = GlobalFileSystem.Open(iniFile)) { var file = new IniFile(stream); var basic = file.GetSection("Basic"); var mapSection = file.GetSection("Map"); var legacyMapFormat = (IniMapFormat)Exts.ParseIntegerInvariant(basic.GetValue("NewINIFormat", "0")); var offsetX = Exts.ParseIntegerInvariant(mapSection.GetValue("X", "0")); var offsetY = Exts.ParseIntegerInvariant(mapSection.GetValue("Y", "0")); var width = Exts.ParseIntegerInvariant(mapSection.GetValue("Width", "0")); var height = Exts.ParseIntegerInvariant(mapSection.GetValue("Height", "0")); mapSize = (legacyMapFormat == IniMapFormat.RedAlert) ? 128 : 64; var tileset = Truncate(mapSection.GetValue("Theater", "TEMPERAT"), 8); map = new Map(rules.TileSets[tileset], mapSize, mapSize) { Title = basic.GetValue("Name", Path.GetFileNameWithoutExtension(iniFile)), Author = "Westwood Studios" }; var tl = new PPos(offsetX, offsetY); var br = new PPos(offsetX + width - 1, offsetY + height - 1); map.SetBounds(tl, br); if (legacyMapFormat == IniMapFormat.RedAlert) { UnpackRATileData(ReadPackedSection(file.GetSection("MapPack"))); UnpackRAOverlayData(ReadPackedSection(file.GetSection("OverlayPack"))); ReadRATrees(file); } else { // CnC using (var s = GlobalFileSystem.Open(iniFile.Substring(0, iniFile.Length - 4) + ".bin")) UnpackCncTileData(s); ReadCncOverlay(file); ReadCncTrees(file); } LoadVideos(file, "BASIC"); LoadActors(file, "STRUCTURES"); LoadActors(file, "UNITS"); LoadActors(file, "INFANTRY"); LoadActors(file, "SHIPS"); LoadSmudges(file, "SMUDGE"); var wps = file.GetSection("Waypoints") .Where(kv => Exts.ParseIntegerInvariant(kv.Value) > 0) .Select(kv => Pair.New(Exts.ParseIntegerInvariant(kv.Key), LocationFromMapOffset(Exts.ParseIntegerInvariant(kv.Value), mapSize))); // Add waypoint actors foreach (var kv in wps) { if (kv.First <= 7) { var ar = new ActorReference("mpspawn") { new LocationInit((CPos)kv.Second), new OwnerInit("Neutral") }; map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, ar.Save())); } else { var ar = new ActorReference("waypoint") { new LocationInit((CPos)kv.Second), new OwnerInit("Neutral") }; map.ActorDefinitions.Add(new MiniYamlNode("waypoint" + kv.First, ar.Save())); } } // Create default player definitions only if there are no players to import mapPlayers = new MapPlayers(map.Rules, (players.Count == 0) ? map.SpawnPoints.Value.Length : 0); foreach (var p in players) LoadPlayer(file, p, legacyMapFormat == IniMapFormat.RedAlert); map.PlayerDefinitions = mapPlayers.ToMiniYaml(); } }