static void Main(string[] args)
        {
            ProcUtils proc;
            KeyUtils keys = new KeyUtils();
            CHConfig config = new CHConfig();
            config.ReadSettingsFromFile("chconfig.cfg");
            bool clicker = true,
                drawing = true,
                randomize = false,
                firstRun = true,
                castSpells = false,
                advanceLevels = true;
            Random random = new Random();
            Point[] trail = new Point[16];

            while (!keys.KeyIsDown(WinAPI.VirtualKeyShort.F10))
            {
                Console.Clear();
                Console.WriteLine("Controls:\n" +
                    "F10: Terminate\n" +
                    "F9: Toggle auto-clicker\n" +
                    "F8: Toggle drawing\n" +
                    "F7: Toggle randomization\n" +
                    "Num9/Num6: Increase/decrease clicker-offset (x)\n" +
                    "Num8/Num5: Increase/decrease clicker-offset (y)\n" +
                    "F6: Save window-size and -position and clicker-offsets\n" +
                    "F5: Apply saved window-size and -position to game-window\n" +
                    "F4: Toggle spell-casting");

                firstRun = true;
                Console.WriteLine("Wait for ClickerHeroes to start...");
                while (!ProcUtils.ProcessIsRunning("Clicker Heroes")) { Thread.Sleep(500); }
                proc = new ProcUtils("Clicker Heroes", WinAPI.ProcessAccessFlags.VirtualMemoryOperation);

                Console.WriteLine("Wait for ClickerHeroes' window to show up...");
                while (proc.Process.MainWindowHandle == IntPtr.Zero) { Thread.Sleep(500); }
                while (ProcUtils.ProcessIsRunning("Clicker Heroes"))
                {
                    Thread.Sleep(8);

                    keys.Update();
                    if (keys.KeyWentUp(WinAPI.VirtualKeyShort.F9))
                        clicker = !clicker;
                    if (keys.KeyWentUp(WinAPI.VirtualKeyShort.F8))
                        drawing = !drawing;
                    if (keys.KeyWentUp(WinAPI.VirtualKeyShort.F7))
                        randomize = !randomize;
                    if (keys.KeyWentUp(WinAPI.VirtualKeyShort.F4))
                        castSpells = !castSpells;
                    if (keys.KeyWentUp(WinAPI.VirtualKeyShort.F3))
                        advanceLevels = !advanceLevels;

                    if (keys.KeyWentUp(WinAPI.VirtualKeyShort.NUMPAD8))
                        config.SetValue("offsetY", config.GetValue<int>("offsetY") + 1);
                    if (keys.KeyWentUp(WinAPI.VirtualKeyShort.NUMPAD5))
                        config.SetValue("offsetY", config.GetValue<int>("offsetY") - 1);
                    if (keys.KeyWentUp(WinAPI.VirtualKeyShort.NUMPAD9))
                        config.SetValue("offsetX", config.GetValue<int>("offsetX") + 1);
                    if (keys.KeyWentUp(WinAPI.VirtualKeyShort.NUMPAD6))
                        config.SetValue("offsetY", config.GetValue<int>("offsetY") + 1);
                    if (keys.KeyWentUp(WinAPI.VirtualKeyShort.F5))
                    {
                        firstRun = true;
                        config.ReadSettingsFromFile("chconfig.cfg");
                    }

                    WinAPI.WINDOWINFO info = new WinAPI.WINDOWINFO();
                    if (!WinAPI.GetWindowInfo(proc.Process.MainWindowHandle, ref info))
                        continue;

                    if (firstRun)
                    {
                        if (config.GetValue<int>("windowHeight") != 0 || config.GetValue<int>("windowWidth") != 0 || config.GetValue<int>("windowX") != 0 || config.GetValue<int>("windowY") != 0)
                        {
                            WinAPI.SetWindowPos(proc.Process.MainWindowHandle, IntPtr.Zero, config.GetValue<int>("windowX"), config.GetValue<int>("windowY"), config.GetValue<int>("windowWidth"), config.GetValue<int>("windowHeight"), 0);
                        }

                        for (int i = 0; i < trail.Length; i++)
                            trail[i] = new Point(0, 0);

                        firstRun = false;
                    }
                    if (keys.KeyWentUp(WinAPI.VirtualKeyShort.F6))
                    {
                        config.SetValue("windowWidth", info.rcWindow.Right - info.rcWindow.Left);
                        config.SetValue("windowHeight", info.rcWindow.Bottom - info.rcWindow.Top);
                        config.SetValue("windowX", info.rcWindow.Left);
                        config.SetValue("windowY", info.rcWindow.Top);
                        config.SaveSettingsToFile("chconfig.cfg");
                    }

                    int width = info.rcClient.Right - info.rcClient.Left;
                    int height = info.rcClient.Bottom - info.rcClient.Top;
                    int sin = (int)(Math.Sin(DateTime.Now.TimeOfDay.TotalSeconds * 10) * width * 0.06);
                    int cos = (int)(Math.Cos(DateTime.Now.TimeOfDay.TotalSeconds * 10) * height * 0.07);
                    int randomD = (int)Math.Sqrt(Math.Sqrt(width * height));
                    int click_x = (int)(width * 0.725) + sin + config.GetValue<int>("offsetX");
                    int click_y = (int)(height * 0.55) + cos + config.GetValue<int>("offsetY");

                    if (randomize)
                    {
                        random = new Random(random.Next(0, (int)Environment.TickCount));
                        click_x += random.Next(0, randomD) * (random.Next(0, 2) == 1 ? 1 : -1);
                        click_y += random.Next(0, randomD) * (random.Next(0, 2) == 1 ? 1 : -1);
                    }

                    if (advanceLevels && clicker)
                    {
                        int x = (int)(width * 0.81);
                        int y = (int)(height * 0.06);
                        int lParam = WinAPI.MakeLParam(x, y);
                        int wParam = 0;
                        WinAPI.SendMessage(proc.Process.MainWindowHandle, (uint)WinAPI.WindowMessage.WM_LBUTTONDOWN, wParam, lParam);
                        WinAPI.SendMessage(proc.Process.MainWindowHandle, (uint)WinAPI.WindowMessage.WM_LBUTTONUP, wParam, lParam);
                    }

                    if (clicker)
                    {

                        int lParam = WinAPI.MakeLParam(click_x, click_y);
                        int wParam = 0;
                        WinAPI.SendMessage(proc.Process.MainWindowHandle, (uint)WinAPI.WindowMessage.WM_LBUTTONDOWN, wParam, lParam);
                        WinAPI.SendMessage(proc.Process.MainWindowHandle, (uint)WinAPI.WindowMessage.WM_LBUTTONUP, wParam, lParam);
                    }

                    if (castSpells)
                    {
                        for (uint i = 0; i < 10; i++)
                        {
                            uint key = (uint)WinAPI.VirtualKeyShort.KEY_0 + i;
                            uint scanCode = WinAPI.MapVirtualKey(key, 0);
                            uint lParam = lParam = (0x00000001 | (scanCode << 16));

                            WinAPI.SendMessage(proc.Process.MainWindowHandle, (uint)WinAPI.WindowMessage.WM_KEYDOWN, (int)key, (int)lParam);
                            WinAPI.SendMessage(proc.Process.MainWindowHandle, (uint)WinAPI.WindowMessage.WM_KEYUP, (int)key, (int)lParam);
                        }
                    }

                    if (drawing)
                    {

                        Point[] tmp = new Point[trail.Length];
                        Array.Copy(trail, 1, tmp, 0, trail.Length - 1);
                        trail = tmp;
                        trail[trail.Length - 1] = new Point(click_x, click_y);
                        try
                        {
                            using (Graphics g = Graphics.FromHwnd(proc.Process.MainWindowHandle))
                            {
                                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

                                g.DrawRectangle(Pens.Black, width / 2f, 0, width / 2f, height);

                                StringBuilder builder = new StringBuilder();
                                builder.AppendLine("ClickerHeroes - ExternalUtilsCSharp");
                                builder.AppendFormat("Autoclicker: {0}\n", clicker.ToString());
                                builder.AppendFormat("Randomize: {0}\n", randomize.ToString());
                                builder.AppendFormat("Cast spells: {0}\n", castSpells.ToString());
                                builder.AppendFormat("Offsets (x,y): {0} {1}\n", config.GetValue<int>("offsetX").ToString(), config.GetValue<int>("offsetY").ToString());
                                builder.AppendFormat("Current Window size (w,h): {0} {1}\n", (info.rcWindow.Right - info.rcWindow.Left).ToString(), (info.rcWindow.Bottom - info.rcWindow.Top).ToString());
                                builder.AppendFormat("Current Window coords (x,y): {0} {1}\n", info.rcWindow.Left.ToString(), info.rcWindow.Top.ToString());
                                builder.AppendFormat("Saved Window size (w,h): {0} {1}\n", config.GetValue<int>("windowWidth").ToString(), config.GetValue<int>("windowHeight").ToString());
                                builder.AppendFormat("Saved Window coords (x,y): {0} {1}", config.GetValue<int>("windowX").ToString(), config.GetValue<int>("windowY").ToString());

                                using (Font fnt = new Font("Courier New", 8))
                                {
                                    string text = builder.ToString();
                                    SizeF size = g.MeasureString(text, fnt);
                                    g.FillRectangle(Brushes.Black, width / 2f, 0, size.Width + 8, size.Height + 8);
                                    g.DrawString(text, fnt, Brushes.Red, width / 2f + 4, 4);
                                }

                                for (int i = trail.Length - 1; i >= 1; i--)
                                {
                                    if (trail[i].X != 0 && trail[i].Y != 0 && trail[i - 1].X != 0 && trail[i - 1].Y != 0)
                                    {
                                        g.DrawLine(Pens.Red, trail[i], trail[i - 1]);
                                    }
                                }
                                g.FillEllipse(Brushes.Red, click_x - 8, click_y - 8, 16, 16);
                                int x = (int)(width * 0.81);
                                int y = (int)(height * 0.06);
                                g.FillEllipse(Brushes.Red, x - 8, y - 8, 16, 16);
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Drawing failed: {0}", ex.Message);
                        }
                    }
                }
            }
        }
        private static void overlay_TickEvent(object sender, SharpDXOverlay.DeltaEventArgs e)
        {
            seconds += e.SecondsElapsed;
            //Update logic
            KeyUtils.Update();
            Framework.Update();
            SHDXOverlay.UpdateControls(e.SecondsElapsed, KeyUtils);

            //Process input
            if (KeyUtils.KeyWentUp(WinAPI.VirtualKeyShort.DELETE))
            {
                SHDXOverlay.Kill();
            }
            if (KeyUtils.KeyWentUp(WinAPI.VirtualKeyShort.INSERT))
            {
                Framework.MouseEnabled = !Framework.MouseEnabled;
            }
            if (KeyUtils.KeyWentUp(WinAPI.VirtualKeyShort.HOME))
            {
                windowMenu.Visible = !windowMenu.Visible;
            }

            //Update UI
            cursor.Visible = !Framework.MouseEnabled;

            if (seconds >= 1)
            {
                seconds = 0;
                graphMemRead.AddValue(MemUtils.BytesRead);
                graphMemWrite.AddValue(MemUtils.BytesWritten);
            }

            ctrlRadar.X     = SHDXOverlay.Width - ctrlRadar.Width;
            ctrlCrosshair.X = SHDXOverlay.Width / 2f;
            ctrlCrosshair.Y = SHDXOverlay.Height / 2f;


            for (int i = 0; i < ctrlPlayerESP.Length; i++)
            {
                ctrlPlayerESP[i].Visible = false;
            }

            labelAimbot.Text          = string.Format("Aimbot: {0}", Framework.AimbotActive ? "ON" : "OFF");
            labelAimbot.ForeColor     = Framework.AimbotActive ? SharpDX.Color.Green : windowBots.Caption.ForeColor;
            labelTriggerbot.Text      = string.Format("Triggerbot: {0}", Framework.TriggerbotActive ? "ON" : "OFF");
            labelTriggerbot.ForeColor = Framework.TriggerbotActive ? SharpDX.Color.Green : windowBots.Caption.ForeColor;

            windowGraphs.Visible     = ConfigUtils.GetValue <bool>("windowPerformanceEnabled");
            windowBots.Visible       = ConfigUtils.GetValue <bool>("windowBotsEnabled");
            windowSpectators.Visible = ConfigUtils.GetValue <bool>("windowSpectatorsEnabled");
            ctrlRadar.Visible        = ConfigUtils.GetValue <bool>("radarEnabled");
            ctrlRadar.Width          = ConfigUtils.GetValue <float>("radarWidth");
            ctrlRadar.Height         = ConfigUtils.GetValue <float>("radarHeight");
            if (ctrlCrosshair.PrimaryColor.ToRgba() != colorControlCrosshairPrimary.SDXColor.ToRgba())
            {
                ctrlCrosshair.PrimaryColor = colorControlCrosshairPrimary.SDXColor;
            }
            if (ctrlCrosshair.SecondaryColor.ToRgba() != colorControlCrosshairSecondary.SDXColor.ToRgba())
            {
                ctrlCrosshair.SecondaryColor = colorControlCrosshairSecondary.SDXColor;
            }
            ctrlCrosshair.Type        = (Crosshair.Types)ConfigUtils.GetValue <int>("crosshairType");
            ctrlCrosshair.Visible     = ConfigUtils.GetValue <bool>("crosshairEnabled");
            ctrlCrosshair.Outline     = ConfigUtils.GetValue <bool>("crosshairOutline");
            ctrlCrosshair.Radius      = ConfigUtils.GetValue <float>("crosshairRadius");
            ctrlCrosshair.Width       = ConfigUtils.GetValue <float>("crosshairWidth");
            ctrlCrosshair.SpreadScale = ConfigUtils.GetValue <float>("crosshairSpreadScale");

            if (Framework.LocalPlayer != null)
            {
                Weapon wpn = Framework.LocalPlayer.GetActiveWeapon();
                if (wpn != null)
                {
                    ctrlCrosshair.Spread = wpn.m_fAccuracyPenalty * 10000;
                }
                else
                {
                    ctrlCrosshair.Spread = 1f;
                }
            }
            else
            {
                ctrlCrosshair.Spread = 1f;
            }
            if (Framework.IsPlaying())
            {
                #region ESP
                for (int i = 0; i < ctrlPlayerESP.Length && i < Framework.Players.Length; i++)
                {
                    if (Framework.Players[i].Item2.m_iDormant != 1 &&
                        (ConfigUtils.GetValue <bool>("espEnemies") && Framework.Players[i].Item2.m_iTeamNum != Framework.LocalPlayer.m_iTeamNum) ||
                        (ConfigUtils.GetValue <bool>("espAllies") && Framework.Players[i].Item2.m_iTeamNum == Framework.LocalPlayer.m_iTeamNum))
                    {
                        ctrlPlayerESP[i].Visible = true;
                    }
                    ctrlPlayerESP[i].Player = Framework.Players[i].Item2;
                }
                #endregion
                #region Spectators
                if (Framework.LocalPlayer != null)
                {
                    var           spectators = Framework.Players.Where(x => x.Item2.m_hObserverTarget == Framework.LocalPlayer.m_iID && x.Item2.m_iHealth == 0 && x.Item2.m_iDormant != 1);
                    StringBuilder builder    = new StringBuilder();
                    foreach (Tuple <int, CSPlayer> spec in spectators)
                    {
                        CSPlayer player = spec.Item2;
                        builder.AppendFormat("{0} [{1}]{2}", Framework.Names[player.m_iID], (SpectatorView)player.m_iObserverMode, builder.Length > 0 ? "\n" : "");
                    }
                    if (builder.Length > 0)
                    {
                        labelSpectators.Text = builder.ToString();
                    }
                    else
                    {
                        labelSpectators.Text = "<none>";
                    }
                }
                else
                {
                    labelSpectators.Text = "<none>";
                }
                #endregion
            }
            else
            {
                labelSpectators.Text = "<none>";
                //ctrlRadar.Visible = false;
            }
        }