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(','); var loc = int.Parse(parts[3]); if (parts[0] == "") parts[0] = "Neutral"; if (!Players.Contains(parts[0])) Players.Add(parts[0]); var actor = new ActorReference(parts[1].ToLowerInvariant()) { new LocationInit(new CPos(loc % MapSize, loc / MapSize)), new OwnerInit(parts[0]), new HealthInit(float.Parse(parts[2], NumberFormatInfo.InvariantInfo)/256), new FacingInit((section == "INFANTRY") ? int.Parse(parts[6]) : int.Parse(parts[4])), }; if (section == "INFANTRY") actor.Add(new SubCellInit(int.Parse(parts[4]))); if (!Rules.Info.ContainsKey(parts[1].ToLowerInvariant())) errorHandler("Ignoring unknown actor type: `{0}`".F(parts[1].ToLowerInvariant())); else Map.Actors.Value.Add("Actor" + ActorCount++, actor); } catch (Exception) { errorHandler("Malformed actor definition: `{0}`".F(s)); } } }
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)); } } }
public void ConvertIniMap(string iniFile) { var file = new IniFile(FileSystem.Open(iniFile)); var basic = file.GetSection("Basic"); var map = file.GetSection("Map"); var legacyMapFormat = (IniMapFormat)int.Parse(basic.GetValue("NewINIFormat", "0")); var XOffset = int.Parse(map.GetValue("X", "0")); var YOffset = int.Parse(map.GetValue("Y", "0")); var Width = int.Parse(map.GetValue("Width", "0")); var Height = int.Parse(map.GetValue("Height", "0")); MapSize = (legacyMapFormat == IniMapFormat.RedAlert) ? 128 : 64; Map.Title = basic.GetValue("Name", "(null)"); Map.Author = "Westwood Studios"; Map.Tileset = Truncate(map.GetValue("Theater", "TEMPERAT"), 8); Map.MapSize.X = MapSize; Map.MapSize.Y = MapSize; Map.Bounds = Rectangle.FromLTRB(XOffset, YOffset, XOffset + Width, YOffset + Height); Map.Selectable = true; Map.Smudges = Lazy.New(() => new List<SmudgeReference>()); Map.Actors = Lazy.New(() => new Dictionary<string, ActorReference>()); Map.MapResources = Lazy.New(() => new TileReference<byte, byte>[MapSize, MapSize]); Map.MapTiles = Lazy.New(() => new TileReference<ushort, byte>[MapSize, MapSize]); if (legacyMapFormat == IniMapFormat.RedAlert) { UnpackRATileData(ReadPackedSection(file.GetSection("MapPack"))); UnpackRAOverlayData(ReadPackedSection(file.GetSection("OverlayPack"))); ReadRATrees(file); } else // CNC { UnpackCncTileData(FileSystem.Open(iniFile.Substring(0, iniFile.Length - 4) + ".bin")); ReadCncOverlay(file); ReadCncTrees(file); } LoadActors(file, "STRUCTURES"); LoadActors(file, "UNITS"); LoadActors(file, "INFANTRY"); LoadSmudges(file, "SMUDGE"); foreach (var p in Players) LoadPlayer(file, p, (legacyMapFormat == IniMapFormat.RedAlert)); var wps = file.GetSection("Waypoints") .Where(kv => int.Parse(kv.Value) > 0) .Select(kv => Pair.New(int.Parse(kv.Key), LocationFromMapOffset(int.Parse(kv.Value), MapSize))) .ToArray(); // Add waypoint actors foreach( var kv in wps ) { var a = new ActorReference("waypoint"); a.Add(new LocationInit((CPos)kv.Second)); a.Add(new OwnerInit("Neutral")); Map.Actors.Value.Add("waypoint" + kv.First, a); } }
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())); } } }
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())); } }
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(); } }
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())); } } } }
public void ConvertIniMap(string iniFile) { var file = new IniFile(GlobalFileSystem.Open(iniFile)); 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 size = new Size(mapSize, mapSize); var tileset = Truncate(mapSection.GetValue("Theater", "TEMPERAT"), 8); map = Map.FromTileset(rules.TileSets[tileset]); map.Title = basic.GetValue("Name", Path.GetFileNameWithoutExtension(iniFile)); map.Author = "Westwood Studios"; map.MapSize.X = mapSize; map.MapSize.Y = mapSize; map.Bounds = Rectangle.FromLTRB(offsetX, offsetY, offsetX + width, offsetY + height); map.Selectable = true; map.Smudges = Exts.Lazy(() => new List<SmudgeReference>()); map.Actors = Exts.Lazy(() => new Dictionary<string, ActorReference>()); map.MapResources = Exts.Lazy(() => new CellLayer<ResourceTile>(TileShape.Rectangle, size)); map.MapTiles = Exts.Lazy(() => new CellLayer<TerrainTile>(TileShape.Rectangle, size)); map.Options = new MapOptions(); 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); } LoadActors(file, "STRUCTURES"); LoadActors(file, "UNITS"); LoadActors(file, "INFANTRY"); LoadSmudges(file, "SMUDGE"); foreach (var p in players) LoadPlayer(file, p, legacyMapFormat == IniMapFormat.RedAlert); 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))) .ToArray(); // Add waypoint actors foreach (var kv in wps) { if (kv.First <= 7) { var a = new ActorReference("mpspawn"); a.Add(new LocationInit((CPos)kv.Second)); a.Add(new OwnerInit("Neutral")); map.Actors.Value.Add("Actor" + map.Actors.Value.Count.ToString(), a); } else { var a = new ActorReference("waypoint"); a.Add(new LocationInit((CPos)kv.Second)); a.Add(new OwnerInit("Neutral")); map.Actors.Value.Add("waypoint" + kv.First, a); } } }
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(','); var loc = int.Parse(parts[3]); if (parts[0] == "") parts[0] = "Neutral"; if (!Players.Contains(parts[0])) Players.Add(parts[0]); var stance = ActorStance.Stance.None; switch (parts[5]) { case "Area Guard": case "Guard": stance = ActorStance.Stance.Guard; break; case "Defend Base": stance = ActorStance.Stance.Defend; break; case "Hunt": case "Rampage": case "Attack Base": case "Attack Units": case "Attack Civil.": case "Attack Tarcom": stance = ActorStance.Stance.Hunt; break; case "Retreat": case "Return": stance = ActorStance.Stance.Retreat; break; // do we care about `Harvest' and `Sticky'? } var actor = new ActorReference(parts[1].ToLowerInvariant()) { new LocationInit(new int2(loc % MapSize, loc / MapSize)), new OwnerInit(parts[0]), new HealthInit(float.Parse(parts[2], NumberFormatInfo.InvariantInfo)/256), new FacingInit((section == "INFANTRY") ? int.Parse(parts[6]) : int.Parse(parts[4])), new ActorStanceInit(stance), }; if (section == "INFANTRY") actor.Add(new SubCellInit(int.Parse(parts[4]))); if (!Rules.Info.ContainsKey(parts[1].ToLowerInvariant())) errorHandler("Ignoring unknown actor type: `{0}`".F(parts[1].ToLowerInvariant())); else Map.Actors.Value.Add("Actor" + ActorCount++, actor); } catch (Exception) { errorHandler("Malformed actor definition: `{0}`".F(s)); } } }
ColorPalette GetPaletteForActor(ActorReference ar) { if (PlayerPalettes == null) PlayerPalettes = new Cache<string, ColorPalette>(GetPaletteForPlayer); var ownerInit = ar.InitDict.GetOrDefault<OwnerInit>(); if (ownerInit == null) return null; return PlayerPalettes[ownerInit.PlayerName]; }
ColorPalette GetPaletteForActor(ActorReference ar) { var ownerInit = ar.InitDict.GetOrDefault<OwnerInit>(); if (ownerInit == null) return null; return GetPaletteForPlayer(ownerInit.PlayerName); }
public bool HandleMouseInput(MouseInput mi) { // Exclusively uses left and right mouse buttons, but nothing else if (mi.Button != MouseButton.Left && mi.Button != MouseButton.Right) return false; if (mi.Button == MouseButton.Right) { if (mi.Event == MouseInputEvent.Up) { editorWidget.ClearBrush(); return true; } return false; } var cell = worldRenderer.Viewport.ViewToWorld(mi.Location); if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Down) { // Check the actor is inside the map if (!footprint.All(c => world.Map.MapTiles.Value.Contains(cell + locationOffset + c))) return true; var newActorReference = new ActorReference(Actor.Name); newActorReference.Add(new OwnerInit(owner.Name)); cell += locationOffset; newActorReference.Add(new LocationInit(cell)); var ios = Actor.TraitInfoOrDefault<IOccupySpaceInfo>(); if (ios != null && ios.SharesCell) { var subcell = editorLayer.FreeSubCellAt(cell); if (subcell != SubCell.Invalid) newActorReference.Add(new SubCellInit(subcell)); } var initDict = newActorReference.InitDict; if (Actor.HasTraitInfo<IFacingInfo>()) initDict.Add(new FacingInit(facing)); if (Actor.HasTraitInfo<TurretedInfo>()) initDict.Add(new TurretFacingInit(facing)); editorLayer.Add(newActorReference); } return true; }