Example #1
0
        public void SaveZone(bool backup)
        {
            if (BUSY && !backup)
            {
                if (
                    MessageBox.Show("Zone Edit is busy - save as backup?", "Warning!", MessageBoxButtons.YesNo,
                                    MessageBoxIcon.Warning) !=
                    DialogResult.Yes)
                {
                    return;
                }


                backup = true;
            }
            BUSY = true;

            string path = (backup ? PATH + "_backup" : PATH);

            if (!backup)
            {
                //if (Directory.Exists(PATH + "_backup")) {
                //    Directory.Delete(PATH + "_backup", true);
                //}
                Loading.Update("Initiating save process..");
                Loading.ShowLoading(true);
            }
            else
            {
                if (Directory.Exists(PATH + "_backup"))
                {
                    if (Directory.Exists(PATH + "_backup_bak"))
                    {
                        Directory.Delete(PATH + "_backup_bak", true);
                    }

                    Directory.Move(PATH + "_backup", PATH + "_backup_bak");
                }
            }

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            #region datXXX.mpk

            int bwillow = 0;
            {
                string p  = string.Format("dat{0}.mpk", ZoneID.ToString("D3"));
                string pp = path + "\\" + p;
                Loading.Update("Saving " + p + "...");

                if (!Directory.Exists(pp))
                {
                    Directory.CreateDirectory(pp);
                }

                #region SECTOR.DAT

                {
                    Loading.Update("Saving " + p + "... - sector.dat");

                    var s = new INIStreamer(string.Format("{0}\\SECTOR.DAT" + (backup ? ".bak" : ""), pp));
                    s.ReadIni();
                    s.Header.Clear();

                    s.SetItem("terrain", "scalefactor", TerrainScaleFactor.ToString());
                    s.SetItem("terrain", "offsetfactor", TerrainOffsetFactor.ToString());

                    //Rivers
                    int rivers = 0;

                    foreach (Polygon pl in Polygon.Polygons)
                    {
                        if (pl.Type != ePolygon.Water)
                        {
                            continue;
                        }

                        //Save this river

                        string pre = string.Format("river{0:D2}", rivers);

                        if (s.GetTopic(pre) != null)
                        {
                            s.RemTopic(pre);
                        }

                        s.SetItem(pre, "texture", pl.WTexture);
                        s.SetItem(pre, "multitexture", pl.WMultiTexture);
                        s.SetItem(pre, "flow", pl.WFlow.ToString());
                        s.SetItem(pre, "height", pl.WHeight.ToString());
                        s.SetItem(pre, "Tesselation", pl.WTesselation.ToString());
                        s.SetItem(pre, "type", pl.WType.ToString().ToUpper());
                        s.SetItem(pre, "bankpoints", (pl.Points.Count / 2).ToString());
                        s.SetItem(pre, "name", pre);

                        for (int a = 0; a < pl.Points.Count; a += 2)
                        {
                            var x1 = (int)(pl.Points[a].X / 256);
                            var y1 = (int)(pl.Points[a].Y / 256);
                            var x2 = (int)(pl.Points[a + 1].X / 256);
                            var y2 = (int)(pl.Points[a + 1].Y / 256);

                            lock (pl.Points) {
                                pl.Points[a]     = new Vector2(x1 * 256, y1 * 256);
                                pl.Points[a + 1] = new Vector2(x2 * 256, y2 * 256);
                            }

                            s.SetItem(pre, string.Format("left{0:D2}", a / 2),
                                      string.Format("{0},{1},0", x1, y1));
                            s.SetItem(pre, string.Format("right{0:D2}", a / 2),
                                      string.Format("{0},{1},0", x2, y2));
                        }

                        rivers++;
                    }


                    s.SetItem("waterdefs", "num", rivers.ToString());

                    s.WriteIni();
                }

                #endregion

                #region terrain.pcx/offset.pcx

                {
                    Loading.Update("Saving " + p + "... - Heightmaps");

                    var terrain = new byte[256, 256];
                    var offset  = new byte[256, 256];

                    for (int x = 0; x <= 255; x++)
                    {
                        for (int y = 0; y <= 255; y++)
                        {
                            int o = HeightMap[x, y] / TerrainOffsetFactor;

                            if (o > 255)
                            {
                                o = 255;
                            }

                            int remaining = HeightMap[x, y] - o * TerrainOffsetFactor;

                            int t = remaining / TerrainScaleFactor;

                            if (t > 255)
                            {
                                t = 255; //some information may get lost
                            }
                            offset[x, y]  = (byte)(o);
                            terrain[x, y] = (byte)(t);
                        }
                    }

                    PCXImage.Save(string.Format("{0}\\terrain.pcx", pp), terrain);
                    PCXImage.Save(string.Format("{0}\\offset.pcx", pp), offset);
                }

                #endregion

                #region bound.csv

                {
                    Loading.Update("Saving " + p + "... - Bounds");

                    var rs = new StreamWriter(string.Format("{0}\\bound.csv", pp));

                    foreach (Polygon pl in Polygon.Polygons)
                    {
                        if (pl.Type != ePolygon.Bounding)
                        {
                            continue;
                        }

                        //?, count, x,y, x2,y2, x3, y3, ..
                        string vectors = "";

                        foreach (Vector2 v in pl.Points)
                        {
                            vectors += string.Format(",{0},{1}", (int)v.X, (int)v.Y);
                        }

                        rs.WriteLine("{0},{1}{2}", 0, pl.Points.Count, vectors);
                    }

                    rs.Flush();
                    rs.Close();
                }

                #endregion

                #region water.pcx

                {
                    Loading.Update("Saving " + p + "... - Water");

                    var data = new byte[256, 256];

                    for (int x = 0; x < 256; x++)
                    {
                        for (int y = 0; y < 256; y++)
                        {
                            int  height       = (HeightMap[x, y]);
                            bool isUnderwater = false;
                            int  n            = -1;

                            foreach (Polygon pl in Polygon.Polygons)
                            {
                                if (pl.Type != ePolygon.Water)
                                {
                                    continue;
                                }

                                if (!isUnderwater)
                                {
                                    n++;
                                }

                                if (pl.WHeight < height)
                                {
                                    continue;
                                }

                                //Check if point is inside
                                var pnt = new Vector2(x, y);

                                for (int idx = 0; idx < pl.Points.Count - 2; idx += 2)
                                {
                                    Vector2 l1 = pl.Points[idx];
                                    Vector2 r1 = pl.Points[idx + 1];
                                    Vector2 l2 = pl.Points[idx + 2];
                                    Vector2 r2 = pl.Points[idx + 3];

                                    var _l1 = new Vector3(l1.X, l1.Y, 0);
                                    var _r1 = new Vector3(r1.X, r1.Y, 0);
                                    var _l2 = new Vector3(l2.X, l2.Y, 0);
                                    var _r2 = new Vector3(r2.X, r2.Y, 0);

                                    var rayStart = new Vector3(pnt.X * 256, pnt.Y * 256, 1.0f);
                                    var rayDir   = new Vector3(0, 0, -1);

                                    IntersectInformation i;
                                    if (Geometry.IntersectTri(_l1, _r1, _l2, rayStart, rayDir, out i) ||
                                        Geometry.IntersectTri(_r1, _r2, _l2, rayStart, rayDir, out i))
                                    {
                                        isUnderwater = true;
                                        break;
                                    }
                                }
                            }

                            data[x, y] = (byte)(isUnderwater ? n : 255);
                        }
                    }

                    for (int i = 0; i < 2; i++)
                    {
                        WaterDilatation(data);
                    }
                    PCXImage.Save(string.Format("{0}\\water.pcx", pp), data);
                }

                #endregion

                #region nifs.csv

                {
                    Loading.Update("Saving " + p + "... - NIFs");

                    var rs = new StreamWriter(string.Format("{0}\\nifs.csv", pp));

                    rs.WriteLine("Grid Nifs,,,Ambient,Merlin Data");
                    rs.WriteLine(
                        "NIF,Textual Name,Filename,Only,Shadow,Color,Animate,Collide,Ground,MinAngle,MaxAngle,MinScale,MaxScale,Radius,LOD 1,LOD 2,LOD 3,LOD 4,Ref Height,Ref Width,Unique,Local,Terrain");


                    int id = 1;

                    var clones = new List <Objects.NIF>();
                    foreach (Objects.NIF n in Objects.NIFs.Values)
                    {
                        clones.Add(n);
                    }
                    Objects.NIFs.Clear();

                    foreach (Objects.NIF n in clones)
                    {
                        n.ID = id;
                        Objects.NIFs.Add(n.ID, n);

                        rs.Write(id);
                        rs.Write("," + n.FileName + "|" + n.Group); //name
                        rs.Write("," + n.FileName);                 //filename
                        rs.Write("," + 0);                          //ambient only
                        rs.Write("," + 0);                          //merlin shadow data
                        rs.Write("," + 0);                          //color
                        rs.Write("," + (n.IsDoor ? 1 : 0));         //animate
                        rs.Write("," + n.Collision);                //collide
                        rs.Write("," + 1);                          //on ground
                        rs.Write("," + 0);                          //min angle
                        rs.Write("," + 0);                          //max angle
                        rs.Write("," + n.MinScale);                 //min scale
                        rs.Write("," + n.MaxScale);                 //max scale
                        rs.Write("," + n.CollideRadius);            //radius
                        rs.Write("," + 0);                          //lod1
                        rs.Write("," + 0);                          //lod2
                        rs.Write("," + 0);                          //lod3
                        rs.Write("," + 0);                          //lod4
                        rs.Write("," + 16);                         //ref height
                        rs.Write("," + 16);                         //ref width
                        rs.Write("," + 0);                          //unique
                        rs.Write("," + 0);                          //local
                        rs.Write("," + 0);                          //terrain
                        rs.WriteLine();

                        id++;
                    }

                    rs.Flush();
                    rs.Close();
                }

                #endregion

                #region fixtures.csv

                {
                    Loading.Update("Saving " + p + "... - Fixtures");
                    var rs = new StreamWriter(string.Format("{0}\\fixtures.csv", pp));

                    rs.WriteLine("Fixtures,,,,,,,,NIF,Collide,,On,,,,,,,");
                    rs.WriteLine(
                        "ID,NIF #,Textual Name,X,Y,Z,A,Scale,Collide,Radius,Animate,Ground,Flip,Cave,Unique ID, 3D Angle, 3D Axis X, 3D Axis Y, 3D Axis Z");

                    var freeIDs = new List <int>();

                    int id = 1;
                    foreach (Objects.Fixture f in Objects.Fixtures)
                    {
                        if (f.NIF.FileName.ToLower().Contains("bwillow"))
                        {
                            bwillow++;
                        }

                        if (f.NIF.IsDoor) //lock ID
                        {
                            for (int i = id; i < f.ID; i++)
                            {
                                freeIDs.Add(i);
                            }
                            id = f.ID + 1;
                        }
                        else
                        {
                            if (freeIDs.Count > 0)
                            {
                                f.ID = freeIDs[0];
                                freeIDs.RemoveAt(0);
                            }
                            else
                            {
                                f.ID = id++;
                            }
                        }

                        rs.Write(f.ID);
                        rs.Write("," + f.NIF_ID);
                        rs.Write("," + f.Name);
                        rs.Write("," + f.X.ToString().Replace(',', '.'));
                        rs.Write("," + f.Y.ToString().Replace(',', '.'));
                        rs.Write("," + f.Z.ToString().Replace(',', '.'));
                        rs.Write("," + 0);                                       //A (angle?)
                        rs.Write("," + f.Scale);
                        rs.Write("," + f.NIF.Collision);                         //collide
                        rs.Write("," + f.NIF.CollideRadius);                     //radius
                        rs.Write("," + 0);                                       //animate
                        rs.Write("," + (f.OnGround ? 1 : 0));                    //ground
                        rs.Write("," + 0);                                       //flip
                        rs.Write("," + 0);                                       //cave
                        rs.Write("," + f.ID);                                    //uid
                        rs.Write("," + f.Rotation.ToString().Replace(',', '.')); //3d angle
                        rs.Write("," + f.AxisX.ToString().Replace(',', '.'));    //); //3d x
                        rs.Write("," + f.AxisY.ToString().Replace(',', '.'));    //3d y
                        rs.Write("," + f.AxisZ.ToString().Replace(',', '.'));    //3d z
                        rs.WriteLine();
                    }

                    rs.Flush();
                    rs.Close();
                }

                #endregion

                #region zonejump.csv

                {
                    Loading.Update("Saving " + p + "... - Zonejumps");

                    var rs    = new StreamWriter(string.Format("{0}\\zonejump.csv", pp));
                    int index = 1;

                    foreach (Zonejump j in Zonejump.Zonejumps)
                    {
                        //ID, Name, X, Y, X2, Y2, Z1, Z2, JID

                        rs.Write(index++);
                        rs.Write("," + j.Name);
                        rs.Write("," + (int)j.First.X);
                        rs.Write("," + (int)j.First.Y);
                        rs.Write("," + (int)j.Second.X);
                        rs.Write("," + (int)j.Second.Y);
                        rs.Write("," + (int)j.First.Z);
                        rs.Write("," + (int)j.Second.Z);
                        rs.Write("," + j.ID);

                        rs.WriteLine();
                    }

                    rs.Flush();
                    rs.Close();
                }

                #endregion

                #region lights.csv

                {
                    Loading.Update("Saving " + p + "... - Lights");

                    var rs = new StreamWriter(string.Format("{0}\\lights.csv", pp));

                    foreach (Light l in Light.Lights)
                    {
                        //46473, 54362, 2910, 3
                        //X, Y, Z, Intensity

                        rs.Write(l.X);
                        rs.Write(", " + l.Y);
                        rs.Write(", " + (l.Z + l.ZOffset));
                        rs.Write(", " + ((int)l.Color + ((l.Intensity - 1) * 10)));
                        rs.WriteLine();
                    }

                    rs.Flush();
                    rs.Close();
                }

                #endregion
            }

            #endregion

            #region terXXX.mpk

            {
                string p  = string.Format("ter{0}.mpk", ZoneID.ToString("D3"));
                string pp = path + "\\" + p;
                Loading.Update("Saving Textures..");

                if (!Directory.Exists(pp))
                {
                    Directory.CreateDirectory(pp);
                }

                PatchMap.Save(pp + "\\", backup);
            }

            #endregion

            Loading.Update("Saving Sounds...");
            SoundMgr.Save(path);

            if (!backup)
            {
                if (bwillow >= 2000)
                {
                    MessageBox.Show("For every bwillow you will now have to close one Messagebox..!");
                    Loading.Update("Annoying you...");

                    for (int i = bwillow; i <= bwillow; i++)
                    {
                        MessageBox.Show("bwillow " + bwillow);
                    }
                }
            }

            if (!backup)
            {
                LAST_SAVE = DateTime.UtcNow.Ticks;
            }

            GC.Collect();
            Loading.Update("Done.");
            Loading.CloseLoading();
            BUSY = false;
        }