Ejemplo n.º 1
0
        private clsResult Serialize_WZ_StructuresINI(IniWriter File, int PlayerCount)
        {
            var ReturnResult = new clsResult("Serializing structures INI", false);
            logger.Info("Serializing structures INI");

            var structureTypeBase = default(StructureTypeBase);
            var unitModuleCount = new int[map.Units.Count];
            var sectorNum = new XYInt();
            var otherStructureTypeBase = default(StructureTypeBase);
            var otherUnit = default(clsUnit);
            var moduleMin = new XYInt();
            var moduleMax = new XYInt();
            var footprint = new XYInt();
            var A = 0;
            var underneathTypes = new StructureTypeBase.enumStructureType[2];
            var underneathTypeCount = 0;
            var badModuleCount = 0;
            var priorityOrder = new clsObjectPriorityOrderList();

            foreach ( var unit in map.Units.Where(d => d.TypeBase.Type == UnitType.PlayerStructure) )
            {
                structureTypeBase = (StructureTypeBase)unit.TypeBase;
                switch ( structureTypeBase.StructureType )
                {
                    case StructureTypeBase.enumStructureType.FactoryModule:
                        underneathTypes[0] = StructureTypeBase.enumStructureType.Factory;
                        underneathTypes[1] = StructureTypeBase.enumStructureType.VTOLFactory;
                        underneathTypeCount = 2;
                        break;
                    case StructureTypeBase.enumStructureType.PowerModule:
                        underneathTypes[0] = StructureTypeBase.enumStructureType.PowerGenerator;
                        underneathTypeCount = 1;
                        break;
                    case StructureTypeBase.enumStructureType.ResearchModule:
                        underneathTypes[0] = StructureTypeBase.enumStructureType.Research;
                        underneathTypeCount = 1;
                        break;
                    default:
                        underneathTypeCount = 0;
                        break;
                }

                if ( underneathTypeCount == 0 )
                {
                    priorityOrder.SetItem(unit);
                    priorityOrder.ActionPerform();
                }
                else
                {
                    // IS module.
                    sectorNum = map.GetPosSectorNum(unit.Pos.Horizontal);
                    clsUnit underneath = null;
                    var connection = default(clsUnitSectorConnection);
                    foreach ( var tempLoopVar_Connection in map.Sectors[sectorNum.X, sectorNum.Y].Units )
                    {
                        connection = tempLoopVar_Connection;
                        otherUnit = connection.Unit;
                        if ( otherUnit.TypeBase.Type == UnitType.PlayerStructure )
                        {
                            otherStructureTypeBase = (StructureTypeBase)otherUnit.TypeBase;
                            if ( otherUnit.UnitGroup == unit.UnitGroup )
                            {
                                for ( A = 0; A <= underneathTypeCount - 1; A++ )
                                {
                                    if ( otherStructureTypeBase.StructureType == underneathTypes[A] )
                                    {
                                        break;
                                    }
                                }
                                if ( A < underneathTypeCount )
                                {
                                    footprint = otherStructureTypeBase.get_GetFootprintSelected(otherUnit.Rotation);
                                    moduleMin.X = otherUnit.Pos.Horizontal.X - (int)(footprint.X * Constants.TerrainGridSpacing / 2.0D);
                                    moduleMin.Y = otherUnit.Pos.Horizontal.Y - (int)(footprint.Y * Constants.TerrainGridSpacing / 2.0D);
                                    moduleMax.X = otherUnit.Pos.Horizontal.X + (int)(footprint.X * Constants.TerrainGridSpacing / 2.0D);
                                    moduleMax.Y = otherUnit.Pos.Horizontal.Y + (int)(footprint.Y * Constants.TerrainGridSpacing / 2.0D);
                                    if ( unit.Pos.Horizontal.X >= moduleMin.X & unit.Pos.Horizontal.X < moduleMax.X &
                                         unit.Pos.Horizontal.Y >= moduleMin.Y & unit.Pos.Horizontal.Y < moduleMax.Y )
                                    {
                                        unitModuleCount[otherUnit.MapLink.ArrayPosition]++;
                                        underneath = otherUnit;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    if ( underneath == null )
                    {
                        badModuleCount++;
                    }
                }
            }

            if ( badModuleCount > 0 )
            {
                ReturnResult.WarningAdd(string.Format("{0} modules had no underlying structure.", badModuleCount));
            }

            var tooManyModulesWarningCount = 0;
            var tooManyModulesWarningMaxCount = 16;
            var moduleCount = 0;
            var moduleLimit = 0;

            for ( A = 0; A <= priorityOrder.Result.Count - 1; A++ )
            {
                var unit = priorityOrder.Result[A];
                structureTypeBase = (StructureTypeBase)unit.TypeBase;
                if ( unit.ID <= 0 )
                {
                    ReturnResult.WarningAdd("Error. A structure\'s ID was zero. It was NOT saved. Delete and replace it to allow save.");
                }
                else
                {
                    File.AddSection("structure_" + unit.ID.ToStringInvariant());
                    File.AddProperty("id", unit.ID.ToStringInvariant());
                    if ( unit.UnitGroup == map.ScavengerUnitGroup || (PlayerCount >= 0 & unit.UnitGroup.WZ_StartPos >= PlayerCount) )
                    {
                        File.AddProperty("player", "scavenger");
                    }
                    else
                    {
                        File.AddProperty("startpos", unit.UnitGroup.WZ_StartPos.ToStringInvariant());
                    }
                    File.AddProperty("name", structureTypeBase.Code);
                    if ( structureTypeBase.WallLink.IsConnected )
                    {
                        File.AddProperty("wall/type", structureTypeBase.WallLink.ArrayPosition.ToStringInvariant());
                    }
                    File.AddProperty("position", unit.GetINIPosition());
                    File.AddProperty("rotation", unit.GetINIRotation());
                    if ( unit.Health < 1.0D )
                    {
                        File.AddProperty("health", unit.GetINIHealthPercent());
                    }
                    switch ( structureTypeBase.StructureType )
                    {
                        case StructureTypeBase.enumStructureType.Factory:
                            moduleLimit = 2;
                            break;
                        case StructureTypeBase.enumStructureType.VTOLFactory:
                            moduleLimit = 2;
                            break;
                        case StructureTypeBase.enumStructureType.PowerGenerator:
                            moduleLimit = 1;
                            break;
                        case StructureTypeBase.enumStructureType.Research:
                            moduleLimit = 1;
                            break;
                        default:
                            moduleLimit = 0;
                            break;
                    }
                    if ( unitModuleCount[unit.MapLink.ArrayPosition] > moduleLimit )
                    {
                        moduleCount = moduleLimit;
                        if ( tooManyModulesWarningCount < tooManyModulesWarningMaxCount )
                        {
                            ReturnResult.WarningAdd(string.Format("Structure {0} at {1} has too many modules ({2})",
                                structureTypeBase.GetDisplayTextCode(),
                                unit.GetPosText(),
                                unitModuleCount[unit.MapLink.ArrayPosition]));
                        }
                        tooManyModulesWarningCount++;
                    }
                    else
                    {
                        moduleCount = unitModuleCount[unit.MapLink.ArrayPosition];
                    }
                    File.AddProperty("modules", moduleCount.ToStringInvariant());
                }
            }

            if ( tooManyModulesWarningCount > tooManyModulesWarningMaxCount )
            {
                ReturnResult.WarningAdd(string.Format("{0} structures had too many modules.", tooManyModulesWarningCount));
            }

            return ReturnResult;
        }
Ejemplo n.º 2
0
        public clsResult Write_WZ(sWrite_WZ_Args Args)
        {
            clsResult ReturnResult =
                new clsResult("Compiling to " + Convert.ToString(ControlChars.Quote) + Args.Path + Convert.ToString(ControlChars.Quote));

            try
            {
                switch ( Args.CompileType )
                {
                    case sWrite_WZ_Args.enumCompileType.Multiplayer:
                        if ( Args.Multiplayer == null )
                        {
                            ReturnResult.ProblemAdd("Multiplayer arguments were not passed.");
                            return ReturnResult;
                        }
                        if ( Args.Multiplayer.PlayerCount < 2 | Args.Multiplayer.PlayerCount > 10 )
                        {
                            ReturnResult.ProblemAdd("Number of players was below 2 or above 10.");
                            return ReturnResult;
                        }
                        if ( !Args.Multiplayer.IsBetaPlayerFormat )
                        {
                            if ( !(Args.Multiplayer.PlayerCount == 2 | Args.Multiplayer.PlayerCount == 4 | Args.Multiplayer.PlayerCount == 8) )
                            {
                                ReturnResult.ProblemAdd("Number of players was not 2, 4 or 8 in original format.");
                                return ReturnResult;
                            }
                        }
                        break;
                    case sWrite_WZ_Args.enumCompileType.Campaign:
                        if ( Args.Campaign == null )
                        {
                            ReturnResult.ProblemAdd("Campaign arguments were not passed.");
                            return ReturnResult;
                        }
                        break;
                    default:
                        ReturnResult.ProblemAdd("Unknown compile method.");
                        return ReturnResult;
                }

                if ( !Args.Overwrite )
                {
                    if ( File.Exists(Args.Path) )
                    {
                        ReturnResult.ProblemAdd("The selected file already exists.");
                        return ReturnResult;
                    }
                }

                char Quote = ControlChars.Quote;
                char EndChar = '\n';
                string Text = "";

                MemoryStream File_LEV_Memory = new MemoryStream();
                StreamWriter File_LEV = new StreamWriter(File_LEV_Memory, App.UTF8Encoding);
                MemoryStream File_MAP_Memory = new MemoryStream();
                BinaryWriter File_MAP = new BinaryWriter(File_MAP_Memory, App.ASCIIEncoding);
                MemoryStream File_GAM_Memory = new MemoryStream();
                BinaryWriter File_GAM = new BinaryWriter(File_GAM_Memory, App.ASCIIEncoding);
                MemoryStream File_featBJO_Memory = new MemoryStream();
                BinaryWriter File_featBJO = new BinaryWriter(File_featBJO_Memory, App.ASCIIEncoding);
                MemoryStream INI_feature_Memory = new MemoryStream();
                IniWriter INI_feature = IniWriter.CreateFile(INI_feature_Memory);
                MemoryStream File_TTP_Memory = new MemoryStream();
                BinaryWriter File_TTP = new BinaryWriter(File_TTP_Memory, App.ASCIIEncoding);
                MemoryStream File_structBJO_Memory = new MemoryStream();
                BinaryWriter File_structBJO = new BinaryWriter(File_structBJO_Memory, App.ASCIIEncoding);
                MemoryStream INI_struct_Memory = new MemoryStream();
                IniWriter INI_struct = IniWriter.CreateFile(INI_struct_Memory);
                MemoryStream File_droidBJO_Memory = new MemoryStream();
                BinaryWriter File_droidBJO = new BinaryWriter(File_droidBJO_Memory, App.ASCIIEncoding);
                MemoryStream INI_droid_Memory = new MemoryStream();
                IniWriter INI_droid = IniWriter.CreateFile(INI_droid_Memory);
                MemoryStream INI_Labels_Memory = new MemoryStream();
                IniWriter INI_Labels = IniWriter.CreateFile(INI_Labels_Memory);

                string PlayersPrefix = "";
                string PlayersText = "";

                if ( Args.CompileType == sWrite_WZ_Args.enumCompileType.Multiplayer )
                {
                    PlayersText = IOUtil.InvariantToString(Args.Multiplayer.PlayerCount);
                    PlayersPrefix = PlayersText + "c-";
                    string fog = "";
                    string TilesetNum = "";
                    if ( Tileset == null )
                    {
                        ReturnResult.ProblemAdd("Map must have a tileset.");
                        return ReturnResult;
                    }
                    else if ( Tileset == App.Tileset_Arizona )
                    {
                        fog = "fog1.wrf";
                        TilesetNum = "1";
                    }
                    else if ( Tileset == App.Tileset_Urban )
                    {
                        fog = "fog2.wrf";
                        TilesetNum = "2";
                    }
                    else if ( Tileset == App.Tileset_Rockies )
                    {
                        fog = "fog3.wrf";
                        TilesetNum = "3";
                    }
                    else
                    {
                        ReturnResult.ProblemAdd("Unknown tileset selected.");
                        return ReturnResult;
                    }

                    Text = "// Made with " + Constants.ProgramName + " " + Constants.ProgramVersionNumber + " " + Constants.ProgramPlatform +
                           Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    DateTime DateNow = DateTime.Now;
                    Text = "// Date: " + Convert.ToString(DateNow.Year) + "/" + App.MinDigits(DateNow.Month, 2) + "/" +
                           App.MinDigits(DateNow.Day, 2) + " " + App.MinDigits(DateNow.Hour, 2) + ":" + App.MinDigits(DateNow.Minute, 2) + ":" +
                           App.MinDigits(DateNow.Second, 2) + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "// Author: " + Args.Multiplayer.AuthorName + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "// License: " + Args.Multiplayer.License + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = EndChar.ToString();
                    File_LEV.Write(Text);
                    Text = "level   " + Args.MapName + "-T1" + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "players " + PlayersText + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "type    14" + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "dataset MULTI_CAM_" + TilesetNum + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "game    " + Convert.ToString(Quote) + "multiplay/maps/" + PlayersPrefix + Args.MapName + ".gam" + Convert.ToString(Quote) +
                           Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "data    " + Convert.ToString(Quote) + "wrf/multi/skirmish" + PlayersText + ".wrf" + Convert.ToString(Quote) +
                           Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "data    " + Convert.ToString(Quote) + "wrf/multi/" + fog + Convert.ToString(Quote) + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = EndChar.ToString();
                    File_LEV.Write(Text);
                    Text = "level   " + Args.MapName + "-T2" + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "players " + PlayersText + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "type    18" + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "dataset MULTI_T2_C" + TilesetNum + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "game    " + Convert.ToString(Quote) + "multiplay/maps/" + PlayersPrefix + Args.MapName + ".gam" + Convert.ToString(Quote) +
                           Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "data    " + Convert.ToString(Quote) + "wrf/multi/t2-skirmish" + PlayersText + ".wrf" + Convert.ToString(Quote) +
                           Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "data    " + Convert.ToString(Quote) + "wrf/multi/" + fog + Convert.ToString(Quote) + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = EndChar.ToString();
                    File_LEV.Write(Text);
                    Text = "level   " + Args.MapName + "-T3" + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "players " + PlayersText + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "type    19" + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "dataset MULTI_T3_C" + TilesetNum + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "game    " + Convert.ToString(Quote) + "multiplay/maps/" + PlayersPrefix + Args.MapName + ".gam" + Convert.ToString(Quote) +
                           Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "data    " + Convert.ToString(Quote) + "wrf/multi/t3-skirmish" + PlayersText + ".wrf" + Convert.ToString(Quote) +
                           Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                    Text = "data    " + Convert.ToString(Quote) + "wrf/multi/" + fog + Convert.ToString(Quote) + Convert.ToString(EndChar);
                    File_LEV.Write(Text);
                }

                byte[] GameZeroBytes = new byte[20];

                IOUtil.WriteText(File_GAM, false, "game");
                File_GAM.Write(8U);
                File_GAM.Write(0U); //Time
                if ( Args.CompileType == sWrite_WZ_Args.enumCompileType.Multiplayer )
                {
                    File_GAM.Write(0U);
                }
                else if ( Args.CompileType == sWrite_WZ_Args.enumCompileType.Campaign )
                {
                    File_GAM.Write(Args.Campaign.GAMType);
                }
                File_GAM.Write(Args.ScrollMin.X);
                File_GAM.Write(Args.ScrollMin.Y);
                File_GAM.Write(Args.ScrollMax.X);
                File_GAM.Write(Args.ScrollMax.Y);
                File_GAM.Write(GameZeroBytes);

                int A = 0;
                int X = 0;
                int Y = 0;

                IOUtil.WriteText(File_MAP, false, "map ");
                File_MAP.Write(10U);
                File_MAP.Write(Convert.ToBoolean((uint)Terrain.TileSize.X));
                File_MAP.Write(Convert.ToBoolean((uint)Terrain.TileSize.Y));
                byte Flip = 0;
                byte Rotation = 0;
                bool DoFlipX = default(bool);
                int InvalidTileCount = 0;
                int TextureNum = 0;
                for ( Y = 0; Y <= Terrain.TileSize.Y - 1; Y++ )
                {
                    for ( X = 0; X <= Terrain.TileSize.X - 1; X++ )
                    {
                        TileUtil.TileOrientation_To_OldOrientation(Terrain.Tiles[X, Y].Texture.Orientation, ref Rotation, ref DoFlipX);
                        Flip = (byte)0;
                        if ( Terrain.Tiles[X, Y].Tri )
                        {
                            Flip += (byte)8;
                        }
                        Flip += (byte)(Rotation * 16);
                        if ( DoFlipX )
                        {
                            Flip += (byte)128;
                        }
                        TextureNum = Terrain.Tiles[X, Y].Texture.TextureNum;
                        if ( TextureNum < 0 | TextureNum > 255 )
                        {
                            TextureNum = 0;
                            if ( InvalidTileCount < 16 )
                            {
                                ReturnResult.WarningAdd("Tile texture number " + Convert.ToString(Terrain.Tiles[X, Y].Texture.TextureNum) +
                                                        " is invalid on tile " + Convert.ToString(X) + ", " + Convert.ToString(Y) +
                                                        " and was compiled as texture number " + Convert.ToString(TextureNum) + ".");
                            }
                            InvalidTileCount++;
                        }
                        File_MAP.Write((byte)TextureNum);
                        File_MAP.Write(Flip);
                        File_MAP.Write(Convert.ToBoolean(Terrain.Vertices[X, Y].Height));
                    }
                }
                if ( InvalidTileCount > 0 )
                {
                    ReturnResult.WarningAdd(InvalidTileCount + " tile texture numbers were invalid.");
                }
                File_MAP.Write(1U); //gateway version
                File_MAP.Write(Convert.ToBoolean((uint)Gateways.Count));
                clsGateway Gateway = default(clsGateway);
                foreach ( clsGateway tempLoopVar_Gateway in Gateways )
                {
                    Gateway = tempLoopVar_Gateway;
                    File_MAP.Write((byte)(MathUtil.Clamp_int(Gateway.PosA.X, 0, 255)));
                    File_MAP.Write((byte)(MathUtil.Clamp_int(Gateway.PosA.Y, 0, 255)));
                    File_MAP.Write((byte)(MathUtil.Clamp_int(Gateway.PosB.X, 0, 255)));
                    File_MAP.Write((byte)(MathUtil.Clamp_int(Gateway.PosB.Y, 0, 255)));
                }

                clsFeatureType FeatureType = default(clsFeatureType);
                clsStructureType StructureType = default(clsStructureType);
                clsDroidDesign DroidType = default(clsDroidDesign);
                clsDroidTemplate DroidTemplate = default(clsDroidTemplate);
                clsUnit Unit = default(clsUnit);
                clsStructureWriteWZ StructureWrite = new clsStructureWriteWZ();
                StructureWrite.File = File_structBJO;
                StructureWrite.CompileType = Args.CompileType;
                if ( Args.CompileType == sWrite_WZ_Args.enumCompileType.Multiplayer )
                {
                    StructureWrite.PlayerCount = Args.Multiplayer.PlayerCount;
                }
                else
                {
                    StructureWrite.PlayerCount = 0;
                }

                byte[] FeatZeroBytes = new byte[12];

                IOUtil.WriteText(File_featBJO, false, "feat");
                File_featBJO.Write(8U);
                clsObjectPriorityOrderList FeatureOrder = new clsObjectPriorityOrderList();
                foreach ( clsUnit tempLoopVar_Unit in Units )
                {
                    Unit = tempLoopVar_Unit;
                    if ( Unit.Type.Type == clsUnitType.enumType.Feature )
                    {
                        FeatureOrder.SetItem(Unit);
                        FeatureOrder.ActionPerform();
                    }
                }
                File_featBJO.Write(Convert.ToBoolean((uint)FeatureOrder.Result.Count));
                for ( A = 0; A <= FeatureOrder.Result.Count - 1; A++ )
                {
                    Unit = FeatureOrder.Result[A];
                    FeatureType = (clsFeatureType)Unit.Type;
                    IOUtil.WriteTextOfLength(File_featBJO, 40, FeatureType.Code);
                    File_featBJO.Write(Unit.ID);
                    File_featBJO.Write(Convert.ToBoolean((uint)Unit.Pos.Horizontal.X));
                    File_featBJO.Write(Convert.ToBoolean((uint)Unit.Pos.Horizontal.Y));
                    File_featBJO.Write(Convert.ToBoolean((uint)Unit.Pos.Altitude));
                    File_featBJO.Write(Convert.ToBoolean((uint)Unit.Rotation));
                    switch ( Args.CompileType )
                    {
                        case sWrite_WZ_Args.enumCompileType.Multiplayer:
                            File_featBJO.Write(Unit.GetBJOMultiplayerPlayerNum(Args.Multiplayer.PlayerCount));
                            break;
                        case sWrite_WZ_Args.enumCompileType.Campaign:
                            File_featBJO.Write(Unit.GetBJOCampaignPlayerNum());
                            break;
                        default:
                            Debugger.Break();
                            break;
                    }
                    File_featBJO.Write(FeatZeroBytes);
                }

                IOUtil.WriteText(File_TTP, false, "ttyp");
                File_TTP.Write(8U);
                File_TTP.Write(Convert.ToBoolean((uint)Tileset.TileCount));
                for ( A = 0; A <= Tileset.TileCount - 1; A++ )
                {
                    File_TTP.Write(Convert.ToBoolean(Tile_TypeNum[A]));
                }

                IOUtil.WriteText(File_structBJO, false, "stru");
                File_structBJO.Write(8U);
                clsObjectPriorityOrderList NonModuleStructureOrder = new clsObjectPriorityOrderList();
                //non-module structures
                foreach ( clsUnit tempLoopVar_Unit in Units )
                {
                    Unit = tempLoopVar_Unit;
                    if ( Unit.Type.Type == clsUnitType.enumType.PlayerStructure )
                    {
                        StructureType = (clsStructureType)Unit.Type;
                        if ( !StructureType.IsModule() )
                        {
                            NonModuleStructureOrder.SetItem(Unit);
                            NonModuleStructureOrder.ActionPerform();
                        }
                    }
                }
                clsObjectPriorityOrderList ModuleStructureOrder = new clsObjectPriorityOrderList();
                //module structures
                foreach ( clsUnit tempLoopVar_Unit in Units )
                {
                    Unit = tempLoopVar_Unit;
                    if ( Unit.Type.Type == clsUnitType.enumType.PlayerStructure )
                    {
                        StructureType = (clsStructureType)Unit.Type;
                        if ( StructureType.IsModule() )
                        {
                            ModuleStructureOrder.SetItem(Unit);
                            ModuleStructureOrder.ActionPerform();
                        }
                    }
                }
                File_structBJO.Write(Convert.ToBoolean((uint)(NonModuleStructureOrder.Result.Count + ModuleStructureOrder.Result.Count)));
                NonModuleStructureOrder.Result.PerformTool(StructureWrite);
                ModuleStructureOrder.Result.PerformTool(StructureWrite);

                byte[] DintZeroBytes = new byte[12];

                IOUtil.WriteText(File_droidBJO, false, "dint");
                File_droidBJO.Write(8U);
                clsObjectPriorityOrderList Droids = new clsObjectPriorityOrderList();
                foreach ( clsUnit tempLoopVar_Unit in Units )
                {
                    Unit = tempLoopVar_Unit;
                    if ( Unit.Type.Type == clsUnitType.enumType.PlayerDroid )
                    {
                        DroidType = (clsDroidDesign)Unit.Type;
                        if ( DroidType.IsTemplate )
                        {
                            Droids.SetItem(Unit);
                            Droids.ActionPerform();
                        }
                    }
                }
                File_droidBJO.Write(Convert.ToBoolean((uint)Droids.Result.Count));
                for ( A = 0; A <= Droids.Result.Count - 1; A++ )
                {
                    Unit = Droids.Result[A];
                    DroidTemplate = (clsDroidTemplate)Unit.Type;
                    IOUtil.WriteTextOfLength(File_droidBJO, 40, DroidTemplate.Code);
                    File_droidBJO.Write(Unit.ID);
                    File_droidBJO.Write(Convert.ToBoolean((uint)Unit.Pos.Horizontal.X));
                    File_droidBJO.Write(Convert.ToBoolean((uint)Unit.Pos.Horizontal.Y));
                    File_droidBJO.Write(Convert.ToBoolean((uint)Unit.Pos.Altitude));
                    File_droidBJO.Write(Convert.ToBoolean((uint)Unit.Rotation));
                    switch ( Args.CompileType )
                    {
                        case sWrite_WZ_Args.enumCompileType.Multiplayer:
                            File_droidBJO.Write(Unit.GetBJOMultiplayerPlayerNum(Args.Multiplayer.PlayerCount));
                            break;
                        case sWrite_WZ_Args.enumCompileType.Campaign:
                            File_droidBJO.Write(Unit.GetBJOCampaignPlayerNum());
                            break;
                        default:
                            Debugger.Break();
                            break;
                    }
                    File_droidBJO.Write(DintZeroBytes);
                }

                ReturnResult.Add(Serialize_WZ_FeaturesINI(INI_feature));
                if ( Args.CompileType == sWrite_WZ_Args.enumCompileType.Multiplayer )
                {
                    ReturnResult.Add(Serialize_WZ_StructuresINI(INI_struct, Args.Multiplayer.PlayerCount));
                    ReturnResult.Add(Serialize_WZ_DroidsINI(INI_droid, Args.Multiplayer.PlayerCount));
                    ReturnResult.Add(Serialize_WZ_LabelsINI(INI_Labels, Args.Multiplayer.PlayerCount));
                }
                else if ( Args.CompileType == sWrite_WZ_Args.enumCompileType.Campaign )
                {
                    ReturnResult.Add(Serialize_WZ_StructuresINI(INI_struct, -1));
                    ReturnResult.Add(Serialize_WZ_DroidsINI(INI_droid, -1));
                    ReturnResult.Add(Serialize_WZ_LabelsINI(INI_Labels, 0)); //interprets -1 players as an FMap
                }

                File_LEV.Flush();
                File_MAP.Flush();
                File_GAM.Flush();
                File_featBJO.Flush();
                INI_feature.File.Flush();
                File_TTP.Flush();
                File_structBJO.Flush();
                INI_struct.File.Flush();
                File_droidBJO.Flush();
                INI_droid.File.Flush();
                INI_Labels.File.Flush();

                if ( Args.CompileType == sWrite_WZ_Args.enumCompileType.Multiplayer )
                {
                    if ( !Args.Overwrite )
                    {
                        if ( File.Exists(Args.Path) )
                        {
                            ReturnResult.ProblemAdd("A file already exists at: " + Args.Path);
                            return ReturnResult;
                        }
                    }
                    else
                    {
                        if ( File.Exists(Args.Path) )
                        {
                            try
                            {
                                File.Delete(Args.Path);
                            }
                            catch ( Exception ex )
                            {
                                ReturnResult.ProblemAdd("Unable to delete existing file: " + ex.Message);
                                return ReturnResult;
                            }
                        }
                    }

                    ZipOutputStream WZStream = default(ZipOutputStream);

                    try
                    {
                        WZStream = new ZipOutputStream(File.Create(Args.Path));
                    }
                    catch ( Exception ex )
                    {
                        ReturnResult.ProblemAdd(ex.Message);
                        return ReturnResult;
                    }

                    WZStream.SetLevel(9);
                    WZStream.UseZip64 = UseZip64.Off; //warzone crashes without this

                    try
                    {
                        string ZipPath = "";
                        ZipEntry ZipEntry = default(ZipEntry);

                        if ( Args.Multiplayer.IsBetaPlayerFormat )
                        {
                            ZipPath = PlayersPrefix + Args.MapName + ".xplayers.lev";
                        }
                        else
                        {
                            ZipPath = PlayersPrefix + Args.MapName + ".addon.lev";
                        }
                        ZipEntry = IOUtil.ZipMakeEntry(WZStream, ZipPath, ReturnResult);
                        if ( ZipEntry != null )
                        {
                            File_LEV_Memory.WriteTo(WZStream);
                            WZStream.Flush();
                            WZStream.CloseEntry();
                        }

                        ZipEntry = new ZipEntry("multiplay/");
                        WZStream.PutNextEntry(ZipEntry);
                        ZipEntry = new ZipEntry("multiplay/maps/");
                        WZStream.PutNextEntry(ZipEntry);
                        ZipEntry = new ZipEntry("multiplay/maps/" + PlayersPrefix + Args.MapName + "/");
                        WZStream.PutNextEntry(ZipEntry);

                        ZipPath = "multiplay/maps/" + PlayersPrefix + Args.MapName + ".gam";
                        ZipEntry = IOUtil.ZipMakeEntry(WZStream, ZipPath, ReturnResult);
                        if ( ZipEntry != null )
                        {
                            ReturnResult.Add(IOUtil.WriteMemoryToZipEntryAndFlush(File_GAM_Memory, WZStream));
                        }
                        else
                        {
                            ReturnResult.ProblemAdd("Unable to make entry " + ZipPath);
                        }

                        ZipPath = "multiplay/maps/" + PlayersPrefix + Args.MapName + "/" + "dinit.bjo";
                        ZipEntry = IOUtil.ZipMakeEntry(WZStream, ZipPath, ReturnResult);
                        if ( ZipEntry != null )
                        {
                            ReturnResult.Add(IOUtil.WriteMemoryToZipEntryAndFlush(File_droidBJO_Memory, WZStream));
                        }
                        else
                        {
                            ReturnResult.ProblemAdd("Unable to make entry " + ZipPath);
                        }

                        ZipPath = "multiplay/maps/" + PlayersPrefix + Args.MapName + "/" + "droid.ini";
                        ZipEntry = IOUtil.ZipMakeEntry(WZStream, ZipPath, ReturnResult);
                        if ( ZipEntry != null )
                        {
                            ReturnResult.Add(IOUtil.WriteMemoryToZipEntryAndFlush(INI_droid_Memory, WZStream));
                        }
                        else
                        {
                            ReturnResult.ProblemAdd("Unable to make entry " + ZipPath);
                        }

                        ZipPath = "multiplay/maps/" + PlayersPrefix + Args.MapName + "/" + "feat.bjo";
                        ZipEntry = IOUtil.ZipMakeEntry(WZStream, ZipPath, ReturnResult);
                        if ( ZipEntry != null )
                        {
                            ReturnResult.Add(IOUtil.WriteMemoryToZipEntryAndFlush(File_featBJO_Memory, WZStream));
                        }
                        else
                        {
                            ReturnResult.ProblemAdd("Unable to make entry " + ZipPath);
                        }

                        ZipPath = "multiplay/maps/" + PlayersPrefix + Args.MapName + "/" + "feature.ini";
                        ZipEntry = IOUtil.ZipMakeEntry(WZStream, ZipPath, ReturnResult);
                        if ( ZipEntry != null )
                        {
                            ReturnResult.Add(IOUtil.WriteMemoryToZipEntryAndFlush(INI_feature_Memory, WZStream));
                        }
                        else
                        {
                            ReturnResult.ProblemAdd("Unable to make entry " + ZipPath);
                        }

                        ZipPath = "multiplay/maps/" + PlayersPrefix + Args.MapName + "/" + "game.map";
                        ZipEntry = IOUtil.ZipMakeEntry(WZStream, ZipPath, ReturnResult);
                        if ( ZipEntry != null )
                        {
                            ReturnResult.Add(IOUtil.WriteMemoryToZipEntryAndFlush(File_MAP_Memory, WZStream));
                        }
                        else
                        {
                            ReturnResult.ProblemAdd("Unable to make entry " + ZipPath);
                        }

                        ZipPath = "multiplay/maps/" + PlayersPrefix + Args.MapName + "/" + "struct.bjo";
                        ZipEntry = IOUtil.ZipMakeEntry(WZStream, ZipPath, ReturnResult);
                        if ( ZipEntry != null )
                        {
                            ReturnResult.Add(IOUtil.WriteMemoryToZipEntryAndFlush(File_structBJO_Memory, WZStream));
                        }
                        else
                        {
                            ReturnResult.ProblemAdd("Unable to make entry " + ZipPath);
                        }

                        ZipPath = "multiplay/maps/" + PlayersPrefix + Args.MapName + "/" + "struct.ini";
                        ZipEntry = IOUtil.ZipMakeEntry(WZStream, ZipPath, ReturnResult);
                        if ( ZipEntry != null )
                        {
                            ReturnResult.Add(IOUtil.WriteMemoryToZipEntryAndFlush(INI_struct_Memory, WZStream));
                        }
                        else
                        {
                            ReturnResult.ProblemAdd("Unable to make entry " + ZipPath);
                        }

                        ZipPath = "multiplay/maps/" + PlayersPrefix + Args.MapName + "/" + "ttypes.ttp";
                        ZipEntry = IOUtil.ZipMakeEntry(WZStream, ZipPath, ReturnResult);
                        if ( ZipEntry != null )
                        {
                            ReturnResult.Add(IOUtil.WriteMemoryToZipEntryAndFlush(File_TTP_Memory, WZStream));
                        }
                        else
                        {
                            ReturnResult.ProblemAdd("Unable to make entry " + ZipPath);
                        }

                        if ( INI_Labels_Memory.Length > 0 )
                        {
                            ZipPath = "multiplay/maps/" + PlayersPrefix + Args.MapName + "/" + "labels.ini";
                            ZipEntry = IOUtil.ZipMakeEntry(WZStream, ZipPath, ReturnResult);
                            if ( ZipEntry != null )
                            {
                                ReturnResult.Add(IOUtil.WriteMemoryToZipEntryAndFlush(INI_Labels_Memory, WZStream));
                            }
                            else
                            {
                                ReturnResult.ProblemAdd("Unable to make entry " + ZipPath);
                            }
                        }

                        WZStream.Finish();
                        WZStream.Close();
                        return ReturnResult;
                    }
                    catch ( Exception ex )
                    {
                        WZStream.Close();
                        ReturnResult.ProblemAdd(ex.Message);
                        return ReturnResult;
                    }
                }
                else if ( Args.CompileType == sWrite_WZ_Args.enumCompileType.Campaign )
                {
                    string CampDirectory = App.EndWithPathSeperator(Args.Path);

                    if ( !Directory.Exists(CampDirectory) )
                    {
                        ReturnResult.ProblemAdd("Directory " + CampDirectory + " does not exist.");
                        return ReturnResult;
                    }

                    string FilePath = "";

                    FilePath = CampDirectory + Args.MapName + ".gam";
                    ReturnResult.Add(IOUtil.WriteMemoryToNewFile(File_GAM_Memory, CampDirectory + Args.MapName + ".gam"));

                    CampDirectory += Args.MapName + Convert.ToString(App.PlatformPathSeparator);
                    try
                    {
                        Directory.CreateDirectory(CampDirectory);
                    }
                    catch ( Exception )
                    {
                        ReturnResult.ProblemAdd("Unable to create directory " + CampDirectory);
                        return ReturnResult;
                    }

                    FilePath = CampDirectory + "dinit.bjo";
                    ReturnResult.Add(IOUtil.WriteMemoryToNewFile(File_droidBJO_Memory, FilePath));

                    FilePath = CampDirectory + "droid.ini";
                    ReturnResult.Add(IOUtil.WriteMemoryToNewFile(INI_droid_Memory, FilePath));

                    FilePath = CampDirectory + "feat.bjo";
                    ReturnResult.Add(IOUtil.WriteMemoryToNewFile(File_featBJO_Memory, FilePath));

                    FilePath = CampDirectory + "feature.ini";
                    ReturnResult.Add(IOUtil.WriteMemoryToNewFile(INI_feature_Memory, FilePath));

                    FilePath = CampDirectory + "game.map";
                    ReturnResult.Add(IOUtil.WriteMemoryToNewFile(File_MAP_Memory, FilePath));

                    FilePath = CampDirectory + "struct.bjo";
                    ReturnResult.Add(IOUtil.WriteMemoryToNewFile(File_structBJO_Memory, FilePath));

                    FilePath = CampDirectory + "struct.ini";
                    ReturnResult.Add(IOUtil.WriteMemoryToNewFile(INI_struct_Memory, FilePath));

                    FilePath = CampDirectory + "ttypes.ttp";
                    ReturnResult.Add(IOUtil.WriteMemoryToNewFile(File_TTP_Memory, FilePath));

                    FilePath = CampDirectory + "labels.ini";
                    ReturnResult.Add(IOUtil.WriteMemoryToNewFile(INI_Labels_Memory, FilePath));
                }
            }
            catch ( Exception ex )
            {
                Debugger.Break();
                ReturnResult.ProblemAdd(ex.Message);
                return ReturnResult;
            }

            return ReturnResult;
        }
Ejemplo n.º 3
0
        private Result Serialize_WZ_StructuresINI(IniWriter File, int PlayerCount)
        {
            var ReturnResult = new Result("Serializing structures INI", false);

            logger.Info("Serializing structures INI");

            var structureTypeBase      = default(StructureTypeBase);
            var unitModuleCount        = new int[map.Units.Count];
            var sectorNum              = new XYInt();
            var otherStructureTypeBase = default(StructureTypeBase);
            var otherUnit              = default(Unit);
            var moduleMin              = new XYInt();
            var moduleMax              = new XYInt();
            var footprint              = new XYInt();
            var A = 0;
            var underneathTypes     = new StructureType[2];
            var underneathTypeCount = 0;
            var badModuleCount      = 0;
            var priorityOrder       = new clsObjectPriorityOrderList();

            foreach (var unit in map.Units.Where(d => d.TypeBase.Type == UnitType.PlayerStructure))
            {
                structureTypeBase = (StructureTypeBase)unit.TypeBase;
                switch (structureTypeBase.StructureType)
                {
                case StructureType.FactoryModule:
                    underneathTypes[0]  = StructureType.Factory;
                    underneathTypes[1]  = StructureType.VTOLFactory;
                    underneathTypeCount = 2;
                    break;

                case StructureType.PowerModule:
                    underneathTypes[0]  = StructureType.PowerGenerator;
                    underneathTypeCount = 1;
                    break;

                case StructureType.ResearchModule:
                    underneathTypes[0]  = StructureType.Research;
                    underneathTypeCount = 1;
                    break;

                default:
                    underneathTypeCount = 0;
                    break;
                }

                if (underneathTypeCount == 0)
                {
                    priorityOrder.SetItem(unit);
                    priorityOrder.ActionPerform();
                }
                else
                {
                    // IS module.
                    sectorNum = map.GetPosSectorNum(unit.Pos.Horizontal);
                    Unit underneath = null;
                    var  connection = default(clsUnitSectorConnection);
                    foreach (var tempLoopVar_Connection in map.Sectors[sectorNum.X, sectorNum.Y].Units)
                    {
                        connection = tempLoopVar_Connection;
                        otherUnit  = connection.Unit;
                        if (otherUnit.TypeBase.Type == UnitType.PlayerStructure)
                        {
                            otherStructureTypeBase = (StructureTypeBase)otherUnit.TypeBase;
                            if (otherUnit.UnitGroup == unit.UnitGroup)
                            {
                                for (A = 0; A <= underneathTypeCount - 1; A++)
                                {
                                    if (otherStructureTypeBase.StructureType == underneathTypes[A])
                                    {
                                        break;
                                    }
                                }
                                if (A < underneathTypeCount)
                                {
                                    footprint   = otherStructureTypeBase.GetGetFootprintSelected(otherUnit.Rotation);
                                    moduleMin.X = otherUnit.Pos.Horizontal.X - (footprint.X * Constants.TerrainGridSpacing / 2.0D).ToInt();
                                    moduleMin.Y = otherUnit.Pos.Horizontal.Y - (footprint.Y * Constants.TerrainGridSpacing / 2.0D).ToInt();
                                    moduleMax.X = otherUnit.Pos.Horizontal.X + (footprint.X * Constants.TerrainGridSpacing / 2.0D).ToInt();
                                    moduleMax.Y = otherUnit.Pos.Horizontal.Y + (footprint.Y * Constants.TerrainGridSpacing / 2.0D).ToInt();
                                    if (unit.Pos.Horizontal.X >= moduleMin.X & unit.Pos.Horizontal.X < moduleMax.X &
                                        unit.Pos.Horizontal.Y >= moduleMin.Y & unit.Pos.Horizontal.Y < moduleMax.Y)
                                    {
                                        unitModuleCount[otherUnit.MapLink.ArrayPosition]++;
                                        underneath = otherUnit;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    if (underneath == null)
                    {
                        badModuleCount++;
                    }
                }
            }

            if (badModuleCount > 0)
            {
                ReturnResult.WarningAdd(string.Format("{0} modules had no underlying structure.", badModuleCount));
            }

            var tooManyModulesWarningCount    = 0;
            var tooManyModulesWarningMaxCount = 16;
            var moduleCount = 0;
            var moduleLimit = 0;

            for (A = 0; A <= priorityOrder.Result.Count - 1; A++)
            {
                var unit = priorityOrder.Result[A];
                structureTypeBase = (StructureTypeBase)unit.TypeBase;
                if (unit.ID <= 0)
                {
                    ReturnResult.WarningAdd("Error. A structure\'s ID was zero. It was NOT saved. Delete and replace it to allow save.");
                }
                else
                {
                    File.AddSection("structure_" + unit.ID.ToStringInvariant());
                    File.AddProperty("id", unit.ID.ToStringInvariant());
                    if (unit.UnitGroup == map.ScavengerUnitGroup || (PlayerCount >= 0 & unit.UnitGroup.WZ_StartPos >= PlayerCount))
                    {
                        File.AddProperty("player", "scavenger");
                    }
                    else
                    {
                        File.AddProperty("startpos", unit.UnitGroup.WZ_StartPos.ToStringInvariant());
                    }
                    File.AddProperty("name", structureTypeBase.Code);
                    if (structureTypeBase.WallLink.IsConnected)
                    {
                        File.AddProperty("wall/type", structureTypeBase.WallLink.ArrayPosition.ToStringInvariant());
                    }
                    File.AddProperty("position", unit.GetINIPosition());
                    File.AddProperty("rotation", unit.GetINIRotation());
                    if (unit.Health < 1.0D)
                    {
                        File.AddProperty("health", unit.GetINIHealthPercent());
                    }
                    switch (structureTypeBase.StructureType)
                    {
                    case StructureType.Factory:
                        moduleLimit = 2;
                        break;

                    case StructureType.VTOLFactory:
                        moduleLimit = 2;
                        break;

                    case StructureType.PowerGenerator:
                        moduleLimit = 1;
                        break;

                    case StructureType.Research:
                        moduleLimit = 1;
                        break;

                    default:
                        moduleLimit = 0;
                        break;
                    }
                    if (unitModuleCount[unit.MapLink.ArrayPosition] > moduleLimit)
                    {
                        moduleCount = moduleLimit;
                        if (tooManyModulesWarningCount < tooManyModulesWarningMaxCount)
                        {
                            ReturnResult.WarningAdd(string.Format("Structure {0} at {1} has too many modules ({2})",
                                                                  structureTypeBase.GetDisplayTextCode(),
                                                                  unit.GetPosText(),
                                                                  unitModuleCount[unit.MapLink.ArrayPosition]));
                        }
                        tooManyModulesWarningCount++;
                    }
                    else
                    {
                        moduleCount = unitModuleCount[unit.MapLink.ArrayPosition];
                    }
                    File.AddProperty("modules", moduleCount.ToStringInvariant());
                }
            }

            if (tooManyModulesWarningCount > tooManyModulesWarningMaxCount)
            {
                ReturnResult.WarningAdd(string.Format("{0} structures had too many modules.", tooManyModulesWarningCount));
            }

            return(ReturnResult);
        }
Ejemplo n.º 4
0
        public clsResult Serialize_WZ_StructuresINI(IniWriter File, int PlayerCount)
        {
            clsResult ReturnResult = new clsResult("Serializing structures INI");

            clsStructureType StructureType = default(clsStructureType);
            clsUnit Unit = default(clsUnit);
            bool[] UnitIsModule = new bool[Units.Count];
            int[] UnitModuleCount = new int[Units.Count];
            sXY_int SectorNum = new sXY_int();
            clsStructureType OtherStructureType = default(clsStructureType);
            clsUnit OtherUnit = default(clsUnit);
            sXY_int ModuleMin = new sXY_int();
            sXY_int ModuleMax = new sXY_int();
            sXY_int Footprint = new sXY_int();
            int A = 0;
            clsStructureType.enumStructureType[] UnderneathTypes = new clsStructureType.enumStructureType[2];
            int UnderneathTypeCount = 0;
            int BadModuleCount = 0;
            clsObjectPriorityOrderList PriorityOrder = new clsObjectPriorityOrderList();

            foreach ( clsUnit tempLoopVar_Unit in Units )
            {
                Unit = tempLoopVar_Unit;
                if ( Unit.Type.Type == clsUnitType.enumType.PlayerStructure )
                {
                    StructureType = (clsStructureType)Unit.Type;
                    switch ( StructureType.StructureType )
                    {
                        case clsStructureType.enumStructureType.FactoryModule:
                            UnderneathTypes[0] = clsStructureType.enumStructureType.Factory;
                            UnderneathTypes[1] = clsStructureType.enumStructureType.VTOLFactory;
                            UnderneathTypeCount = 2;
                            break;
                        case clsStructureType.enumStructureType.PowerModule:
                            UnderneathTypes[0] = clsStructureType.enumStructureType.PowerGenerator;
                            UnderneathTypeCount = 1;
                            break;
                        case clsStructureType.enumStructureType.ResearchModule:
                            UnderneathTypes[0] = clsStructureType.enumStructureType.Research;
                            UnderneathTypeCount = 1;
                            break;
                        default:
                            UnderneathTypeCount = 0;
                            break;
                    }
                    if ( UnderneathTypeCount == 0 )
                    {
                        PriorityOrder.SetItem(Unit);
                        PriorityOrder.ActionPerform();
                    }
                    else
                    {
                        UnitIsModule[Unit.MapLink.ArrayPosition] = true;
                        SectorNum = GetPosSectorNum(Unit.Pos.Horizontal);
                        clsUnit Underneath = null;
                        clsUnitSectorConnection Connection = default(clsUnitSectorConnection);
                        foreach ( clsUnitSectorConnection tempLoopVar_Connection in Sectors[SectorNum.X, SectorNum.Y].Units )
                        {
                            Connection = tempLoopVar_Connection;
                            OtherUnit = Connection.Unit;
                            if ( OtherUnit.Type.Type == clsUnitType.enumType.PlayerStructure )
                            {
                                OtherStructureType = (clsStructureType)OtherUnit.Type;
                                if ( OtherUnit.UnitGroup == Unit.UnitGroup )
                                {
                                    for ( A = 0; A <= UnderneathTypeCount - 1; A++ )
                                    {
                                        if ( OtherStructureType.StructureType == UnderneathTypes[A] )
                                        {
                                            break;
                                        }
                                    }
                                    if ( A < UnderneathTypeCount )
                                    {
                                        Footprint = OtherStructureType.get_GetFootprintSelected(OtherUnit.Rotation);
                                        ModuleMin.X = OtherUnit.Pos.Horizontal.X - (int)(Footprint.X * App.TerrainGridSpacing / 2.0D);
                                        ModuleMin.Y = OtherUnit.Pos.Horizontal.Y - (int)(Footprint.Y * App.TerrainGridSpacing / 2.0D);
                                        ModuleMax.X = OtherUnit.Pos.Horizontal.X + (int)(Footprint.X * App.TerrainGridSpacing / 2.0D);
                                        ModuleMax.Y = OtherUnit.Pos.Horizontal.Y + (int)(Footprint.Y * App.TerrainGridSpacing / 2.0D);
                                        if ( Unit.Pos.Horizontal.X >= ModuleMin.X & Unit.Pos.Horizontal.X < ModuleMax.X &
                                             Unit.Pos.Horizontal.Y >= ModuleMin.Y & Unit.Pos.Horizontal.Y < ModuleMax.Y )
                                        {
                                            UnitModuleCount[OtherUnit.MapLink.ArrayPosition]++;
                                            Underneath = OtherUnit;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        if ( Underneath == null )
                        {
                            BadModuleCount++;
                        }
                    }
                }
            }

            if ( BadModuleCount > 0 )
            {
                ReturnResult.WarningAdd(BadModuleCount + " modules had no underlying structure.");
            }

            int TooManyModulesWarningCount = 0;
            int TooManyModulesWarningMaxCount = 16;
            int ModuleCount = 0;
            int ModuleLimit = 0;

            for ( A = 0; A <= PriorityOrder.Result.Count - 1; A++ )
            {
                Unit = PriorityOrder.Result[A];
                StructureType = (clsStructureType)Unit.Type;
                if ( Unit.ID <= 0 )
                {
                    ReturnResult.WarningAdd("Error. A structure\'s ID was zero. It was NOT saved. Delete and replace it to allow save.");
                }
                else
                {
                    File.AppendSectionName("structure_" + IOUtil.InvariantToString(Unit.ID));
                    File.AppendProperty("id", IOUtil.InvariantToString(Unit.ID));
                    if ( Unit.UnitGroup == ScavengerUnitGroup || (PlayerCount >= 0 & Unit.UnitGroup.WZ_StartPos >= PlayerCount) )
                    {
                        File.AppendProperty("player", "scavenger");
                    }
                    else
                    {
                        File.AppendProperty("startpos", IOUtil.InvariantToString(Unit.UnitGroup.WZ_StartPos));
                    }
                    File.AppendProperty("name", StructureType.Code);
                    if ( StructureType.WallLink.IsConnected )
                    {
                        File.AppendProperty("wall/type", IOUtil.InvariantToString(StructureType.WallLink.ArrayPosition));
                    }
                    File.AppendProperty("position", Unit.GetINIPosition());
                    File.AppendProperty("rotation", Unit.GetINIRotation());
                    if ( Unit.Health < 1.0D )
                    {
                        File.AppendProperty("health", Unit.GetINIHealthPercent());
                    }
                    switch ( StructureType.StructureType )
                    {
                        case clsStructureType.enumStructureType.Factory:
                            ModuleLimit = 2;
                            break;
                        case clsStructureType.enumStructureType.VTOLFactory:
                            ModuleLimit = 2;
                            break;
                        case clsStructureType.enumStructureType.PowerGenerator:
                            ModuleLimit = 1;
                            break;
                        case clsStructureType.enumStructureType.Research:
                            ModuleLimit = 1;
                            break;
                        default:
                            ModuleLimit = 0;
                            break;
                    }
                    if ( UnitModuleCount[Unit.MapLink.ArrayPosition] > ModuleLimit )
                    {
                        ModuleCount = ModuleLimit;
                        if ( TooManyModulesWarningCount < TooManyModulesWarningMaxCount )
                        {
                            ReturnResult.WarningAdd("Structure " + StructureType.GetDisplayTextCode() + " at " + Unit.GetPosText() + " has too many modules (" +
                                                    Convert.ToString(UnitModuleCount[Unit.MapLink.ArrayPosition]) + ").");
                        }
                        TooManyModulesWarningCount++;
                    }
                    else
                    {
                        ModuleCount = UnitModuleCount[Unit.MapLink.ArrayPosition];
                    }
                    File.AppendProperty("modules", IOUtil.InvariantToString(ModuleCount));
                    File.Gap_Append();
                }
            }

            if ( TooManyModulesWarningCount > TooManyModulesWarningMaxCount )
            {
                ReturnResult.WarningAdd(TooManyModulesWarningCount + " structures had too many modules.");
            }

            return ReturnResult;
        }