/// <summary>
        /// Directory under which the stage is contained.
        /// </summary>
        /// <param name="StageDirectoryX">Subdirectory of the mod folder where the stage is contained.</param>
        public Feature_Inject_Stage(string StageDirectoryX)
        {
            // Get folder locations.
            Mod_Folder            = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            Heroes_Game_Directory = Environment.CurrentDirectory;
            StageDirectory        = StageDirectoryX;

            // Get Stage Properties based off of level configuration.
            Read_Config_File();

            // Read Original Memory Stuff.
            ASM_PushPointerTable_Old   = Program.Sonic_Heroes_Process.ReadMemory((IntPtr)PUSH_INSTRUCTION_POINTER, 5);
            STAGE_START_ORIGINAL_BYTES = Program.Sonic_Heroes_Process.ReadMemory((IntPtr)STAGE_START_POSITION_POINTER + 4, 0x8C);
            STAGE_END_ORIGINAL_BYTES   = Program.Sonic_Heroes_Process.ReadMemory((IntPtr)STAGE_END_POSITION_POINTER + 4, 0x64);

            // Get all trigger files and construct them.
            try
            {
                string[] TriggerFiles = Directory.GetFiles(Mod_Folder + "\\" + StageDirectory + "\\Triggers\\", "*.obj");
                for (int x = 0; x < TriggerFiles.Length; x++)
                {
                    FrameDelegates.Add(ConstructBox(TriggerFiles[x]));
                }
            }
            catch { } // No trigger files.

            // Get All Files & Construct All Splines.
            // If your stage has no splines, place one offscreen.
            string[] SplineFiles = Directory.GetFiles(Mod_Folder + "\\" + StageDirectory + "\\Splines\\", "*.obj");
            for (int x = 0; x < SplineFiles.Length; x++)
            {
                SplineHeader Spline = ConstructSpline(SplineFiles[x]); WriteSpline(Spline);
            }

            // Generate Spline Pointer Table
            Generate_Pointer_Table();

            // Backup Old Files
            BackupFiles();
        }
        /// <summary>
        /// Writes a spline onto game memory.
        /// </summary>
        /// <param name="Spline"></param>
        private void WriteSpline(SplineHeader Spline)
        {
            // Write Spline Vertices to Memory
            List <byte> VertexData = new List <byte>();

            // Add data fo all vertices.
            for (int x = 0; x < Spline.Vertices.Count(); x++)
            {
                VertexData.AddRange(BitConverter.GetBytes(Spline.Vertices[x].UnknownFlags));
                VertexData.AddRange(BitConverter.GetBytes(Spline.Vertices[x].DistanceToNextVertex));
                VertexData.AddRange(BitConverter.GetBytes(Spline.Vertices[x].PositionX));
                VertexData.AddRange(BitConverter.GetBytes(Spline.Vertices[x].PositionY));
                VertexData.AddRange(BitConverter.GetBytes(Spline.Vertices[x].PositionZ));
            }

            // Write Vertices to Memory
            Spline.Pointer_Vertex_List = (int)Program.Sonic_Heroes_Process.AllocateMemory(VertexData.Count);
            Program.Sonic_Heroes_Process.WriteMemory((IntPtr)Spline.Pointer_Vertex_List, VertexData.ToArray());

            // Construct Header File and Add to Header List.
            List <byte> HeaderData = new List <byte>();

            HeaderData.AddRange(BitConverter.GetBytes(Spline.Enabler));
            HeaderData.AddRange(BitConverter.GetBytes(Spline.Number_Of_Vertices));
            HeaderData.AddRange(BitConverter.GetBytes(Spline.Total_Spline_Length));
            HeaderData.AddRange(BitConverter.GetBytes(Spline.Pointer_Vertex_List));
            HeaderData.AddRange(BitConverter.GetBytes(Spline.Spline_Type));

            // Add spline to pointer list.
            int SplineHeaderPointer = (int)Program.Sonic_Heroes_Process.AllocateMemory(HeaderData.Count);

            Program.Sonic_Heroes_Process.WriteMemory((IntPtr)SplineHeaderPointer, HeaderData.ToArray());

            // Add Spline Header Pointer to List
            SplinePointers.Add(SplineHeaderPointer);
        }
        /// <summary>
        /// Constructs a spline from scratch.
        /// </summary>
        /// <param name="SplinePath"></param>
        private SplineHeader ConstructSpline(string SplinePath)
        {
            SplineHeader SplineFile = new SplineHeader();

            // Properties
            bool  CalculateSplineDistanceFlag = false;
            float SplineVertexDistance        = 0.0F;
            int   SplineVertexFlags           = 0;

            // Defaults
            SplineFile.Spline_Type = (int)Spline_Type.Autoloop;

            // Read Spline File
            List <HeroesVertexStruct> Vertices = new List <HeroesVertexStruct>(); // List of vertices for spline.

            string[] OBJ_File = File.ReadAllLines(SplinePath);                    // Read all of the lines.
            string[] Vertex_XYZ;                                                  // Used when splitting current lines of OBJ Files.

            // Iterate over all lines.
            for (int x = 0; x < OBJ_File.Length; x++)
            {
                try
                {
                    string Value = OBJ_File[x].Substring(OBJ_File[x].IndexOf("=") + 1);

                    // Check Spline Type
                    if (OBJ_File[x].StartsWith("SPLINE_TYPE"))
                    {
                        if (Value == "Loop")
                        {
                            SplineFile.Spline_Type = (int)Spline_Type.Autoloop;
                        }
                        else if (Value == "Rail")
                        {
                            SplineFile.Spline_Type = (int)Spline_Type.Rail;
                        }
                    }
                    else if (OBJ_File[x].StartsWith("SPLINE_VERTEX_FLAGS"))
                    {
                        SplineVertexFlags = Convert.ToInt32(Value, 16);
                    }
                    else if (OBJ_File[x].StartsWith("DISTANCE_TO_NEXT_POINT"))
                    {
                        if (Value == "Auto")
                        {
                            CalculateSplineDistanceFlag = true;
                        }
                        else
                        {
                            SplineVertexDistance = Convert.ToSingle(Value);
                        }
                    }
                    else if (OBJ_File[x].StartsWith("v"))
                    {
                        // Remove spaces, place strings to array.
                        Vertex_XYZ = OBJ_File[x].Split(' ');

                        // Define a new Vertex.
                        HeroesVertexStruct TempVertex;

                        // Set Flags
                        TempVertex.UnknownFlags = SplineVertexFlags;

                        // Set Distance between Verts.
                        if (!CalculateSplineDistanceFlag)
                        {
                            TempVertex.DistanceToNextVertex = SplineVertexDistance;
                        }
                        else
                        {
                            TempVertex.DistanceToNextVertex = 0.0F;
                        }

                        // Get coordinates.
                        TempVertex.PositionX = Convert.ToSingle(Vertex_XYZ[1]);
                        TempVertex.PositionY = Convert.ToSingle(Vertex_XYZ[2]);
                        TempVertex.PositionZ = Convert.ToSingle(Vertex_XYZ[3]);
                        Vertices.Add(TempVertex);
                    }
                } catch { }
            }

            // Read all vertices.
            SplineFile.Vertices = Vertices;

            // Set properties
            SplineFile.Enabler            = 1;
            SplineFile.Number_Of_Vertices = (ushort)SplineFile.Vertices.Count;

            // Calculate Distance to Next Vertex if Auto
            if (CalculateSplineDistanceFlag)
            {
                for (int x = 0; x < SplineFile.Vertices.Count; x++)
                {
                    try
                    {
                        HeroesVertexStruct TempVertex = SplineFile.Vertices[x];

                        // Get the difference in current and location of next spline.
                        float X_Delta_Position = SplineFile.Vertices[x].PositionX - SplineFile.Vertices[x + 1].PositionX;
                        float Y_Delta_Position = SplineFile.Vertices[x].PositionY - SplineFile.Vertices[x + 1].PositionY;
                        float Z_Delta_Position = SplineFile.Vertices[x].PositionZ - SplineFile.Vertices[x + 1].PositionZ;

                        float Length_Squared = (X_Delta_Position * X_Delta_Position) + (Y_Delta_Position * Y_Delta_Position) + (Z_Delta_Position * Z_Delta_Position);
                        TempVertex.DistanceToNextVertex = (float)Math.Sqrt(Length_Squared);
                        SplineFile.Vertices[x]          = TempVertex;
                    } catch { } // Throws exception on last vertex, leaving it untouched.
                }
            }

            // Calculate Spline Length
            SplineFile.Total_Spline_Length = 0F;
            for (int x = 0; x < SplineFile.Vertices.Count; x++)
            {
                SplineFile.Total_Spline_Length += SplineFile.Vertices[x].DistanceToNextVertex;
            }

            return(SplineFile);
        }