Red de conocimiento informático - Consumibles informáticos - ¿Cómo permite el editor terrestre de Warcraft que la computadora cree unidades personalizadas?

¿Cómo permite el editor terrestre de Warcraft que la computadora cree unidades personalizadas?

Este artículo te ayudará a crear un mapa de IA de héroe contra héroe simple pero genial.

El sistema de inteligencia artificial que estás a punto de aprender no es perfecto. Lo que queremos crear es un sistema de inteligencia artificial que pueda atacar a otros héroes, elegir cosas por sí mismo y aprender y usar habilidades, pero aún no es tan bueno como los jugadores humanos.

Sin embargo, cuando aprendas los conceptos básicos, deberías poder mejorar por tu cuenta.

Requisitos previos:

Conceptos básicos de JASS: este artículo utiliza JASS como ejemplo, por lo que debes conocer JASS. Teóricamente, se puede hacer en T, pero no lo recomiendo, porque hacerlo en T puede causar pérdidas de memoria y una gran cantidad de código innecesario, y el sistema de caché de juegos y errores de valor de retorno de JASS no se puede usar en T. Si No está familiarizado con él, JASS, complemente sus conocimientos de JASS con anticipación. También debes saber qué es una línea de código. Si no lo sabe, agregue sus propios conocimientos.

Sistema basado en caché del juego y valor de retorno ERROR

Notas:

-Aunque el sistema de IA que queremos construir no puede alcanzar el nivel humano, sí lo hará. Siempre mejor que nada. Y creo que una vez que comprendas los conceptos básicos, podrás mejorar por tu cuenta.

-No tienes que hacer exactamente lo que digo; yo hago lo que pienso, pero si tu idea es mejor o te sientes más cómodo, por favor haz lo que piensas. No soy perfecto y este artículo no puede ser perfecto, pero espero que ayude.

-Puedes usar el sistema de IA en mi mapa de demostración sin hacerlo tú mismo (si lo haces, dímelo), pero te sugiero que lo escribas tú mismo, porque el mapa puede ser más complicado. , escriba uno usted mismo, los sistemas de IA pueden obtener más información.

Parte de inicialización:

Primero cree un activador en WE con la condición de activador "Jugador 1 - Jugador 1 (rojo) abandona el juego" y luego conviértalo a JASS. Necesitamos este disparador para monitorear cuándo un jugador abandona el juego para que podamos activar la IA para este jugador. Ahora solo monitorea la salida del jugador número 1, por lo que necesitamos usar un bucle en la imagen oficial para monitorear a los jugadores 0-11.

Esperamos que este sistema de IA pueda utilizar habilidades. Suena difícil, pero en realidad es muy sencillo. Sólo necesitamos dejar que los héroes aprendan las habilidades para que puedan usarlas ellos mismos.

Nota: La situación cuando un héroe controlado por computadora libera una habilidad personalizada es siempre la misma que cuando libera la habilidad básica de esta habilidad personalizada (la traducción aquí es un poco vaga, la habilidad básica del La habilidad personalizada se refiere a... Las habilidades básicas son las habilidades que vienen con el juego en sí, y las habilidades personalizadas se basan en ciertas habilidades básicas... Todos los que han hecho dibujos deberían saber esto, ¿verdad?). se basan en el silencio. Luego, el héroe controlado por computadora usará esta habilidad cuando se deba usar el silencio en el mapa de batalla. Nunca crees una habilidad en un "canal", porque la computadora nunca la usará, e incluso cambiar el OrderString de la habilidad es inútil.

Para poder saber qué habilidades tiene cada héroe, creamos un caché del juego para guardar.

En el mapa de demostración, mi activador crea un caché del juego en la parte de inicialización del mapa, que se guarda en la variable global udg_GameCache. Tenga en cuenta que el caché debe inicializarse antes de que podamos usarlo, así que lo creé cuando se inicializó el mapa.

En mi mapa, escribí una función SetupSkills. En la función InitTrig de este disparador AI, uso la función de biblioteca ExecuteFunc para iniciar otro hilo para ejecutar esta función. Esto es para evitar que el mapa tarde demasiado en inicializarse.

jass: copiar código

Mi función SetupSkills es la siguiente:

La función SetupSkills no toma ningún contenido y no devuelve nada

Local String h //Crea una variable de cadena local

//Paladín//Aquí inicializaremos las habilidades del Paladín, repetiremos esta operación para todos los demás héroes

set h = UnitId2String('Hpal') //Almacena el valor de retorno de UnitId2String('Hpal ') localmente

Llamar a StoreInteger(udg_GameCache, h, "BaseSkill1", 'AHhb') //Una de sus habilidades básicas Es la Luz Sagrada, almacenada como "BaseSkill1"

Llamar a StoreInteger(udg_GameCache,h,"BaseSkill2",'AHds') //Guardar el Escudo Sagrado como "BaseSkill2"

Llamar StoreInteger(udg_GameCache,h,"BaseSkill3",'AHad') //Guarda el aura de piedad como "BaseSkill3"

Llama a StoreInteger(udg_GameCache,h,"UltimateSkill",'AHre') //Revivirá Almacenar como su "UltimateSkill"

… //Repetir para cada héroe.

Función final

Luego viene la parte InitTrig de mi activador AI:

La función InitTrig_AI no toma nada ni devuelve nada

Entero local i = 0

establecer gg_trg_AI = CreateTrigger()

Timbre

salir cuando i gt11

Llamar al disparadoregisterplayereventlate(gg _ trg _ AI, Player(i))

Establecer i = i 1

Finalizar bucle

Llamar a TriggerAddAction(gg_trg_AI, función PlayerLeaves)

Llamar a ExecuteFunc ("SetupSkills ")

Finalizar la función

Habilitar el sistema de inteligencia artificial del héroe

Para controlar la inteligencia artificial, utilizamos un temporizador. Escribí una función StartAI para obtener el tipo de unidad: héroe (verifique esta función en la imagen de demostración). Esta función simplemente crea un cronómetro, lo "vincula" al héroe e inicia el cronómetro.

Esta es la función AILoop vacía y la función StartAI en el diagrama de demostración (aquí solo se proporciona un marco, mostraremos algunas funciones de acción más adelante, pero al menos debe escribir la función y la función final para garantizar que no reportar error):

jass: Copiar código

La función AILoop no toma ningún contenido y no devuelve ningún contenido

Finalizar función

La función StartAI toma héroes de la unidad No devuelve nada

Temporizador local m = CreateTimer()

Llama a AttachObject(m, "hero", hero)

Llama a TimerStart(m, 0, false, function AILoop)

set m = null

Finalizar función

Tenga en cuenta que mi función StartAI establece el parámetro periódico a false (lo haremos (lo discutiremos más adelante) para que el temporizador se ejecute solo una vez.

Ahora puedes llamar a esta función en tu sistema de selección de héroe cuando un jugador controlado por computadora selecciona un héroe, y ejecutarla cuando el jugador abandona el juego. Comprueba si el jugador tiene un héroe. Si es así, llama a esta función para abrir el sistema de IA del héroe. Por ejemplo:

jass: copiar código

La función PlayerLeaves no toma ningún contenido y no devuelve ningún contenido

Reproductor local p = GetTriggerPlayer()

Llame a DisplayTextToForce(bj _ FORCE _ ALL _ PLAYERS, GetPlayerName(p) "Dejó el juego.")

if udg_Hero[GetPlayerId(p)]! = luego nulo

Llamar a StartAI(udg _ Hero[GetPlayerId(p)])

endif

Establecer p = nulo

Fin Función

Nota: Esta función permitirá que el sistema de IA controle al héroe del jugador que sale, pero esto no es necesario y también puedes hacer otras cosas.

¿Qué hace esta IA?

Cuando el cronómetro expire, queremos que haga lo siguiente:

Si el héroe muere, esperar a que resucite.

●Si el héroe está a punto de morir, ordénale que se mueva a la Fuente de la Vida en el centro del mapa.

●Si el héroe está en buenas condiciones, detecta si hay enemigos cerca. Si es así, ordena al héroe que lo ataque. De lo contrario, comprueba si hay un objeto cerca y, de ser así, envía una orden inteligente para que el héroe lo recoja. Luego ordena al héroe que patrulle hasta cualquier coordenada del mapa.

●Si el héroe está vivo y tiene puntos de habilidad no utilizados, aprende una habilidad.

Comenzamos con la declaración de variables. Observe la variable real "e" en mi función, define el tiempo transcurrido antes de que el cronómetro comience nuevamente, por lo que podemos esperar un corto tiempo cuando el héroe muere y un largo tiempo cuando ataca. El valor inicial de esta variable es 5.

jass: Copiar código

Declaración de variables locales:

La función AILoop no toma ningún contenido y no devuelve nada

Caracteres locales Cadena a = GetAttachmentTable(GetExpiredTimer())

Unidad local h = GetTableUnit(a, "hero")

Rect local i

Ubicación local r

p>

Número real local x = GetUnitX(h)

Número real local y = GetUnitY(h)

Grupo local g

Boolexpr local b

Boolexpr local be

Unidad local f

Cadena local o = orderid 2 string(GetUnitCurrentOrder(h))

Real local l = GetUnitState(h, unit_state_life)

Número real local e = 5

<…

Comenzamos detectando si el héroe está muerto. Si muere, establezca "e" en 1,5 (porque esperar 5 segundos después de resucitar es demasiado tiempo y no queremos hacer eso).

Cuando la salud del héroe "L" es 0, establece "E" en 1,5 para que el temporizador detecte si el héroe resucita con más frecuencia.

Si i lt entonces = 0

El conjunto e = 1,5

endif

…< / p>

Luego compruebo si la vida útil del héroe es inferior a la vida útil máxima de 20. Si es así, le ordeno al héroe que se mueva a la Fuente de la Vida y pongo "e" en 3.

Cuando la salud del héroe es inferior a 20 de la salud máxima, ordena al héroe que se mueva a la ubicación de la fuente de la vida.

Si ltGetUnitState(h, vida útil máxima del estado de la unidad)/5 entonces

llamo a IssuePointOrder(h, " move ", GetUnitX(gg _ unit _ nfoh _ 0001), GetUnitY(gg _ unit _ nfoh _ 0001))

Set e = 3

Si el héroe está en buenas condiciones , verifique si tiene el mando normal (lo que le impide interrumpir las habilidades de encantamiento). Si es un comando estándar, comprobaremos si hay un enemigo dentro de un radio de 500. Si hay enemigos, simplemente da el comando de ataque (no cambies el valor de "e", 5 segundos está bien para esta situación).

jass: Copiar código

La función AIFilterEnemyConditions no acepta ningún contenido y devuelve un valor booleano

return GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE ) gt; 0 y isplayerename(GetOwningPlayer(GetFilterUnit()), GetOwningPlayer(GetAttachedUnit(GetExpiredTimer(), " hero)))

Función final

Otros

Si ((o == "inteligente ") o (o == "atacar") o (o == "patrullar ") o (o == "mover ") o (o = = "detener ") o (o == "hold ") o (o == null)) entonces

establecer g = CreateGroup()

establecer b = condición (función AIFilterEnemyConditions )

p>

Llamar a GroupEnumUnitsInRange(g, x, y, 500, b)

Establecer f = FirstOfGroup(g)

Si f == nulo, luego

Otro

Llamar a IssueTargetOrder(h, "ataque", f)

endif

Llamar a DestroyGroup(g)

Llamar a DestroyBoolExpr(b)

endif

<…

Si no hay ningún enemigo, verifica nuevamente si hay Si lo encuentra, verifique si lo es. Artículos mejorados. Si no, verifique si hay un espacio vacío en el inventario del héroe y, de ser así, ordene al héroe que lo recoja.

jass: copiar código

La función AISetItem no acepta ningún contenido y no devuelve ningún contenido

set bj _ lastRemovedItem = GetEnumItem()

Finalizar función

La función AIItemFilter no acepta ningún contenido y devuelve un valor booleano

Devuelve IsItemVisible(GetFilterItem()) y GetWidgetLife(GetFilterItem()) gt;

Finalizar función

La función AIHasEmptyInventorySlot acepta la unidad u y devuelve un valor booleano

Devuelve UnitItemInSlot(u, 0) == null o UnitItemInSlot(u, 1) == nulo o UnitItemInSlot(u, 2) == nulo o UnitItemInSlot(u, 3) == nulo o UnitItemInSlot(u, 4) == nulo o UnitItemInSlot(u, 5) == nulo

Función final

>…

Si f == null, entonces

Establezca i = Rect(x-800, y-800, x 800, y 800)

set be = Condición(función AIItemFilter)

set bj_lastRemovedItem=null

Llamar a EnumItemsInRect(i, be, función AISetItem)

si bj_lastRemovedItem! = null y (getitem TYPE(bj_lastRemovedItem)== ITEM_TYPE_power up o AIHasEmptyInventorySlot(h)) y luego

Llame a IssueTargetOrder(h, "smart", bj_lastRemovedItem)

Otro

endif

Llamar a RemoveRect(i)

Llamar a DestroyBoolExpr(be)

Si no hay espacio en el inventario, o no se encuentra el objeto, ordena al héroe que busque un nuevo objetivo en una ubicación aleatoria.

Otros

set r = GetRandomLocInRect(bj _ mapInitialPlayableArea)

Llamar a issuespintorderloc(h, "patrol", r)

Llamar a eliminar posición(r)

Lo que necesitamos detectar ahora es si el héroe tiene puntos de habilidad no utilizados (esta función se combina con ataque/ recoger artículos/avanzar a ubicaciones aleatorias y otros módulos por separado).

Si el héroe tiene puntos de habilidad no utilizados, llama a una función para permitir que el héroe aprenda la habilidad. En mi mapa de demostración, uso una función para guardar las habilidades que aprenderá el héroe, usando el siguiente patrón: