пятница, 6 июня 2014 г.

Простейший бот-кликер для игры

Есть такая игра http://armorgames.com/play/15760/gemcraft-chasing-shadows . Игра очень хорошая и вставляющая - качественный Tower Defense. С кучей миссий и прочим кайфом. Есть там также такая вещь, как талисман - и прокачивается за счёт так называемых "Shadom cores". Прикол в чём - игра построена по модели free-to-play поэтому играть можно и бесплатно, но если хочешь качаться быстрее плати. И тут возникает вопрос - "Откуда деньги у старого евреямолодого архонта?".

Думал я, думал и решил написать тупого простейшего бота. Чтобы он сам фармил это всё. Ситуацию облегчило две вещи - 1) Первый уровень - типа демонстрационный, с разными уже построенными камнями. 2) то что уже был достаточно прокачен и не требовалось ничего улучшать, строить дополнительно и прочее.

После пары ручных прогонов стало понятно, что от бота будет нужно 4 действия -
1. Выбрать миссию
2. Нажать кнопку "Start the Battle!"
3. Нажать кнопку "9х" (служить для ускорения в 9 раз игры)
4. После прохождения вернуться обратно на карту
И ПОВТОРЯТЬ, ПОВТОРЯТЬ, ПОВТОРЯТЬ

Решено было писать на C#. По сути всё свелось к одной единственной процедуре, которая "щелкала" мыщъ по переданным координатам.

        #region Send mouse click
        [DllImport("user32.dll")]
        static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, IntPtr dwExtraInfo);
 
        public const int MOUSEEVENTF_LEFTDOWN = 0x02;
        public const int MOUSEEVENTF_LEFTUP = 0x04;
 
        public static void SendClick(Point location)
        {
            Cursor.Position = location;
            mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, new IntPtr());
            mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, new IntPtr());
        }
        #endregion


        private void botAction()
        {
            Thread.Sleep(2000);
            SendClick(new Point(500, 660)); // Select mission
            Thread.Sleep(2000);
 
            SendClick(new Point(615, 875)); // Start the Battle!
            Thread.Sleep(6000);
 
            SendClick(new Point(141, 388)); // 9x speed
            Thread.Sleep(18000);
 
            SendClick(new Point(836, 928)); // Back to the Map
            Thread.Sleep(2000);
 
            Count++;
            labelCount.Text = Count.ToString();
        }

Данная процедура была засунута в таймер и оставлена на ночное выполнение. За ночь я набрал около 20к этих хреновин, что СЭКОНОМИЛО МНЕ ЦЕЛЫХ ПЯТЬ ДОЛЛАРОВ!!!



PS: Чтобы знать какие координаты прописывать ещё одна небольшая процедура.

        #region Get Cursor Location
        [DllImport("user32.dll")]
        static extern bool GetCursorPos(ref Point lpPoint);
 
        private void timer1_Tick(object sender, EventArgs e)
        {
            Point ptCoords = new Point();
            GetCursorPos(ref ptCoords);
 
            uint x = (uint)ptCoords.X;
            uint y = (uint)ptCoords.Y;
 
            labelX.Text = x.ToString();
            labelY.Text = y.ToString();
        }
        #endregion