diff --git a/Build/Scripting/ZDoom_DECORATE.cfg b/Build/Scripting/ZDoom_DECORATE.cfg index 10564a44..7cffa271 100644 --- a/Build/Scripting/ZDoom_DECORATE.cfg +++ b/Build/Scripting/ZDoom_DECORATE.cfg @@ -695,6 +695,7 @@ constants DMSS_AFFECTARMOR; DMSS_FOILINVUL; DMSS_KILL; + DMSS_NOFACTOR; FPF_AIMATANGLE; FPF_TRANSFERTRANSLATION; JLOSF_PROJECTILE; diff --git a/Resources/Icons/TextLump.png b/Resources/Icons/TextLump.png new file mode 100644 index 00000000..1a56c521 Binary files /dev/null and b/Resources/Icons/TextLump.png differ diff --git a/Source/Core/Data/DirectoryReader.cs b/Source/Core/Data/DirectoryReader.cs index 696bd3bc..392ea594 100644 --- a/Source/Core/Data/DirectoryReader.cs +++ b/Source/Core/Data/DirectoryReader.cs @@ -81,8 +81,9 @@ namespace CodeImp.DoomBuilder.Data try { //mxd. Find in directories ZDoom expects them to be - foreach(string location in PatchLocations){ - string path = Path.Combine(location, Path.GetDirectoryName(pname)); + foreach(string loc in PatchLocations) + { + string path = Path.Combine(loc, Path.GetDirectoryName(pname)); string filename = FindFirstFile(path, Path.GetFileName(pname), true); if(!string.IsNullOrEmpty(filename) && FileExists(filename)) @@ -114,12 +115,13 @@ namespace CodeImp.DoomBuilder.Data try { - // Find in patches directory - string path = Path.Combine(TEXTURES_DIR, Path.GetDirectoryName(pname)); - string filename = FindFirstFile(path, Path.GetFileName(pname), true); - if((filename != null) && FileExists(filename)) + //mxd. Find in directories ZDoom expects them to be + foreach(string loc in TextureLocations) { - return LoadFile(filename); + string path = Path.Combine(loc, Path.GetDirectoryName(pname)); + string filename = FindFirstFile(path, Path.GetFileName(pname), true); + if(!string.IsNullOrEmpty(filename) && FileExists(filename)) + return LoadFile(filename); } } catch(Exception e) diff --git a/Source/Core/Data/HighResImage.cs b/Source/Core/Data/HighResImage.cs index 74d0ce21..793a0577 100644 --- a/Source/Core/Data/HighResImage.cs +++ b/Source/Core/Data/HighResImage.cs @@ -33,7 +33,6 @@ namespace CodeImp.DoomBuilder.Data #region ================== Variables private List patches; //mxd - private bool gotFullName;//mxd private string type; #endregion @@ -52,6 +51,7 @@ namespace CodeImp.DoomBuilder.Data this.patches = new List(1); this.type = type; SetName(name); + this.fullName = "[TEXTURES]\\" + type + "s\\" + name; //mxd // We have no destructor GC.SuppressFinalize(this); @@ -66,13 +66,6 @@ namespace CodeImp.DoomBuilder.Data { // Add it patches.Add(patch); - - //mxd. Get full name from first patch - if (!gotFullName) { - fullName = General.Map.Data.GetPatchLocation(patch.lumpname); - gotFullName = true; - } - if (patch.lumpname == Name) hasPatchWithSameName = true; //mxd } @@ -116,14 +109,7 @@ namespace CodeImp.DoomBuilder.Data foreach(TexturePatch p in patches) { // Get the patch data stream - Stream patchdata; - - //mxd - if (type == "sprite") { - patchdata = General.Map.Data.GetSpriteData(p.lumpname); - } else { - patchdata = General.Map.Data.GetPatchData(p.lumpname); - } + Stream patchdata = General.Map.Data.GetPatchData(p.lumpname); if(patchdata != null) { diff --git a/Source/Core/Data/PK3Reader.cs b/Source/Core/Data/PK3Reader.cs index 2cdbb1c1..e63f3fab 100644 --- a/Source/Core/Data/PK3Reader.cs +++ b/Source/Core/Data/PK3Reader.cs @@ -123,8 +123,9 @@ namespace CodeImp.DoomBuilder.Data } //mxd. Find in directories ZDoom expects them to be - foreach(string location in PatchLocations) { - string filename = FindFirstFile(location, pname, true); + foreach(string loc in PatchLocations) + { + string filename = FindFirstFile(loc, pname, true); if((filename != null) && FileExists(filename)) return LoadFile(filename); } @@ -147,11 +148,12 @@ namespace CodeImp.DoomBuilder.Data if(data != null) return data; } - // Find in patches directory - string filename = FindFirstFile(TEXTURES_DIR, pname, true); - if((filename != null) && FileExists(filename)) + //mxd. Find in directories ZDoom expects them to be + foreach(string loc in TextureLocations) { - return LoadFile(filename); + string filename = FindFirstFile(loc, pname, true); + if(!string.IsNullOrEmpty(filename) && FileExists(filename)) + return LoadFile(filename); } // Nothing found diff --git a/Source/Core/Data/PK3StructuredReader.cs b/Source/Core/Data/PK3StructuredReader.cs index 43cca57e..8295749f 100644 --- a/Source/Core/Data/PK3StructuredReader.cs +++ b/Source/Core/Data/PK3StructuredReader.cs @@ -54,7 +54,8 @@ namespace CodeImp.DoomBuilder.Data #region ================== Properties - protected string[] PatchLocations = { PATCHES_DIR, TEXTURES_DIR, FLATS_DIR, GRAPHICS_DIR }; //mxd. Because ZDoom looks for patches in these folders ///TODO: check the order of these + protected readonly string[] PatchLocations = { PATCHES_DIR, TEXTURES_DIR, FLATS_DIR, SPRITES_DIR, GRAPHICS_DIR }; //mxd. Because ZDoom looks for patches and sprites in this order + protected readonly string[] TextureLocations = { TEXTURES_DIR, PATCHES_DIR, FLATS_DIR, SPRITES_DIR, GRAPHICS_DIR }; //mxd. Because ZDoom looks for textures in this order #endregion @@ -210,7 +211,6 @@ namespace CodeImp.DoomBuilder.Data // Load TEXTURES lump files imgset.Clear(); - //string[] alltexturefiles = GetAllFilesWithTitle("", "TEXTURES", false); string[] alltexturefiles = GetAllFilesWhichTitleStartsWith("", "TEXTURES"); //mxd foreach(string texturesfile in alltexturefiles) { @@ -268,12 +268,14 @@ namespace CodeImp.DoomBuilder.Data // Error when suspended if (issuspended) throw new Exception("Data reader is suspended"); - //no need to search in wads... - // Find in patches directory - //string filename = FindFirstFile(PATCHES_DIR, pname, true); - string filename = FindFirstFile("", pname, true); //mxd. ZDoom can load them from anywhere, so shall we - if ((filename != null) && FileExists(filename)) - return filename; + // Find in directories ZDoom expects them to be + foreach (string loc in PatchLocations) + { + string path = Path.Combine(loc, Path.GetDirectoryName(pname)); + string filename = FindFirstFile(path, Path.GetFileName(pname), true); + if (!string.IsNullOrEmpty(filename) && FileExists(filename)) + return filename; + } return pname; } @@ -311,13 +313,8 @@ namespace CodeImp.DoomBuilder.Data collection = LoadDirectoryImages(FLATS_DIR, ImageDataFormat.DOOMFLAT, true); AddImagesToList(images, collection); - // Add images to the container-specific texture set - foreach(ImageData img in images.Values) - textureset.AddFlat(img); - // Load TEXTURES lump file - imgset.Clear(); - string[] alltexturefiles = GetAllFilesWithTitle("", "TEXTURES", false); + string[] alltexturefiles = GetAllFilesWhichTitleStartsWith("", "TEXTURES"); //mxd foreach(string texturesfile in alltexturefiles) { MemoryStream filedata = LoadFile(texturesfile); @@ -327,6 +324,13 @@ namespace CodeImp.DoomBuilder.Data // Add images from TEXTURES lump file AddImagesToList(images, imgset); + + // Add images to the container-specific texture set + foreach(ImageData img in images.Values) + textureset.AddFlat(img); + + // Add images from TEXTURES lump file + AddImagesToList(images, imgset); return new List(images.Values); } @@ -371,7 +375,7 @@ namespace CodeImp.DoomBuilder.Data // Load TEXTURES lump file imgset.Clear(); - string[] alltexturefiles = GetAllFilesWithTitle("", "TEXTURES", false); + string[] alltexturefiles = GetAllFilesWhichTitleStartsWith("", "TEXTURES"); //mxd foreach(string texturesfile in alltexturefiles) { MemoryStream filedata = LoadFile(texturesfile); diff --git a/Source/Core/GZBuilder/GZDoom/ModeldefParser.cs b/Source/Core/GZBuilder/GZDoom/ModeldefParser.cs index 6346995d..75813b3e 100644 --- a/Source/Core/GZBuilder/GZDoom/ModeldefParser.cs +++ b/Source/Core/GZBuilder/GZDoom/ModeldefParser.cs @@ -51,12 +51,16 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { } else { // Unknown structure! string token2; - do { - if (!SkipWhitespace(true)) break; - token2 = ReadToken(); - if (token2 == null) break; + if (token != "{") { + do + { + if (!SkipWhitespace(true)) break; + token2 = ReadToken(); + if (token2 == null) break; + } + while (token2 != "{"); } - while (token2 != "{"); + int scopelevel = 1; do { if (!SkipWhitespace(true)) break; diff --git a/Source/Core/IO/DirectoryFileEntry.cs b/Source/Core/IO/DirectoryFileEntry.cs index 65febeb8..bfc1c743 100644 --- a/Source/Core/IO/DirectoryFileEntry.cs +++ b/Source/Core/IO/DirectoryFileEntry.cs @@ -30,7 +30,7 @@ namespace CodeImp.DoomBuilder.IO public string filename; // bar.wad public string filetitle; // bar public string extension; // wad - public string path; // foo + public string path; // foo\ public string filepathname; // Foo\Bar.WAD public string filepathtitle; // Foo\Bar @@ -47,7 +47,7 @@ namespace CodeImp.DoomBuilder.IO extension = ""; path = Path.GetDirectoryName(fullname); if(path.Length > (frompath.Length + 1)) - path = path.Substring(frompath.Length + 1); + path = path.Substring(frompath.Length + 1) + Path.DirectorySeparatorChar; else path = ""; filepathname = Path.Combine(path, filename); @@ -72,6 +72,7 @@ namespace CodeImp.DoomBuilder.IO else extension = ""; path = Path.GetDirectoryName(fullname); + if(!string.IsNullOrEmpty(path)) path += Path.DirectorySeparatorChar; //mxd filepathname = Path.Combine(path, filename); filepathtitle = Path.Combine(path, filetitle); diff --git a/Source/Core/IO/DirectoryFilesList.cs b/Source/Core/IO/DirectoryFilesList.cs index bf1895bb..d862f4c2 100644 --- a/Source/Core/IO/DirectoryFilesList.cs +++ b/Source/Core/IO/DirectoryFilesList.cs @@ -288,20 +288,18 @@ namespace CodeImp.DoomBuilder.IO return null; } - // This fixes a path so that it doesn't have the \ at the end + // This fixes a path so that it ends with the proper directory separator (mxd) private static string CorrectPath(string path) { if(path.Length > 0) { - if((path[path.Length - 1] == Path.DirectorySeparatorChar) || (path[path.Length - 1] == Path.AltDirectorySeparatorChar)) - return path.Substring(0, path.Length - 1); - else - return path; - } - else - { - return path; + if(path[path.Length - 1] == Path.DirectorySeparatorChar) return path; + if(path[path.Length - 1] == Path.AltDirectorySeparatorChar) + path = path.Substring(0, path.Length - 1); + return path + Path.DirectorySeparatorChar; } + + return path; } #endregion diff --git a/Source/Core/Rendering/Renderer2D.cs b/Source/Core/Rendering/Renderer2D.cs index 7b53c1fc..e3814774 100644 --- a/Source/Core/Rendering/Renderer2D.cs +++ b/Source/Core/Rendering/Renderer2D.cs @@ -1327,7 +1327,9 @@ namespace CodeImp.DoomBuilder.Rendering graphics.Shaders.Things2D.FillColor = t.Selected ? cHighlight : cWire; for(int i = 0; i < mde.Model.Meshes.Count; i++) { - Matrix modelcale = Matrix.Scaling(t.ScaleX, t.ScaleX, t.ScaleY); + float sx = t.ScaleX * t.ActorScale.Width; + float sy = t.ScaleY * t.ActorScale.Height; + Matrix modelcale = Matrix.Scaling(sx, sx, sy); Matrix rotation = Matrix.RotationY(-(t.RollRad - General.Map.Data.ModeldefEntries[t.Type].RollOffset)) * Matrix.RotationX(-(t.PitchRad + General.Map.Data.ModeldefEntries[t.Type].PitchOffset)) * Matrix.RotationZ(t.Angle); diff --git a/Source/Core/Windows/SectorEditForm.Designer.cs b/Source/Core/Windows/SectorEditForm.Designer.cs index eda49272..41636154 100644 --- a/Source/Core/Windows/SectorEditForm.Designer.cs +++ b/Source/Core/Windows/SectorEditForm.Designer.cs @@ -190,7 +190,8 @@ namespace CodeImp.DoomBuilder.Windows label7.TabIndex = 25; label7.Text = "Height offset:"; label7.TextAlign = System.Drawing.ContentAlignment.TopRight; - this.tooltip.SetToolTip(label7, "Changes floor and ceiling\r\nheight by given value"); + this.tooltip.SetToolTip(label7, "Use ++ or -- prefixes to change\r\nheight by given value.\r\nUse * or / prefixes to m" + + "ultiply\r\nor divide height by given value."); // // label5 // @@ -202,7 +203,8 @@ namespace CodeImp.DoomBuilder.Windows label5.TabIndex = 17; label5.Text = "Floor height:"; label5.TextAlign = System.Drawing.ContentAlignment.TopRight; - this.tooltip.SetToolTip(label5, "Use ++ or -- prefixes to change\r\nheight by given value"); + this.tooltip.SetToolTip(label5, "Use ++ or -- prefixes to change\r\nheight by given value.\r\nUse * or / prefixes to m" + + "ultiply\r\nor divide height by given value."); // // label6 // @@ -214,7 +216,8 @@ namespace CodeImp.DoomBuilder.Windows label6.TabIndex = 19; label6.Text = "Ceiling height:"; label6.TextAlign = System.Drawing.ContentAlignment.TopRight; - this.tooltip.SetToolTip(label6, "Use ++ or -- prefixes to change\r\nheight by given value"); + this.tooltip.SetToolTip(label6, "Use ++ or -- prefixes to change\r\nheight by given value.\r\nUse * or / prefixes to m" + + "ultiply\r\nor divide height by given value."); // // heightoffset // diff --git a/Source/Core/Windows/TextureBrowserForm.Designer.cs b/Source/Core/Windows/TextureBrowserForm.Designer.cs index fffafa95..6c33a42d 100644 --- a/Source/Core/Windows/TextureBrowserForm.Designer.cs +++ b/Source/Core/Windows/TextureBrowserForm.Designer.cs @@ -73,6 +73,7 @@ namespace CodeImp.DoomBuilder.Windows this.smallimages.Images.SetKeyName(4, "PK3TextureSet.ico"); this.smallimages.Images.SetKeyName(5, "FolderImage.png"); this.smallimages.Images.SetKeyName(6, "ArchiveImage.png"); + this.smallimages.Images.SetKeyName(7, "TextLump.png"); // // tvTextureSets // diff --git a/Source/Core/Windows/TextureBrowserForm.cs b/Source/Core/Windows/TextureBrowserForm.cs index b2460beb..f3f6a308 100644 --- a/Source/Core/Windows/TextureBrowserForm.cs +++ b/Source/Core/Windows/TextureBrowserForm.cs @@ -47,9 +47,10 @@ namespace CodeImp.DoomBuilder.Windows public TextureBrowserForm(string selecttexture, bool browseFlats) { Cursor.Current = Cursors.WaitCursor; - TreeNode item;//mxd + TreeNode item; //mxd long longname = Lump.MakeLongName(selecttexture ?? ""); - selectedset = null;//mxd + int count; //mxd + selectedset = null; //mxd this.browseFlats = browseFlats; // Initialize @@ -75,9 +76,12 @@ namespace CodeImp.DoomBuilder.Windows availgroup = browser.AddGroup("Available " + imgType + ":"); //mxd. Fill texture sets list with normal texture sets - foreach(IFilledTextureSet ts in General.Map.Data.TextureSets) + foreach(IFilledTextureSet ts in General.Map.Data.TextureSets) { - item = tvTextureSets.Nodes.Add(ts.Name + " [" + ts.Textures.Count + "]"); + count = (browseFlats ? ts.Flats.Count : ts.Textures.Count); + if(count == 0 && !General.Map.Config.MixTexturesFlats) continue; + + item = tvTextureSets.Nodes.Add(ts.Name + " [" + count + "]"); item.Name = ts.Name; item.Tag = ts; item.ImageIndex = 0; @@ -86,7 +90,10 @@ namespace CodeImp.DoomBuilder.Windows //mxd. Add container-specific texture sets foreach(ResourceTextureSet ts in General.Map.Data.ResourceTextureSets) { - item = tvTextureSets.Nodes.Add(ts.Name + " [" + ts.Textures.Count + "]"); + count = (browseFlats ? ts.Flats.Count : ts.Textures.Count); + if(count == 0 && !General.Map.Config.MixTexturesFlats) continue; + + item = tvTextureSets.Nodes.Add(ts.Name + " [" + count + "]"); item.Name = ts.Name; item.Tag = ts; item.ImageIndex = 2 + ts.Location.type; @@ -99,7 +106,8 @@ namespace CodeImp.DoomBuilder.Windows } //mxd. Add All textures set - item = tvTextureSets.Nodes.Add(General.Map.Data.AllTextureSet.Name + " [" + General.Map.Data.AllTextureSet.Textures.Count + "]"); + count = (browseFlats ? General.Map.Data.AllTextureSet.Flats.Count : General.Map.Data.AllTextureSet.Textures.Count); + item = tvTextureSets.Nodes.Add(General.Map.Data.AllTextureSet.Name + " [" + count + "]"); item.Name = General.Map.Data.AllTextureSet.Name; item.Tag = General.Map.Data.AllTextureSet; item.ImageIndex = 1; @@ -175,7 +183,7 @@ namespace CodeImp.DoomBuilder.Windows } //mxd - private static TreeNode findTextureByLongName(TreeNode node, long longname) + private TreeNode findTextureByLongName(TreeNode node, long longname) { //first search in child nodes TreeNode match; @@ -188,8 +196,16 @@ namespace CodeImp.DoomBuilder.Windows //then - in current node IFilledTextureSet set = (node.Tag as IFilledTextureSet); - foreach (ImageData img in set.Textures) - if (img.LongName == longname) return node; + if (browseFlats) + { + foreach(ImageData img in set.Flats) + if(img.LongName == longname) return node; + } + else + { + foreach(ImageData img in set.Textures) + if(img.LongName == longname) return node; + } return null; } @@ -218,8 +234,17 @@ namespace CodeImp.DoomBuilder.Windows int imageIndex = set.Location.type + 4; string[] separator = new[] { Path.DirectorySeparatorChar.ToString() }; - ImageData[] textures = new ImageData[set.Textures.Count]; - set.Textures.CopyTo(textures, 0); + ImageData[] textures; + if (browseFlats) + { + textures = new ImageData[set.Flats.Count]; + set.Flats.CopyTo(textures, 0); + } + else + { + textures = new ImageData[set.Textures.Count]; + set.Textures.CopyTo(textures, 0); + } Array.Sort(textures, sortImageData); foreach (ImageData image in textures) { @@ -228,6 +253,7 @@ namespace CodeImp.DoomBuilder.Windows TreeNode curNode = root; if (parts.Length == 1) continue; + int localindex = parts[0] == "[TEXTURES]" ? 7 : imageIndex; for (int i = 0; i < parts.Length - 1; i++) { string category = parts[i]; @@ -237,7 +263,7 @@ namespace CodeImp.DoomBuilder.Windows curNode = curNode.Nodes[category]; } else { //create a new one - TreeNode n = new TreeNode(category) {Name = category, ImageIndex = imageIndex, SelectedImageIndex = imageIndex}; + TreeNode n = new TreeNode(category) { Name = category, ImageIndex = localindex, SelectedImageIndex = localindex }; curNode.Nodes.Add(n); curNode = n; @@ -251,7 +277,10 @@ namespace CodeImp.DoomBuilder.Windows TreeNode cn = curNode; while (cn != root) { ResourceTextureSet curTs = cn.Tag as ResourceTextureSet; - curTs.AddTexture(image); + if (image.IsFlat) + curTs.AddFlat(image); + else + curTs.AddTexture(image); cn = cn.Parent; } } @@ -269,14 +298,21 @@ namespace CodeImp.DoomBuilder.Windows } //mxd - private static void SetItemsCount(TreeNode node) + private void SetItemsCount(TreeNode node) { ResourceTextureSet ts = node.Tag as ResourceTextureSet; if (ts == null) throw new Exception("Expected IFilledTextureSet, but got null..."); - node.Text += " [" + ts.Textures.Count + "]"; + - if (General.Map.Config.MixTexturesFlats) + if (node.Parent != null && General.Map.Config.MixTexturesFlats) + { ts.MixTexturesAndFlats(); + node.Text += " [" + ts.Textures.Count + "]"; + } + else + { + node.Text += " [" + (browseFlats ? ts.Flats.Count : ts.Textures.Count) + "]"; + } foreach (TreeNode child in node.Nodes) SetItemsCount(child); } diff --git a/Source/Core/Windows/TextureBrowserForm.resx b/Source/Core/Windows/TextureBrowserForm.resx index 2949ffdc..479f6542 100644 --- a/Source/Core/Windows/TextureBrowserForm.resx +++ b/Source/Core/Windows/TextureBrowserForm.resx @@ -124,72 +124,76 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 - ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAc - DwAAAk1TRnQBSQFMAgEBBwEAAeQBAAHkAQABEAEAARYBAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo - AwABQAMAASwDAAEBAQABCAYAAQsYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA - AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 - AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA - AWYDAAGZAwABzAIAATMDAAIzAgABMwFmAgABMwGZAgABMwHMAgABMwH/AgABZgMAAWYBMwIAAmYCAAFm - AZkCAAFmAcwCAAFmAf8CAAGZAwABmQEzAgABmQFmAgACmQIAAZkBzAIAAZkB/wIAAcwDAAHMATMCAAHM - AWYCAAHMAZkCAALMAgABzAH/AgAB/wFmAgAB/wGZAgAB/wHMAQABMwH/AgAB/wEAATMBAAEzAQABZgEA - ATMBAAGZAQABMwEAAcwBAAEzAQAB/wEAAf8BMwIAAzMBAAIzAWYBAAIzAZkBAAIzAcwBAAIzAf8BAAEz - AWYCAAEzAWYBMwEAATMCZgEAATMBZgGZAQABMwFmAcwBAAEzAWYB/wEAATMBmQIAATMBmQEzAQABMwGZ - AWYBAAEzApkBAAEzAZkBzAEAATMBmQH/AQABMwHMAgABMwHMATMBAAEzAcwBZgEAATMBzAGZAQABMwLM - AQABMwHMAf8BAAEzAf8BMwEAATMB/wFmAQABMwH/AZkBAAEzAf8BzAEAATMC/wEAAWYDAAFmAQABMwEA - AWYBAAFmAQABZgEAAZkBAAFmAQABzAEAAWYBAAH/AQABZgEzAgABZgIzAQABZgEzAWYBAAFmATMBmQEA - AWYBMwHMAQABZgEzAf8BAAJmAgACZgEzAQADZgEAAmYBmQEAAmYBzAEAAWYBmQIAAWYBmQEzAQABZgGZ - AWYBAAFmApkBAAFmAZkBzAEAAWYBmQH/AQABZgHMAgABZgHMATMBAAFmAcwBmQEAAWYCzAEAAWYBzAH/ - AQABZgH/AgABZgH/ATMBAAFmAf8BmQEAAWYB/wHMAQABzAEAAf8BAAH/AQABzAEAApkCAAGZATMBmQEA - AZkBAAGZAQABmQEAAcwBAAGZAwABmQIzAQABmQEAAWYBAAGZATMBzAEAAZkBAAH/AQABmQFmAgABmQFm - ATMBAAGZATMBZgEAAZkBZgGZAQABmQFmAcwBAAGZATMB/wEAApkBMwEAApkBZgEAA5kBAAKZAcwBAAKZ - Af8BAAGZAcwCAAGZAcwBMwEAAWYBzAFmAQABmQHMAZkBAAGZAswBAAGZAcwB/wEAAZkB/wIAAZkB/wEz - AQABmQHMAWYBAAGZAf8BmQEAAZkB/wHMAQABmQL/AQABzAMAAZkBAAEzAQABzAEAAWYBAAHMAQABmQEA - AcwBAAHMAQABmQEzAgABzAIzAQABzAEzAWYBAAHMATMBmQEAAcwBMwHMAQABzAEzAf8BAAHMAWYCAAHM - AWYBMwEAAZkCZgEAAcwBZgGZAQABzAFmAcwBAAGZAWYB/wEAAcwBmQIAAcwBmQEzAQABzAGZAWYBAAHM - ApkBAAHMAZkBzAEAAcwBmQH/AQACzAIAAswBMwEAAswBZgEAAswBmQEAA8wBAALMAf8BAAHMAf8CAAHM - Af8BMwEAAZkB/wFmAQABzAH/AZkBAAHMAf8BzAEAAcwC/wEAAcwBAAEzAQAB/wEAAWYBAAH/AQABmQEA - AcwBMwIAAf8CMwEAAf8BMwFmAQAB/wEzAZkBAAH/ATMBzAEAAf8BMwH/AQAB/wFmAgAB/wFmATMBAAHM - AmYBAAH/AWYBmQEAAf8BZgHMAQABzAFmAf8BAAH/AZkCAAH/AZkBMwEAAf8BmQFmAQAB/wKZAQAB/wGZ - AcwBAAH/AZkB/wEAAf8BzAIAAf8BzAEzAQAB/wHMAWYBAAH/AcwBmQEAAf8CzAEAAf8BzAH/AQAC/wEz - AQABzAH/AWYBAAL/AZkBAAL/AcwBAAJmAf8BAAFmAf8BZgEAAWYC/wEAAf8CZgEAAf8BZgH/AQAC/wFm - AQABIQEAAaUBAANfAQADdwEAA4YBAAOWAQADywEAA7IBAAPXAQAD3QEAA+MBAAPqAQAD8QEAA/gBAAHw - AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD/9MADUsIAAKZGgAHDgEQ - AW0BbAIOAgABUQ1SAUsFAAHvAXMBHAFuAUoBBxcAAQ4BDQFsAZABuwIJAfcCbAFmAg4BAAFSAXoBUgGg - CHoBUgGgAVIBSwMAAZkBbgN0AVIBSwFEAUoBmR0AAQ4B6gFsAQ8BDgEAAVIBegFSAaABegFYBnkBWAGg - AVIBSwIAAXMBbgF0AZkCdAFSAksBbgFEAW4BGhQAAW0HAAFDAW0BDgIAAVIBegFSAaAKcwFSAUsBAAEc - AXQBmgJSAXQBegFMBUsBcxMAAW0B8QFtAQcBvAHwAfECAAERAQcB7AIAAVIBegFSAaABcwL/AfMD9ALz - AXMBUgFLAQABmQFzAVEBdAF6AnQBTANLAUoBSwGTEwADbQEHArwB8AIAAm0BDgIAAVIBegFSAaABcwH/ - AdwF2wH0AXMBUgFLAQAB7AEcAXkCdAoSEgABbQHwAwcCvAIAAREBBwHsAgABUgGaAVIB/wG8Af8GGQHz - AbwBUgFLAQACHAJ0AgcD7wH3ARwD7QESEgABbQHwAe8DBwG8AgACbQEOAgABUgGgDVICAAHtARwBdAFL - ARwI/wHtARISAAFtAfAC7wMHAgABEQEHAewCAAFSA6ABHAH/Aa4BmgG9AXUB4wGuAf8B7QHrAgAB7AFz - AXQBSwH3Af8GrgH/Ae0BEhIAAW0B8APvAgcCAAJtAQ4CAAFSAf8CoAH3Af8BrgL/AnUBrgH/Ae0B6wIA - AZMDdAHvAf8BrgGUAf8BmgGUAa4B/wHtARISAAFtAbwE7wEHAgABEQEHAewDAAFSAv8B7wH/Aa4BlAH/ - AZoBlAGuAf8B7QHrAgABHAGZAcMBegHvAf8C0wH/AZoC0wH/Ae0BEhIACG0BAAEPAewBDwQAAlIB7wH/ - AdMErgHTAf8B7QHrAwACHAGaAe8B/wbTAf8B7QESEgAJDgHrAZEBDQYAAe8B/wbTAf8B7QHrBAABmQF0 - AQcI/wHtARISAAEOAWUBkAG7BQkB9wFsAg4FAAEHCP8B7QHrBgACBwPvAfcBHAPtHgABDgYAAgcD7wH3 - ARwD7QkAApn/AKgAAfcCrgFtAWwB6gJsBGY0AAH3Bf8C9AMZAWYJAAgOEwAB9wKuAW0BbAHqAmwEZgQA - AbUC/wKTAZkBBwG7AbQCGQNmBgABDgEABe8B9wEOAwACcwHrAW4BbQFKARMBFQFDAREBDwEOAQ8DAAH3 - Bf8C9AMZAWYEAAG1Av8BkwGaAXoBnwGeAbsB9AHzAWYBGQFmBQABDgHvAQAB8ALxAvIBvAEOAwABcwIc - BzECSwFEAe0CAAG1Av8CkwGZAQcBuwG0AhkDZgIAAbUC/wG7AQgCnwF+AXkC9AFsARkDZgIAAQ4B7wEH - AQAB8ALxAvIB8AEOAwAB7AF6ARwBmgN6AlkBUwFSATEBSwHqAgABtQL/AZMBmgF6AZ8BngG7AfQB8wFm - ARkBZgIAAbUC/wLbAQkBCAF+AXkB/wH0AWwB8wFmARkBZgIAAQ4CAAHvAbwB8ALxAfIB8AEOAwAB7QF6 - ARwBmQV6AlkBUwExAUQB7QEAAbUC/wG7AQgCnwF+AXkC9AFsARkDZgEHCv8BbAH0AWwBGQFmAgABDgHw - AgcCvALwAfEBvAEOAwAB7QGaAXoBHAGaBXoDWQFLAW0BAAG1Av8C2wEJAQgBfgF5Af8B9AFsAfMBZgEZ - AWYCBwS1AfcBtQLtApEB9AFsAfMBZgIAAQ4B8AMHArwC8AG8AQ4DAAEcAZoBegEcAZkHegFZAVIBSgHt - AQcK/wFsAfQBbAEZAWYBtQH/AQcK/wFsAfQBbAIAAQ4B8AQHArwB8AG8AQ4DAAEcAZoBoAF6ARwHmgJ6 - AXQBbQIHBLUB9wG1Au0CkQH0AWwB8wFmAbUB/wIHBLUB9wG1Au0CkQH0AWwCAAEOAfAC7wQHAbwBBwEO - AwABHAOgCBwC7QHsAXMCAAEHCv8BbAH0AWwBBwP/AQcK/wFsAgABDgHwA+8FBwEOAwABHASgAZoGegFz - BQACBwS1AfcBtQLtApEB9AFsAgcCtQIHBLUB9wG1Au0CkQIAAQ4BvATvBAcBDgMAARwBoAHDA6ABegMc - Au0BcwcAAQcK/wFsAgABBwr/AWwB9AFsAgABDgG8Be8DBwEOAwABHAGZAsMCoAEcAe0MAAIHBLUB9wG1 - Au0CkQIAAgcEtQH3AbUC7QKRAfQBbAIAAQ4B9APwA7wCBwEOBAAFHAHtHQABBwr/AWwCAAsOJwACBwS1 - AfcBtQLtApHgAAFCAU0BPgcAAT4DAAEoAwABQAMAASwDAAEBAQABAQUAAWABARYAA/8BAAb/AgAG/wIA - Bv8CAAH/AcMBwAEBAf4BfwIAAeABAQGAAQAB+AEfAgABwAEBAgAB4AEHAgABgAEBAgABwAEBAgAB4AEj - AgABgAEBAgABwAEjAgABgAEBAgABwAEjAgABgAMAAcABIwIAAYADAAHAASMBAAEBAYADAAHAASMBAAEB - AYADAAHAASMBAAEBAYADAAHAASMBgAEBAYADAAHAASMBwAEBAcADAAGAAQEB8AEBAeADAAHAAQEB8AEB - AfgBAQIAAeABAwHwAQMB/gF/AgAG/wIABv8CAAb/AgAa/wEAAQ8G/wEAAQ8B+AEHAv8BAAEPAQABAwHw - AQcBAAEHAQABDwEAAQMB4AEHAQABAwEAAQMCAAHAAQcBAAEDAQABAwIAAcABBwEAAQEEAAHAAQcBAAEB - BAABwAEHBgABwAEHBgABwAEHAgABwAMAAcABBwEAAQcBwAMAAcABBwEAAQcB8AEAAcABAAHAAQcBAAH/ - AfABAAHAAQABwAEHAYED/wHwAQABwAEHBP8B8AEAHP8L + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAi + EAAAAk1TRnQBSQFMAgEBCAEAAfwBAAH8AQABEAEAARYBAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + AwABQAMAAUIDAAEBAQABCAUAAYABEBgAAYACAAGAAwACgAEAAYADAAGAAQABgAEAAoACAAPAAQABwAHc + AcABAAHwAcoBpgEAATMFAAEzAQABMwEAATMBAAIzAgADFgEAAxwBAAMiAQADKQEAA1UBAANNAQADQgEA + AzkBAAGAAXwB/wEAAlAB/wEAAZMBAAHWAQAB/wHsAcwBAAHGAdYB7wEAAdYC5wEAAZABqQGtAgAB/wEz + AwABZgMAAZkDAAHMAgABMwMAAjMCAAEzAWYCAAEzAZkCAAEzAcwCAAEzAf8CAAFmAwABZgEzAgACZgIA + AWYBmQIAAWYBzAIAAWYB/wIAAZkDAAGZATMCAAGZAWYCAAKZAgABmQHMAgABmQH/AgABzAMAAcwBMwIA + AcwBZgIAAcwBmQIAAswCAAHMAf8CAAH/AWYCAAH/AZkCAAH/AcwBAAEzAf8CAAH/AQABMwEAATMBAAFm + AQABMwEAAZkBAAEzAQABzAEAATMBAAH/AQAB/wEzAgADMwEAAjMBZgEAAjMBmQEAAjMBzAEAAjMB/wEA + ATMBZgIAATMBZgEzAQABMwJmAQABMwFmAZkBAAEzAWYBzAEAATMBZgH/AQABMwGZAgABMwGZATMBAAEz + AZkBZgEAATMCmQEAATMBmQHMAQABMwGZAf8BAAEzAcwCAAEzAcwBMwEAATMBzAFmAQABMwHMAZkBAAEz + AswBAAEzAcwB/wEAATMB/wEzAQABMwH/AWYBAAEzAf8BmQEAATMB/wHMAQABMwL/AQABZgMAAWYBAAEz + AQABZgEAAWYBAAFmAQABmQEAAWYBAAHMAQABZgEAAf8BAAFmATMCAAFmAjMBAAFmATMBZgEAAWYBMwGZ + AQABZgEzAcwBAAFmATMB/wEAAmYCAAJmATMBAANmAQACZgGZAQACZgHMAQABZgGZAgABZgGZATMBAAFm + AZkBZgEAAWYCmQEAAWYBmQHMAQABZgGZAf8BAAFmAcwCAAFmAcwBMwEAAWYBzAGZAQABZgLMAQABZgHM + Af8BAAFmAf8CAAFmAf8BMwEAAWYB/wGZAQABZgH/AcwBAAHMAQAB/wEAAf8BAAHMAQACmQIAAZkBMwGZ + AQABmQEAAZkBAAGZAQABzAEAAZkDAAGZAjMBAAGZAQABZgEAAZkBMwHMAQABmQEAAf8BAAGZAWYCAAGZ + AWYBMwEAAZkBMwFmAQABmQFmAZkBAAGZAWYBzAEAAZkBMwH/AQACmQEzAQACmQFmAQADmQEAApkBzAEA + ApkB/wEAAZkBzAIAAZkBzAEzAQABZgHMAWYBAAGZAcwBmQEAAZkCzAEAAZkBzAH/AQABmQH/AgABmQH/ + ATMBAAGZAcwBZgEAAZkB/wGZAQABmQH/AcwBAAGZAv8BAAHMAwABmQEAATMBAAHMAQABZgEAAcwBAAGZ + AQABzAEAAcwBAAGZATMCAAHMAjMBAAHMATMBZgEAAcwBMwGZAQABzAEzAcwBAAHMATMB/wEAAcwBZgIA + AcwBZgEzAQABmQJmAQABzAFmAZkBAAHMAWYBzAEAAZkBZgH/AQABzAGZAgABzAGZATMBAAHMAZkBZgEA + AcwCmQEAAcwBmQHMAQABzAGZAf8BAALMAgACzAEzAQACzAFmAQACzAGZAQADzAEAAswB/wEAAcwB/wIA + AcwB/wEzAQABmQH/AWYBAAHMAf8BmQEAAcwB/wHMAQABzAL/AQABzAEAATMBAAH/AQABZgEAAf8BAAGZ + AQABzAEzAgAB/wIzAQAB/wEzAWYBAAH/ATMBmQEAAf8BMwHMAQAB/wEzAf8BAAH/AWYCAAH/AWYBMwEA + AcwCZgEAAf8BZgGZAQAB/wFmAcwBAAHMAWYB/wEAAf8BmQIAAf8BmQEzAQAB/wGZAWYBAAH/ApkBAAH/ + AZkBzAEAAf8BmQH/AQAB/wHMAgAB/wHMATMBAAH/AcwBZgEAAf8BzAGZAQAB/wLMAQAB/wHMAf8BAAL/ + ATMBAAHMAf8BZgEAAv8BmQEAAv8BzAEAAmYB/wEAAWYB/wFmAQABZgL/AQAB/wJmAQAB/wFmAf8BAAL/ + AWYBAAEhAQABpQEAA18BAAN3AQADhgEAA5YBAAPLAQADsgEAA9cBAAPdAQAD4wEAA+oBAAPxAQAD+AEA + AfAB+wH/AQABpAKgAQADgAMAAf8CAAH/AwAC/wEAAf8DAAH/AQAB/wEAAv8CAAP//wD/AP8A/wD/AP8A + WQANSwgAApkIAAEHDBIBBwQABw4BEAFtAWwCDgIAAVENUgFLBQAB7wFzARwBbgFKAQcGAAESDP8BEgMA + AQ4BDQFsAZABuwIJAfcCbAFmAg4BAAFSAXoBUgGgCHoBUgGgAVIBSwMAAZkBbgN0AVIBSwFEAUoBmQQA + AeoB/wn0AfMB/wHqCwABDgHqAWwBDwEOAQABUgF6AVIBoAF6AVgGeQFYAaABUgFLAgABcwFuAXQBmQJ0 + AVICSwFuAUQBbgEaAgAB6gH/AfQI7AHzAf8B6gQAAW0HAAFDAW0BDgIAAVIBegFSAaAKcwFSAUsBAAEc + AXQBmgJSAXQBegFMBUsBcwIAAW0B/wX0BfMB/wFtAwABbQHxAW0BBwG8AfAB8QIAAREBBwHsAgABUgF6 + AVIBoAFzAv8B8wP0AvMBcwFSAUsBAAGZAXMBUQF0AXoCdAFMA0sBSgFLAZMCAAFtAf8B9AjtAfMB/wFt + AwADbQEHArwB8AIAAm0BDgIAAVIBegFSAaABcwH/AdwF2wH0AXMBUgFLAQAB7AEcAXkCdAoSAQAB6wH/ + AfQJ8wH/AesDAAFtAfADBwK8AgABEQEHAewCAAFSAZoBUgH/AbwB/wYZAfMBvAFSAUsBAAIcAnQCBwPv + AfcBHAPtARIBAAHrAf8B8wH3B5IB8wH/AesDAAFtAfAB7wMHAbwCAAJtAQ4CAAFSAaANUgIAAe0BHAF0 + AUsBHAj/Ae0BEgEAAfgB/wrzAf8B+AMAAW0B8ALvAwcCAAERAQcB7AIAAVIDoAEcAf8BrgGaAb0BdQHj + Aa4B/wHtAesCAAHsAXMBdAFLAfcB/wauAf8B7QESAQAB7AH/AfMI7wHyAf8B7AMAAW0B8APvAgcCAAJt + AQ4CAAFSAf8CoAH3Af8BrgL/AnUBrgH/Ae0B6wIAAZMDdAHvAf8BrgGUAf8BmgGUAa4B/wHtARIBAAHs + Af8G8wX/AewDAAFtAbwE7wEHAgABEQEHAewDAAFSAv8B7wH/Aa4BlAH/AZoBlAGuAf8B7QHrAgABHAGZ + AcMBegHvAf8C0wH/AZoC0wH/Ae0BEgEAAe0B/wHzBe8B/wLyAfMB7QG8AwAIbQEAAQ8B7AEPBAACUgHv + Af8B0wSuAdMB/wHtAesDAAIcAZoB7wH/BtMB/wHtARIBAAHtAf8D8wPyAf8B8gHzAe0B8AQACQ4B6wGR + AQ0GAAHvAf8G0wH/Ae0B6wQAAZkBdAEHCP8B7QESAQABkgH/AfMF8gH/AfMBkgHwBQABDgFlAZABuwUJ + AfcBbAIOBQABBwj/Ae0B6wYAAgcD7wH3ARwD7QIAAZII/wGSAfARAAEOBgACBwPvAfcBHAPtCQACmQgA + AfAI9wHw/wCWAAH3Aq4BbQFsAeoCbARmNAAB9wX/AvQDGQFmCQAIDhMAAfcCrgFtAWwB6gJsBGYEAAG1 + Av8CkwGZAQcBuwG0AhkDZgYAAQ4BAAXvAfcBDgMAAnMB6wFuAW0BSgETARUBQwERAQ8BDgEPAwAB9wX/ + AvQDGQFmBAABtQL/AZMBmgF6AZ8BngG7AfQB8wFmARkBZgUAAQ4B7wEAAfAC8QLyAbwBDgMAAXMCHAcx + AksBRAHtAgABtQL/ApMBmQEHAbsBtAIZA2YCAAG1Av8BuwEIAp8BfgF5AvQBbAEZA2YCAAEOAe8BBwEA + AfAC8QLyAfABDgMAAewBegEcAZoDegJZAVMBUgExAUsB6gIAAbUC/wGTAZoBegGfAZ4BuwH0AfMBZgEZ + AWYCAAG1Av8C2wEJAQgBfgF5Af8B9AFsAfMBZgEZAWYCAAEOAgAB7wG8AfAC8QHyAfABDgMAAe0BegEc + AZkFegJZAVMBMQFEAe0BAAG1Av8BuwEIAp8BfgF5AvQBbAEZA2YBBwr/AWwB9AFsARkBZgIAAQ4B8AIH + ArwC8AHxAbwBDgMAAe0BmgF6ARwBmgV6A1kBSwFtAQABtQL/AtsBCQEIAX4BeQH/AfQBbAHzAWYBGQFm + AgcEtQH3AbUC7QKRAfQBbAHzAWYCAAEOAfADBwK8AvABvAEOAwABHAGaAXoBHAGZB3oBWQFSAUoB7QEH + Cv8BbAH0AWwBGQFmAbUB/wEHCv8BbAH0AWwCAAEOAfAEBwK8AfABvAEOAwABHAGaAaABegEcB5oCegF0 + AW0CBwS1AfcBtQLtApEB9AFsAfMBZgG1Af8CBwS1AfcBtQLtApEB9AFsAgABDgHwAu8EBwG8AQcBDgMA + ARwDoAgcAu0B7AFzAgABBwr/AWwB9AFsAQcD/wEHCv8BbAIAAQ4B8APvBQcBDgMAARwEoAGaBnoBcwUA + AgcEtQH3AbUC7QKRAfQBbAIHArUCBwS1AfcBtQLtApECAAEOAbwE7wQHAQ4DAAEcAaABwwOgAXoDHALt + AXMHAAEHCv8BbAIAAQcK/wFsAfQBbAIAAQ4BvAXvAwcBDgMAARwBmQLDAqABHAHtDAACBwS1AfcBtQLt + ApECAAIHBLUB9wG1Au0CkQH0AWwCAAEOAfQD8AO8AgcBDgQABRwB7R0AAQcK/wFsAgALDicAAgcEtQH3 + AbUC7QKR4AABQgFNAT4HAAE+AwABKAMAAUADAAFCAwABAQEAAQEFAAEQAQIWAAP/sQAZ/wHDAcABAQH+ + AX8BgAEBAeABAQGAAQAB+AEfAYABAQHAAQECAAHgAQcBgAEBAYABAQIAAcABAQGAAQEB4AEjAgABgAEB + AYABAQHAASMCAAGAAQEBgAEBAcABIwIAAYABAAGAAQEBwAEjAgABgAEAAYABAQHAASMBAAEBAYABAAGA + AQEBwAEjAQABAQGAAQABgAEBAcABIwEAAQEBgAEAAYABAQHAASMBgAEBAYABAAGAAQEBwAEjAcABAQHA + AQABgAEDAYABAQHwAQEB4AEAAYABBwHAAQEB8AEBAfgBAQGAAQ8B4AEDAfABAwH+AX8BgAEfMv8BAAEP + Bv8BAAEPAfgBBwL/AQABDwEAAQMB8AEHAQABBwEAAQ8BAAEDAeABBwEAAQMBAAEDAgABwAEHAQABAwEA + AQMCAAHAAQcBAAEBBAABwAEHAQABAQQAAcABBwYAAcABBwYAAcABBwIAAcADAAHAAQcBAAEHAcADAAHA + AQcBAAEHAfABAAHAAQABwAEHAQAB/wHwAQABwAEAAcABBwGBA/8B8AEAAcABBwT/AfABABz/Cw==