private void addLine(casPart casP, string keyName, string value)
 {
     addLine(casP, keyName, value, false);
 }
 private void addLine(casPart casP, string keyName, string value, bool addToKeylist)
 {
     if (value != "")
     {
         if (addToKeylist) casP.tgi64list.Add(keyToTGI64(value));
         avSB(keyName, value);
     }
 }
        public void Save(Stream casFile, casPart casP)
        {
            int xmlSize = 0;
            int chunkCount = 0;
            ArrayList newtgi64 = new ArrayList();

            if (casP.xmlChunk != null)
            {

                // Remove the textures from the tgi64 list
                ArrayList temp = new ArrayList();
                for (int j = 0; j < casP.tgi64list.Count; j++)
                {
                    tgi64 tgi = (tgi64)casP.tgi64list[j];
                    if (tgi.typeid != 0x00B2D882)
                    {
                        temp.Add(tgi);
                    }
                }

                casP.tgi64list.Clear();

                // Make up the XML chunks first
                for (int j = 0; j < casP.xmlChunk.Count; j++)
                {

                    chunkCount++;
                    sb = new StringBuilder();

                    sb.Append("<!-- XML generated by CTU -->");

                    xmlChunkDetails chunk = (xmlChunkDetails)casP.xmlChunk[j];
                    sb.Append("<preset>");
                    sb.Append("<complate name=\"" + chunk.name + "\" reskey=\"" + chunk.reskey + "\">");
                    avSB("assetRoot", "X:");

                    addLine(casP, "Overlay", chunk.Overlay, true);
                    addLine(casP, "IsHat", chunk.IsHat);
                    addLine(casP, "DrawsOnFace", chunk.DrawsOnFace);
                    addLine(casP, "DrawsOnScalp", chunk.DrawsOnScalp);

                    addLine(casP, "Control Map", chunk.ControlMap, true);
                    addLine(casP, "Diffuse Map", chunk.DiffuseMap, true);

                    // Hair
                    addLine(casP, "Root Color", chunk.hair.RootColor);
                    addLine(casP, "Diffuse Color", chunk.hair.DiffuseColor);
                    addLine(casP, "Highlight Color", chunk.hair.HighlightColor);
                    addLine(casP, "Tip Color", chunk.hair.TipColor);

                    // Hair
                    addLine(casP, "Scalp Diffuse Map", chunk.hair.ScalpDiffuseMap, true);
                    addLine(casP, "Scalp Control Map", chunk.hair.ScalpControlMap, true);
                    addLine(casP, "Scalp Specular Map", chunk.hair.ScalpSpecularMap, true);
                    addLine(casP, "Scalp AO", chunk.hair.ScalpAO, true);
                    addLine(casP, "Face Diffuse Map", chunk.hair.FaceDiffuseMap, true);
                    addLine(casP, "Face Control Map", chunk.hair.FaceControlMap, true);
                    addLine(casP, "Face Specular Map", chunk.hair.FaceSpecularMap, true);
                    addLine(casP, "Face AO", chunk.hair.FaceAO, true);

                    addLine(casP, "Tint Color A", chunk.tint.A.color);
                    addLine(casP, "Tint Color B", chunk.tint.B.color);
                    addLine(casP, "Tint Color C", chunk.tint.C.color);
                    addLine(casP, "Tint Color D", chunk.tint.D.color);
                    addLine(casP, "Tint Color A Enabled", chunk.tint.A.enabled);
                    addLine(casP, "Tint Color B Enabled", chunk.tint.B.enabled);
                    addLine(casP, "Tint Color C Enabled", chunk.tint.C.enabled);
                    addLine(casP, "Tint Color D Enabled", chunk.tint.D.enabled);

                    addLine(casP, "Face Overlay", chunk.faceOverlay, true);
                    addLine(casP, "Face Specular", chunk.faceSpecular, true);

                    addLine(casP, "Mask", chunk.Mask, true);
                    addLine(casP, "MaskHeight", chunk.MaskHeight);
                    addLine(casP, "MaskWidth", chunk.MaskWidth);

                    sb.Append("<!-- Did you get the satellite photos yet? -->");

                    addLine(casP, "Multiplier", chunk.Multiplier, true);

                    addLine(casP, "Stencil A", casP.stencil.A.key, true);
                    addLine(casP, "Stencil B", casP.stencil.B.key, true);
                    addLine(casP, "Stencil C", casP.stencil.C.key, true);
                    addLine(casP, "Stencil D", casP.stencil.D.key, true);
                    addLine(casP, "Stencil E", casP.stencil.E.key, true);
                    addLine(casP, "Stencil F", casP.stencil.F.key, true);

                    addLine(casP, "Stencil A Tiling", casP.stencil.A.Tiling);
                    addLine(casP, "Stencil B Tiling", casP.stencil.B.Tiling);
                    addLine(casP, "Stencil C Tiling", casP.stencil.C.Tiling);
                    addLine(casP, "Stencil D Tiling", casP.stencil.D.Tiling);
                    addLine(casP, "Stencil E Tiling", casP.stencil.E.Tiling);
                    addLine(casP, "Stencil F Tiling", casP.stencil.F.Tiling);

                    addLine(casP, "Stencil A Rotation", casP.stencil.A.Rotation);
                    addLine(casP, "Stencil B Rotation", casP.stencil.B.Rotation);
                    addLine(casP, "Stencil C Rotation", casP.stencil.C.Rotation);
                    addLine(casP, "Stencil D Rotation", casP.stencil.D.Rotation);
                    addLine(casP, "Stencil E Rotation", casP.stencil.E.Rotation);
                    addLine(casP, "Stencil F Rotation", casP.stencil.F.Rotation);

                    addLine(casP, "Stencil A Enabled", chunk.stencilEnabled[0].ToString());
                    addLine(casP, "Stencil B Enabled", chunk.stencilEnabled[1].ToString());
                    addLine(casP, "Stencil C Enabled", chunk.stencilEnabled[2].ToString());
                    addLine(casP, "Stencil D Enabled", chunk.stencilEnabled[3].ToString());
                    addLine(casP, "Stencil E Enabled", chunk.stencilEnabled[4].ToString());
                    addLine(casP, "Stencil F Enabled", chunk.stencilEnabled[5].ToString());

                    sb.Append("<!-- Damnit! -->");

                    addLine(casP, "IsNaked", chunk.IsNaked);
                    addLine(casP, "IsNotNaked", chunk.IsNotNaked);

                    addLine(casP, "Skin Specular", chunk.SkinSpecular, true);
                    addLine(casP, "Skin Ambient", chunk.SkinAmbient, true);

                    addLine(casP, "Clothing Specular", chunk.ClothingSpecular, true);
                    addLine(casP, "Clothing Ambient", chunk.ClothingAmbient, true);

                    addLine(casP, "Rotation", chunk.Rotation);

                    addLine(casP, "Logo UpperLeft", chunk.logo.upperLeft);
                    addLine(casP, "Logo LowerRight", chunk.logo.lowerRight);
                    addLine(casP, "Logo Enabled", chunk.logo.enabled);
                    addLine(casP, "Logo", chunk.logo.filename);

                    addLine(casP, "Part Mask", chunk.PartMask, true);
                    addLine(casP, "daeFileName", chunk.daeFileName);

                    addLine(casP, "age", chunk.age);
                    addLine(casP, "gender", chunk.gender);
                    addLine(casP, "bodyType", chunk.bodyType);
                    addLine(casP, "partType", chunk.partType);
                    addLine(casP, "filename", chunk.filename);

                    sb.Append("<!-- We are running out of time! -->");

                    for (int i = 0; i < 4; i++)
                    {
                        if (chunk.pattern[i].name != "")
                        {
                            string patternName = "";
                            string charName = "";
                            switch (i)
                            {
                                case 0: patternName = "Pattern A"; charName = "JackB"; break;
                                case 1: patternName = "Pattern B"; charName = "ChloeON"; break;
                                case 2: patternName = "Pattern C"; charName = "TonyA"; break;
                                case 3: patternName = "Pattern D"; charName = "BillB"; break;
                            }

                            avSB(patternName, chunk.pattern[i].filename);
                            avSB(patternName + " Enabled", chunk.pattern[i].Enabled);
                            avSB(patternName + " Linked", chunk.pattern[i].Linked);
                            avSB(patternName + " Tiling", chunk.pattern[i].Tiling);

                            sb.AppendLine("<pattern name=\"" + chunk.pattern[i].name + "\" reskey=\"" + chunk.pattern[i].key + "\" variable=\"" + patternName + "\"> <!-- " + charName + "-->");
                            avSBL("assetRoot", "X:");
                            avSBL("Color", chunk.pattern[i].Color);
                            if (chunk.pattern[i].BackgroundImage != "")
                            {
                                casP.tgi64list.Add(keyToTGI64(chunk.pattern[i].BackgroundImage));
                                avSBL("Background Image", chunk.pattern[i].BackgroundImage);
                            }
                            if (chunk.pattern[i].HBg != "") avSBL("H Bg", chunk.pattern[i].HBg);
                            if (chunk.pattern[i].SBg != "") avSBL("S Bg", chunk.pattern[i].SBg);
                            if (chunk.pattern[i].VBg != "") avSBL("V Bg", chunk.pattern[i].VBg);
                            if (chunk.pattern[i].BaseHBg != "") avSBL("Base H Bg", chunk.pattern[i].BaseHBg);
                            if (chunk.pattern[i].BaseSBg != "") avSBL("Base S Bg", chunk.pattern[i].BaseSBg);
                            if (chunk.pattern[i].BaseVBg != "") avSBL("Base V Bg", chunk.pattern[i].BaseVBg);
                            if (chunk.pattern[i].HSVShiftBg != "") avSBL("HSVShift Bg", chunk.pattern[i].HSVShiftBg);
                            if (chunk.pattern[i].rgbmask != "") avSBL("rgbmask", chunk.pattern[i].rgbmask);
                            if (chunk.pattern[i].specmap != "") avSBL("specmap", chunk.pattern[i].specmap);
                            avSBL("filename", chunk.pattern[i].filename);
                            sb.AppendLine("</pattern>");
                        }
                    }

                    if (chunk.logo.name != "")
                    {
                        sb.Append("<pattern name=\"" + chunk.logo.name + "\" reskey=\"" + chunk.logo.key + "\" variable=\"Logo\">");
                        avSB("assetRoot", "X:");
                        //avSB("Color", chunk.pattern.Logo.Color);
                        avSB("filename", chunk.logo.filename);
                        sb.Append("</pattern>");
                    }
                    sb.Append("</complate>");
                    sb.Append("<!-- Have you seen my daughter?! -->");
                    sb.Append("</preset>");

                    casP.xmlChunkRaw[j] = sb.ToString();

                    sb = null;
                }

                // Remove duplicates from the tgi64list (just in case)
                for (int j = 0; j < casP.tgi64list.Count; j++)
                {
                    tgi64 tgi = (tgi64)casP.tgi64list[j];
                    bool hasTGI = false;

                    for (int k = 0; k < newtgi64.Count; k++)
                    {
                        tgi64 tgiNew = (tgi64)newtgi64[k];
                        if (tgi.typeid == tgiNew.typeid && tgi.groupid == tgiNew.groupid && tgi.instanceid == tgiNew.instanceid)
                        {
                            hasTGI = true;
                            break;
                        }
                    }
                    if (!hasTGI)
                    {
                        Console.WriteLine("Adding tgi64 " + tgi.typeid.ToString("X8") + ":" + tgi.groupid.ToString("X8") + ":" + tgi.instanceid.ToString("X16"));
                        newtgi64.Add(tgi);
                    }
                }

                for (int j = 0; j < temp.Count; j++)
                {
                    newtgi64.Add(temp[j]);
                }

            }
            else
            {
                chunkCount = 0;
                newtgi64 = casP.tgi64list;
            }

            BinaryWriter writer = new BinaryWriter(casFile);
            writer.Write(casP.version);
            writer.Write(xmlSize);

            writer.Write(chunkCount);

            if (chunkCount > 0)
            {
                for (int i = 1; i <= casP.xmlChunk.Count; i++)
                {
                    string temp = (string)casP.xmlChunkRaw[i - 1];
                    writer.Write(temp.Length);
                    Gibbed.Helpers.StreamHelpers.WriteUTF16(casFile, temp, true);
                    writer.Write(i);
                }
            }

            writer.Write((byte)(casP.meshName.Length * 2));
            Gibbed.Helpers.StreamHelpers.WriteUTF16(casFile, casP.meshName, false);
            writer.Write(casP.unk1);
            writer.Write(casP.unk2);
            writer.Write(casP.unk3);
            writer.Write(casP.typeFlag);
            writer.Write(casP.ageGenderFlag);
            writer.Write(casP.clothingCategory);

            writer.Write(casP.tgiIndexBodyPart1);
            writer.Write(casP.tgiIndexBodyPart2);
            writer.Write(casP.tgiIndexBlendInfoFat);
            writer.Write(casP.tgiIndexBlendInfoFit);
            writer.Write(casP.tgiIndexBlendInfoThin);
            writer.Write(casP.tgiIndexBlendInfoSpecial);

            writer.Write(casP.unk5);

            if (casP.tgiIndexVPXY > 0)
            {
                writer.Write((byte)1);
                writer.Write(casP.tgiIndexVPXY);
            }
            else
            {
                writer.Write((byte)0);
            }

            writer.Write(casP.count2);
            for (int i = 0; i < casP.count2; i++)
            {
                unkRepeat uR = (unkRepeat)casP.count2repeat[i];
                writer.Write((byte)(i + 1));
                writer.Write(uR.unk2);
                writer.Write(uR.unkRepeatInnerCount);
                for (int j = 0; j < uR.unkRepeatInnerCount; j++)
                {
                    intTriple iT = (intTriple)uR.unkRepeatInnerLoop[j];
                    writer.Write(iT.one);
                    writer.Write(iT.two);
                    writer.Write(iT.three);
                }

            }

            if (casP.tgiIndexDiffuse > 0)
            {
                writer.Write((byte)1);
                writer.Write(casP.tgiIndexDiffuse);
            }
            else
            {
                writer.Write((byte)0);
            }
            if (casP.tgiIndexSpecular > 0)
            {
                writer.Write((byte)1);
                writer.Write(casP.tgiIndexSpecular);
            }
            else
            {
                writer.Write((byte)0);
            }

            writer.Write(casP.count3);
            for (int i = 0; i < casP.count3; i++)
            {
                byte c3r = (byte)casP.count3repeat[i];
                writer.Write(c3r);
            }

            writer.Write(casP.count4);
            for (int i = 0; i < casP.count4; i++)
            {
                byte c4r = (byte)casP.count4repeat[i];
                writer.Write(c4r);
            }

            writer.Write(casP.count5);
            for (int i = 0; i < casP.count5; i++)
            {
                byte c5r = (byte)casP.count5repeat[i];
                writer.Write(c5r);
            }

            writer.Write((byte)(casP.unkString.Length * 2));
            Gibbed.Helpers.StreamHelpers.WriteUTF16(casFile, casP.unkString, false);

            int tgiPos = (int)casFile.Position - 8;

            casP.count6 = (byte)newtgi64.Count;
            writer.Write(casP.count6);
            for (int i = 0; i < casP.count6; i++)
            {
                tgi64 tgi = (tgi64)newtgi64[i];
                Console.WriteLine("Writing tgi64 " + tgi.typeid.ToString("X8") + ":" + tgi.groupid.ToString("X8") + ":" + tgi.instanceid.ToString("X16"));
                writer.Write(tgi.instanceid);
                writer.Write(tgi.groupid);
                writer.Write(tgi.typeid);
            }

            casFile.Seek(4, SeekOrigin.Begin);
            writer.Write(tgiPos);
        }