Home Developers COMO HACER UN BOT (MACRO BASED) by @AdrianDelahaze

COMO HACER UN BOT (MACRO BASED) by @AdrianDelahaze

by Adrián Hernando

Con este Post cuento con la colaboración de Adrián Hernando, antiguo alumno y profesional de gran valor. Su pasión la programación, que junto a sus conocimientos de sistemas y seguridad informática hacen que sea un gran profesional.

Os dejo sin más con su artículo, que como veréis está hecho en forma y contenido en “Salesians Style” , o lo que es lo mismo… bueno en forma y contenido. Espero os guste, a la vez que espero contar con más colaboraciones suyas.

La explicación la comenta con un video cuyo enlace encontraréis al final del Post. Os dejo si más con este gran Post.

INTRODUCCIÓN

Como es mi primer tutorial, me voy a tomar el lujo de presentarme

Hola, soy Adrián Hernando, conocido como “Kuhi” en el mundo de los bots y hacking de juegos. Dirijo la página web www.kuhiscripts.com

Soy antiguo alumno de Salesians de Sarrià ( https://twitter.com/salesianssarria ) y alumno de SEAS y Udemy.

Me considero un entusiasta de todo el software en general, y estoy estudiando un doble máster en Programación y Seguridad Informática.

Mostraré parte de mis conocimientos para intentar motivar que más gente se interese por estas actividades.

En este tutorial vamos a aprender a programar un game bot basado en macros muy fácilmente y posteriormente ponerlo en segundo plano para poder olvidarnos de que la macro está trabajando por nosotros.

OBJETIVO

Diseñar un programa de escritorio para Windows, para detectar el estado de nuestro personaje dentro de un juego y realizar tareas con el programa que realizaríamos nosotros mismos jugando manualmente.

REFERENCIAS

Ayuda con dudas:

https://es.stackoverflow.com/

https://foro.elhacker.net

https://docs.microsoft.com/es-es/dotnet/

Librerías de funciones:

https://pinvoke.net/

https://docs.microsoft.com/es-es/dotnet/

Ingeniería inversa:

https://www.youtube.com/user/Bl1pi

PREPARACIÓN

Necesitaremos Cheat Engine (yo utilizo el 6.8.1) y Visual Studio Community 2017.

Descarga Cheat Engine: https://www.cheatengine.org/

Descarga Visual Studio: https://visualstudio.microsoft.com/downloads/

AVISO: en el Visual Studio Installer debemos seleccionar el “Desarrollo de escritorio de .NET”

AVISO: al descargar CE (Cheat Engine), antes de iniciar la descarga salta una publicidad muy molesta, pero no cerrar la pestaña simplemente IGNORAR/IGNORAR y comenzará la descarga.

A parte, necesitaremos una víctima, que en este caso va a ser un juego llamado Tibia.

http://kuhibot.sytes.net/softwares/CLIENT%20WITH%20LIGHT%20AND%20MAP.exe

PLANTEAMIENTO DEL BOT

Primero, vamos a entender la lógica de un bot para un juego.

Cuando ejecutamos un juego, se cargan en la memoria del proceso todos los valores que el juego utiliza. Por ejemplo, la vida del personaje.

Dichos valores de los juegos se suelen almacenar en la memoria del ordenador, por lo que podemos leer valores del proceso (Tibia.exe) y realizar una tarea o otra dependiendo de los valores que nos lleguen.

TIPOS DE BOTS PARA JUEGOS

Hay dos tipos de bots para juegos (Game Bots): los que están basados en macros y los que llaman funciones. Fuera del mundo gamer, hay muchos otros tipos de bots, por ejemplo un web crawler que se encargaría de hacer solicitudes web y procesar el resultado.

MACROS

Una macro es un script o programa que repite acciones del teclado / ratón.

Los basados en macros, tienen varias opciones pueden ser cada X tiempo realizar X movimientos del teclado y/o ratón, puede ser también leer direcciones de memoria para controlar la vida, posición del jugador, posición del enemigo, etc… y también pueden combinar estas dos opciones, controlando los valores del juego y reaccionando según lo que obtengamos.

FUNCIONES

Una función es un trozo de código, que tiene su objetivo determinado, por ejemplo:

Función Sumar(A, B)

{

Return A+B

}

Esta función tiene el objetivo de recibir dos valores (A y B), y de devolver “return” el resultado. Al tener esta función dentro de un código lo que conseguimos es poder llamar “invocar” a la función en el momento que queramos, por ejemplo:

sumar(10,5)

Al poner esa línea en nuestro código estamos invocando a la función sumar.

El símbolo () se utiliza para diferenciar una función de una variable (una variable es simplemente un espacio para guardar datos, por ejemplo A y B en el caso anterior de sumar son 2 variables). Y dentro de () pondremos los parámetros para invocar a esa función.

Un parámetro es simplemente un valor que se le pasa a esa función para invocarla correctamente. Por ejemplo:

sumar(10)

Como podemos ver, estamos invocando a sumar, pero no estamos invocando con sus parámetros correctos, porqué la función sumar espera que al invocar se introduzca A y B y si alguno de los dos no se introduce tendremos errores y no funcionará.

Esto es importante porqué en los juegos también hay funciones como puede ser atacar(), y si queremos, también podemos invocar esas funciones cuando nos convenga.

Un ejemplo sería atacar(id_del_objetivo)

Le estamos diciendo al juego que ataque a lo que encuentre con el id que le indiquemos.

Todo esto se podría resumir en bots externos e internos.

Los externos no invocan funciones del juego, y los internos sí.

Lo cual hace que un bot externo sea infinitamente más seguro que un bot interno.

PREPARANDO EL ARSENAL

Cuando queremos hacer un bot, tenemos básicamente cuatro opciones, la primera de ellas es 100% OBLIGATORIA EN TODOS LOS CASOS y de las otras dos se debe seleccionar UNA DE ELLAS ÚNICAMENTE. La 4 es opcional pero muy recomendable.

OPCIÓN 1: buscar información en foros, youtube, en donde sea para intentar encontrar las direcciones de memoria y funciones (no del juego si no de otros bots) para “copiar” en nuestro bot. Podemos buscar bots de otros juegos no solo del juego que vayamos a usar.

Puede parecer una tontería poner esta opción como obligatoria, pero es muchísimo mejor reciclar un código que nosotros le veamos lógica, añadiendo valores actualizados y los retoques que nosotros queramos, en vez de pelearnos a sacar las funciones desde 0.

Siempre (y la mayoría de las veces así será) podemos encontrar ideas nuevas, optimizaciones a nuestro código, y la más importante: darnos cuenta de cosas que hemos estado haciendo mal desde el principio.

OPCIÓN 2: hacer el bot externo.

OPCIÓN 3: hacer el bot interno.

OPCIÓN 4: preparar café.

PRIMEROS PASOS

Primero abriremos el juego, y posteriormente el CE.

Al abrir el CE debemos cargar el juego:

Ahora podemos leer los valores que necesitemos del juego.

Para esta guía voy a hacer un bot para hacer un hechizo cuando tengamos suficiente maná/energía, y también use la comida cada 1 minuto. La lógica de esto, es que en este juego se recarga el maná comiendo, y se sube el nivel mágico gastando maná. Por lo que con este bot podremos subir nivel mágico automáticamente.

Primero vamos a buscar la dirección de memoria del maná.

Yo tengo 15 puntos de maná, por lo que busco el valor 15.

Algunos valores pueden ser 4 Bytes, Double, Float, String… es decir que podemos estar buscando el maná como valor 15 de 4 Bytes, pero en verdad es valor 15 de Float.

Es decir que si no nos aparece el maná con Value Type: 4 Bytes, probar los otros.

Por ejemplo: en “Value:” ponemos 15 igual, pero en “Value Type:” ponemos “Float”. Y así hasta que encontremos nuestro valor.

Al darle a “First Scan” podemos ver como CE encontrará (normalmente muchísimas) direcciones de memoria diferentes.

Y vamos a tener en cuenta 2 cosas:

– Cuantas menos direcciones de memoria tengamos en “Found:” mejor.

– Las direcciones de memoria que nos interesan son las verdes (las encontraremos más adelante), las negras son dinámicas y cada vez que se abre el juego se reservan aleatoriamente. Mientras que las verdes son fijas y aunque cerremos el juego, cuando lo volvamos a abrir seguirán igual que antes.

Ejemplo:

Si queremos encontrar nuestra dirección de memoria, entre 2551 resultados nos vamos a volver locos. Si el valor que estabamos buscando, no ha cambiado, simplemente le daremos a “Next Scan”.

Como podemos ver ahora tenemos menos resultados, pero siguen siendo muchos.

Los resultados que han desaparecido eran los números rojos que cambiaban de valor en CE.

Como el valor ha cambiado y nuestro maná sigue siendo el mismo, esos estan descartados.

Ahora vamos a cambiar nuestro maná para descartar más direcciones en CE.

En este juego se cambia el maná comiendo (la parte de comer del juego nos la saltamos).

Vamos al CE y seleccionamos en “Scan Type” la opción “Changed Value”, para decirle a CE, que nos guarde todos los valores que hayan cambiado desde el último scan

 

Si le damos varias veces, conseguiremos reducir el número de resultados en “Found:”.

Ya tenemos la dirección estática del maná (5C682C).

En este juego es sencillo, pero en otros como he comentado antes puede ser dinámico.

CREANDO EL BOT Y INYECTANDO EN EL CLIENTE

Vamos a crear una aplicación de Windows Form (una ventana de Windows).

Abrimos el Visual Studio Community 2017 y creamos un nuevo proyecto.

Seleccionamos Aplicación de Windows Forms (.NET Framework) de Visual Basic.

Ahora vamos a colocar un “Timer”. Un Timer se encarga de realizar lo que le digamos cada X tiempo. Por ejemplo podemos poner un “Timer” que cada 3 segundos nos cambie un texto de color. Si el texto está en verde lo ponemos en amarillo, y si está en amarillo lo ponemos en verde. Con eso tendríamos unas letras “luminosas”.

Para poner un timer lo buscamos en el cuadro de herramientas y le damos doble click al que ponga “Componentes”:

Si no encontramos el componente, lo podemos añadir manualmente:

Click derecho en “Todo Windows Forms” y seleccionamos “Elegir elementos…”

Dejamos que cargue los elementos y cuando haya finalizado en “Filtro:” escribimos el componente:

Como estamos trabajando con Windows Forms (al crear el proyecto hemos seleccionado Windows Forms), el nuestro es el que está marcado en la imágen, lo marcaríamos el recuadro y pulsamos “Aceptar”. Con eso tenemos agregado el componente al Cuadro de herramientas.

Ahora en la parte de abajo tenemos un Timer1 que si lo seleccionamos lo podremos editar.

Le vamos a poner de nombre TimerEat, lo desactivaremos, le pondremos un intervalo de 1 minuto y lo modificaremos como Público.

Ahora hacemos doble click en el Timer1, donde hemos seleccionado para poder editar.

Visual Studio nos genera un código ya preparado para escribir.

Nosotros únicamente tenemos que darle instrucciones.

Por ahora le ponemos nombre (click derecho en Form1.vb – Cambiar nombre) y lo dejaremos así. Si nos salta un aviso, aceptamos y se nos cambiará automáticamente el nombre en todo el proyecto.

Con esto, tenemos una ventana de Windows creada, con un Timer.

Ahora vamos a crear un módulo (otro código), que se encargará de detectar el juego y migrar nuestro proceso al mismo proceso del juego, para poder leer de él.

Yo le voy a llamar ProcessRoutines.vb pero cada uno le puede llamar como quiera (cuidado que existen nombres reservados y se puede liar una buena).

Ahora si nos fijamos en el módulo que hemos creado tenemos dos líneas.

Entre esas dos líneas debemos escribir:

Private Declare Function OpenProcess Lib "kernel32.dll" (ByVal dwDesiredAcess As UInt32, ByVal bInheritHandle As Boolean, ByVal dwProcessId As Int32) As IntPtr

Public Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer() As Byte, ByVal iSize As Integer, ByRef lpNumberOfBytesRead As Integer) As Boolean

Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As IntPtr) As Boolean

Con esto podremos migrar al proceso, leer de él y salir del proceso.

Dejaremos un espacio de 1 línea, y añadiremos:

Public _targetProcess As Process = Nothing

Public _targetProcessHandle As IntPtr = IntPtr.Zero

Private PROCESS_ALL_ACCESS As UInt32 = &H1F0FFF

Private PROCESS_VM_READ As UInt32 = &H10

Con esto conseguimos almacenar los detalles del proceso en nuestro código y tener acceso de lectura.

Y volveremos a dejar otra línea y añadiremos el siguiente código:

'Find process

Public Function TryAttachToProcess(ByVal windowCaption As String) As Boolean

Dim _allProcesses() As Process = Process.GetProcesses

For Each pp As Process In _allProcesses

If pp.MainWindowTitle.ToLower.Contains(windowCaption.ToLower) Then

'found it! proceed.

Return TryAttachToProcess(pp)

End If

Next

MessageBox.Show("Unable to find process '" & windowCaption & ".' Is running?")

Return False

End Function

'Inject to process

Private Function TryAttachToProcess(ByVal proc As Process) As Boolean

If _targetProcessHandle = IntPtr.Zero Then 'not already attached

_targetProcess = proc

_targetProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, False, _targetProcess.Id)

If CInt(_targetProcessHandle) = 0 Then

TryAttachToProcess = False

MessageBox.Show("FAIL! Are you Administrator??")

Else

'if we get here, all connected and ready to use ReadProcessMemory()

TryAttachToProcess = True

End If

Else

MessageBox.Show("Already attached!")

TryAttachToProcess = False

End If

End Function

Quedará así:

Básicamente es el código que da funcionalidad a las características que he comentado antes, migración, lectura y salida.

Ahora que ya hemos añadido las funciones para inyectar al proceso, leer memoria del proceso, y soltar el proceso. Podemos hacer que al cargar el programa, se inyecte el proceso.

Vamos al proyecto inicial, que tiene el icono de una ventana.

Hacemos click derecho y seleccionamos “Ver diseñador”.

Vamos a añadir un cuadro de texto para ver que se ha inyectado el proceso.

Buscamos “textbox” y hacemos doble click al último, de “Controles comunes”.

Podemos mover el cuadro de texto a una zona que nos guste más y acceder a sus propiedades para cambiar el nombre y el contenido inicial (que inicie a 0).

Y haremos doble click en el fondo de la ventana.

Se nos cargará un código nuevo, Load. El Load se encarga de ejecutar el código que contenga, cuando esa ventana se abre.

Dentro del Load, añadiremos el siguiente código:

Try

TryAttachToProcess("Classictibia")

txtPID.Text = "PID: " + _targetProcess.Id.ToString

Catch ex As Exception

MsgBox("Injection failed!")

End Try

Con esto hacemos que al cargar el programa, migremos al proceso del juego y mostremos el ID de proceso en el cuadro de texto.

Ahora vamos a iniciar la aplicación y ver que todo funciona.

Este es el resultado:

Si el programa muestra el ID del proceso, quiere decir que todo ha ido bien.

Hemos creado un programa que detecta el juego (siempre que no cambie de nombre Classictibia ), devolviendo el ID de proceso y en caso de error saltar un mensaje.

CREANDO EL MANATRAIN (MACRO PARA GASTAR ENERGÍA/MANÁ HACIENDO HECHIZOS)

Para leer valores del juego, llamaremos a la función que tenemos creada: ReadProcessMemory()

Y vamos a crear un módulo para las direcciones de memoria.

En el cual vamos a añadir la dirección de memoria del maná que hemos sacado de CE.

&H es para VB.NET la forma de declarar que el valor que usamos es hexadecimal.

El resto es simplemente la dirección de memoria: &H + 5C682C

Ahora tenemos que crear un Timer, que revise nuestro personaje constantemente.

Nos vamos al diseñador y podemos copiar nuestro TimerEat y editar la copia (Ctrl+C y Ctrl+V)

Este Timer a diferencia del otro, estará activado y funcionará con una frecuencia mucho más alta para detectar rápidamente cualquier cambio en nuestro personaje.

Antes de editar el código del Timer, copiaremos el cuadro de texto que tenemos, y editaremos la copia para que indique nuestro maná. Le pondremos el nombre txtMana y el texto MANA: 0

Y vamos a crear otro cuadro de texto para que podamos indicar al bot con cuanto maná lanzaremos el hechizo.

Y repetimos para un cuadro de texto que indique el hechizo que vamos a usar.

También vamos a añadir un botón para activar/pausar.

Buscamos en el Cuadro de herramientas “button” y le damos doble click para añadirlo al diseño.

Lo editamos con el nombre butMana y le ponemos el texto ON/OFF.

Resultado:

Como sabemos que nuestro bot va a usar el teclado y el ratón, tenemos que controlar si estamos usando el teclado y/o el ratón antes de realizar cualquier acción.

Para eso vamos a crear un nuevo módulo con el nombre Status.vb para almacenar ese estado.

Y le vamos a añadir el siguiente código:

Private Busy As Boolean = False

Private ManaTrain As Boolean = False

Public Property getBusy As Boolean

Get

Return Busy

End Get

Set(value As Boolean)

Busy = value

End Set

End Property

Public Property getManaTrain As Boolean

Get

Return ManaTrain

End Get

Set(value As Boolean)

ManaTrain = value

End Set

End Property

Ahora crearemos un módulo para el procedimiento de revisar el maná.

Lo llamaremos Mana.vb y añadiremos el siguiente código:

Public Sub CheckMana()

Dim _myBytes(3) As Byte

ReadProcessMemory(_targetProcessHandle, addr_Mana, _myBytes, 4, vbNull)

Dim Mana_Points = BitConverter.ToInt32(_myBytes, 0).ToString

Bot.txtMana.Text = "MANA: " + Mana_Points

If getBusy = False And getManaTrain = True Then

If Mana_Points > CInt(Bot.txtManaForSpell.Text) Then

Try

getBusy = True

AppActivate(_targetProcess.Id)

My.Computer.Keyboard.SendKeys(Bot.txtSpell.Text, True)

My.Computer.Keyboard.SendKeys("{ENTER}", True)

getBusy = False

Catch ex As Exception

getBusy = False

End Try

End If

End If

End Sub

Le daremos doble click al Timer desde el diseñador, y se generará su código.

En él escribiremos lo siguiente:

CheckMana()

Ahora nos falta el botón de activar y desactivar.

Desde el diseñador podemos darle doble click al botón y se generará su código.

Podemos escribir el siguiente código:

If getManaTrain = False Then getManaTrain = True Else getManaTrain = False

CREANDO EL AUTOEAT (MACRO PARA COMER AUTOMÁTICAMENTE)

Para el autoeat primero vamos a encontrar la dirección de memoria del lugar donde pondremos la comida, para antes de intentar comer, comprobar que tenemos comida.

Vamos a utilizar el espacio del inventario para las flechas:

Podemos suponer que si quitamos la comida del inventario, el valor será 0, porque no tendremos nada equipado. Pero vamos a comprobarlo.

Como no sabemos el valor del item de la comida ni del espacio del inventario, simplemente en “Scan Type” seleccionamos “Unknown initial value”

Con esto buscamos todos los valores y ya descartaremos después.

Para bajar coincidencias, nos quitamos del inventario la comida, seleccionamos en “Scan Type” la opción “Changed Value” y le damos a “Next Scan”

Ya hay mucha diferencia, pero no es suficiente… Así que vamos a repetir el proceso.

Nos equipamos la comida en el mismo lugar:

Y le damos otra vez a “Next Scan”

Ahora no movemos la comida, y vamos a probar descartando los valores que cambien.

Como la comida no la vamos a tocar, no va a cambiar su valor.

Podemos darle 20-30 clicks seguidos a “Next Scan”.

Cada vez que le demos reducirá las coincidencias.

Cuando no reduzcan prácticamente, volvemos a equipar la comida, y repetimos con “Scan Type” en “Changed Value”.

Ahora podemos movernos por el juego, realizar acciones menos tocar o mover la comida o usar el espacio del inventario que estamos analizando.

Con esto conseguimos que se muevan los valores de memoria menos el que buscamos.

Caminando un poco por el mapa, sin hacer nada más, y pulsando “Next Scan” con la opción de “Unchanged Value” he reducido las coincidencias a 19:

Ahora vamos a descartar, moviendo la comida y viendo los valores de CE.

Hay que tener en cuenta que cuando movemos la comida de un lugar a otro, cambian las direcciones de memoria del origen y del destino. Y también otras direcciones de memoria como el id del último objeto seleccionado, del último objeto arrastrado, etc.

Por lo que hay que tener cuidado con los pasos que hacemos en CE.

Moviendo el objeto por mi inventario y descartando coincidencias, con estos mismos métodos, he llegado a dos direcciones de memoria:

Y podemos imaginar que 2666 es el ID del objeto y 1 es la cantidad que tenemos del objeto.

Y si no tenemos comida, esto será lo que nuestro bot va a leer:

Ahora podemos añadir a nuestro código la dirección de memoria que nos interesa, que es la primera, la del ID del espacio del inventario.

Creamos un nuevo módulo con el nombre Food.vb

Añadimos el siguiente código:

Private Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Integer, ByVal dx As Integer, ByVal dy As Integer, ByVal cButtons As Integer, ByVal dwExtraInfo As Integer)

Private Function checkFood() As Integer

Dim _myBytes(3) As Byte

ReadProcessMemory(_targetProcessHandle, addr_ArrowID, _myBytes, 4, vbNull)

Dim foundID = BitConverter.ToInt32(_myBytes, 0).ToString

Return CInt(foundID)

End Function

Public Sub eatfood(posX, posY)

If getEatFood = True And checkFood() > 0 Then

If getBusy = False Then

getBusy = True

AppActivate(_targetProcess.Id)

Cursor.Position() = New Point(posX, posY)

System.Threading.Thread.Sleep(100)

mouse_event(&H8, 0, 0, 0, 0)

System.Threading.Thread.Sleep(100)

mouse_event(&H10, 0, 0, 0, 0)

System.Threading.Thread.Sleep(100)

getBusy = False

End If

End If

End Sub

Con este código podemos ver que si nuestra comida es mayor que 0, el bot moverá el cursor a unas coordenadas determinadas y hará click derecho.

Y ya podemos añadir en el módulo principal (el del icono de la ventana, en el Explorador de Soluciones) la órden de revisar la comida y comer si tenemos comida.

Private Declare Function GetCursorPos Lib "user32.dll" (ByRef lpPoint As POINT_API) As Boolean

Private Structure POINT_API

Public X As Integer

Public Y As Integer

End Structure

Private foodXY As POINT_API

Private Sub GetMouseXY(ByRef p As POINT_API)

GetCursorPos(p)

MessageBox.Show("OK!", "Position found")

End Sub

Ahora falta editar el botón para activar/desactivar que el bot coma.

Y también crear un botón para grabar la posición de la comida.

Vamos al diseñador y hacemos doble click en el botón que habíamos creado antes.

En el código que se nos ha generado, añadiremos lo siguiente:

If getEatFood = False Then getEatFood = True Else getEatFood = False
TimerEat.Enabled = True

Para grabar la posición de la comida, crearemos un botón.

Haremos doble click en el botón y añadiremos el siguiente código:

TimerFoodPos.Enabled = True

Y creamos un Timer para que 5 segundos después de darle al botón que hemos creado, el bot capture la posición de nuestro cursor.

Hay que ponerle 5 segundos de delay, desactivado, y nombre: “TimerFoodPos”.

Haremos doble click al Timer y añadiremos el siguiente código:

GetMouseXY(foodXY)

TimerFoodPos.Stop()

PANIC HOTKEY (CERRAR EL BOT CON LA TECLA INSERT)

Como retoque final de código, vamos a hacer que cuando se pulse la tecla “Insert” se cierre el bot. Y después de esto ya retocaremos el diseño del programa para compilar y acabar el tutorial.

Vamos a TimerLoop, y le damos doble click.

Saltaremos al código del Timer, y añadiremos la siguiente línea delante de CheckMana()

If CheckInsert = True Then Application.Exit()

Y añadiremos la función CheckInsert en el módulo Status.vb el código:

Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As IntPtr) As Short

'Check if insert hold

Public Function CheckInsert() As Boolean

If GetKeyState(Keys.Insert).ToString <> "-127" And GetKeyState(Keys.Insert).ToString <> "-128" Then

Return False

Else

Return True

End If

End Function

RESULTADO PÁGINAS:

Dejo unos links de pastebin donde se pueden ver y copiar todas las páginas del proyecto.

[PRINCIPAL] Bot.vb https://pastebin.com/yEvFAjY7

[COMIDA] Food.vb https://pastebin.com/f28vAFEn

[MANÁ] Mana.vb https://pastebin.com/DsFsH4X4

[DIRECCIONES DE MEMORIA] MemoryAddress.vb https://pastebin.com/7hT82zkt

[GESTIÓN DE PROCESOS] ProcessRoutines.vb https://pastebin.com/A9qL5D6Y

[ESTADO DEL BOT] Status.vb https://pastebin.com/WfSGrtJV

CAMBIANDO EL DISEÑO:

Vamos a hacer click derecho en el proyecto y seleccionamos propiedades:

Vamos a asegurarnos que esté marcado en Formulario de inicio, nuestro módulo principal.

En Icono vamos a cambiarlo por uno que nos guste.

Ahora vamos al diseñador y marcamos el fondo de nuestro programa, para seleccionar la ventana y no un componente de la ventana:

Cambiaremos el texto y el icono.

RESULTADO:

VÍDEO DE PRUEBA:

https://youtu.be/wkrZjEI42WI

 

You may also like

1 comment

Adrián Hernando February 25, 2019 - 9:36 pm

Hola! Muchas gracias por el comentario 🙂
Sí estoy disponible, siempre es un placer ayudar en lo que se pueda.
Te contesté hace unos días por el foro, estoy en plena migración y no tenía las alertas configuradas, supongo que tampoco te habrá llegado nada al correo por eso mismo.
Si quieres contactar directamente por correo kuhiscripts@gmail.com
Saludos!

Reply

Leave a Comment