Guía básica de como programar en Lua

Paladin

Admin
VIP
Capataz
Desde
Oct 1, 2019
Mensajes
46
Puntos de Honor
2
Lua es un lenguaje de programación ligero diseñado como un lenguaje de scripting con semántica extensible como objetivo principal. El nombre proviene de la palabra portuguesa Lua que significa "Luna". Lua tiene una interfaz de programación de aplicaciones C (API) relativamente simple en comparación con otros lenguajes de scripting.
Entrando en la programación

Esta guía le enseñará cómo hacer que la Inteligencia Artificial (AI) sea simple para usar con los emuladores ArcEmu y Sandshroud.
Hay muchas opciones para qué tipo de script puede realizar un usuario según los criterios establecidos por el usuario u otra persona que solicite el script, y generalmente es posible llegar a una solución para un problema determinado de más de una manera. Cuanta menos memoria use una secuencia de comandos, mejor será, ya que eso reducirá los recursos del sistema y del emulador. Un script podría verse

Codigo:
SMAGE = {}
UARC = {}

function SMAGE.OnSpawn(pUnit,event)
    pUnit:CastSpell(54467) -- Bone Armor
    pUnit:CastSpell(48169) -- Shadow Protection Rank 5
    pUnit:CastSpell(48943) -- Shadow Resistance Aura Rank 5
    pUnit:CastSpell(15473) -- Shadowform
end

RegisterUnitEvent(7,18,"SMAGE.OnSpawn")

function SMAGE.ShadowVolley(pUnit,event)
        pUnit:InterruptSpell()
Rplr = pUnit:GetRandomPlayer(0)
    if (Rplr ~= nil) then
        VolleyTalk = math.random(1,3)
    if (VolleyTalk == 1) then
        pUnit:SendChatMessage(14,0,"Feel my Volley of furious Shadow Power!")
            pUnit:CastSpellOnTarget(38533,Rplr)
    elseif (VolleyTalk == 2) then
        pUnit:SendChatMessage(14,0,Rplr:GetName().."! You and your friends will die!")
            pUnit:CastSpellOnTarget(38533,Rplr)
    elseif (VolleyTalk == 3) then
        pUnit:SendChatMessage(14,0,"Avoid me all you want. You can't dodge my magic!")
            pUnit:CastSpellOnTarget(38533,Rplr)
    end
end
end

function SMAGE.Blast(pUnit,event)
        pUnit:InterruptSpell()
Rplr = pUnit:GetRandomPlayer(0)
    if (Rplr ~= nil) then
            pUnit:FullCastSpellOnTarget(41078,Rplr)
    end
end

function SMAGE.SFlame(pUnit,event)
    pUnit:InterruptSpell()
Nplr = pUnit:GetClosestPlayer()
    if (Nplr ~= nil) then
    pUnit:FullCastSpellOnTarget(61290,Nplr)
FlameTalk = math.random(1,20)
    if (FlameTalk == 4) then
        pUnit:SendChatMessage(14,0,"Get off my back!")
    elseif (FlameTalk == 9) then
        pUnit:SendChatMessage(14,0,"Hey "..Nplr:GetName().."! You are gonna burn!")
    elseif (FlameTalk == 16) then
        pUnit:SendChatMessage(14,0,"I am gonna blow you brats to pieces!")
    end
end
end

function SMAGE.OnCombat(pUnit,event)
        pUnit:RegisterEvent("SMAGE.Blast",2100,0)
        pUnit:RegisterEvent("SMAGE.ShadowVolley", 7500, 0)
        pUnit:RegisterEvent("SMAGE.SFlame",17500,0)
        pUnit:RegisterEvent("SMAGE.SpawnArcane",20500,0)
    OnCombatTalk = math.random(1,3)
    if (OnCombatTalk == 1) then
        pUnit:SendChatMessage(14,0,"Who dares to attack me, TENDRIS?!")
    elseif (OnCombatTalk == 2) then
        pUnit:SendChatMessage(14,0,"You shall die fast by my cold dead hands..")
    elseif (OnCombatTalk == 3) then
        pUnit:SendChatMessage(14,0,"You picked the wrong undead to disturb!")
    end
end

function SMAGE.SpawnArcane(pUnit,event)
local x = pUnit:GetX();
local y = pUnit:GetY();
local z = pUnit:GetZ();
local o = pUnit:GetO();

    SpawnChoice = math.random(1,3)
    if (SpawnChoice == 1) then
        pUnit:SendChatMessage(14,0,"I Spawn a skeleton from the underworld!")
            pUnit:SpawnCreature(8,x+10,y,z+1,o,14,180000)
elseif (SpawnChoice == 2) then
        pUnit:SendChatMessaget(14,0,"I Spawn two skeletons from the underworld!")
            pUnit:SpawnCreature(8,x+10,y,z+1,o,14,180000)
            pUnit:SpawnCreature(8,x-10,y,z,o,14,180000)
elseif (SpawnChoice == 3) then
        pUnit:SendChatMessage(14,0,"I Spawn three skeletons from the underworld!")
            pUnit:SpawnCreature(8,x+10,y,z+1,o,14,180000)
            pUnit:SpawnCreature(8,x-10,y,z+1,o,14,180000)
            pUnit:SpawnCreature(8,x,y+10,z+1,o,14,180000)
    end
end

function SMAGE.OnLeave(pUnit,event)
    pUnit:RemoveAllAuras()
    pUnit:RemoveEvents()
    pUnit:ReturnToSpawnPoint()
    pUnit:SendChatMessage(14,0,"I suppose you weren't a threat after all. I squeezed you like bugs.")
end

function SMAGE.OnKill(pUnit,event,mTarget)
    pUnit:SendChatMessage(12,0,"Go to sleep.")
end

function SMAGE.OnDied(pUnit,event,mTarget)
    pUnit:SendChatMessage(14, 0,mTarget:Getname().." got the killing blow!")
    pUnit:RemoveAllAuras()
    pUnit:RemoveEvents()
end

RegisterUnitEvent(7,1,"SMAGE.OnCombat")
RegisterUnitEvent(7,2,"SMAGE.OnLeave")
RegisterUnitEvent(7,3,"SMAGE.OnKill")
RegisterUnitEvent(7,4,"SMAGE.OnDied")
Este no es el guión completo, sino la mitad. Es una IA para una criatura llamada Shadow Mage. Está un poco avanzado y va más allá del contenido que cubre esta guía. Pero si un usuario toma este script y lo coloca en un archivo de bloc de notas con la extensión de archivo .lua y lo coloca en la carpeta de scripts del emulador, se ejecutará correctamente.
Básicamente, lo que sucede aquí son muchas llamadas de diferentes funciones, comprobación de valores, declaraciones y argumentos, así como el envío de toda la información al Lua Engine dentro del emulador, que luego ejecutará las acciones especificadas en el script.

Aprendiendo lo Básico

Como cualquier otro lenguaje de programación, esta guía hace un poco de "¡Hola mundo!" script para ver una sintaxis muy básica.

Codigo:
io.write("Hello world!")
Si esto se ejecutó dentro de un World of Warcraft Emulator, ahora no pasaría nada, sin embargo, sigue siendo un script válido. ¡Simplemente usa la función de una biblioteca para escribir Hello World!

Al realizar este tipo de secuencia de comandos en emulación, la acción debe estar vinculada a algo (como una criatura) antes de que se ejecute o antes de que la acción se pueda ver en cualquier lugar de la pantalla.

Requisitos:

Para esta guía, se recomienda obtener los siguientes programas:
  • Notepad ++
Es una versión de código abierto del Bloc de notas estándar que se encuentra en Windows, pero muy mejorado y muy útil para escribir código en varios idiomas. También se recomienda para los usuarios de Mac y Linux obtener este programa y usar un emulador de Windows:
  • Linux: Wine
  • Mac: Boot Camp
Esta guía usará Notepad ++ para su propósito, sin embargo, cualquier otro editor estándar de Notepad lo hará. Notepad ++ es útil porque es posible hacer scripts con pestañas. Significa que es posible mirar múltiples scripts a la vez que resulta muy útil. Solo asegúrese de guardar el archivo con la extensión lua ya que de lo contrario no funcionará con el emulador elegido.

Esta guía está hecha para el que no tiene experiencia previa en programación.

Funciones
Una función es principalmente la secuencia de comandos que se puede llamar en cualquier lugar dentro de una secuencia de comandos. La función tiene un nombre, uno o más argumentos, algunas acciones para ejecutar en función de las condiciones y luego algo que indica que finaliza. Aquí hay un diseño básico de una función:

Codigo:
function name(arg)
     conditions,actions
end

function name
Este es el nombre de la función. Puede tener números, puede tener botones de ALTURA, guiones bajos pero no espacios, puntos, comas, dos puntos, u otros caracteres especiales (@, £, $ ...) ya que pueden estar reservados para ciertas acciones dentro del lenguaje. Los nombres válidos serían:

Codigo:
function HeyThere

function heythere

function Hey_There

function hey_there

function HeY_tHeRe

function heythere
Etcétera, pero ninguna de estas funciones es la misma. El lenguaje es capaz de distinguir mayúsculas de letras no mayúsculas. Las funciones también pueden contener números en sus nombres de funciones. Lo que debe notarse es que la función siempre se deletrea con una f no capital. Tiene que estar escrito con todas las letras que no sean mayúsculas: función. De lo contrario, es una sintaxis inválida y el lenguaje no lo leerá como una función, sino como un error.

Codigo:
(arg)
Un argumento generalmente es un valor u otra cosa que la función necesita pasar para que pueda usarse en la función. A veces, esta es una necesidad si se definen ciertos parámetros para un determinado tipo de función para que funcione. Un ejemplo podría ser:

Codigo:
function Killed(pUnit,event,pPlayer)
If pUnit and pPlayer wasn't included in the argument list then they cannot be used in the function. It will return an error saying that pUnit and pPlayer are invalid arguments as they were never passed to the function. When making arguments there have to be a comma for every new argument that needs to be passed. It is allowed to make a space between the functions name and it is also allowed to make spaces in between the commas within the ().
conditions,actions
Esta es la carne de una función. Ahí es donde sucede toda la magia. Es posible hacer funciones largas y avanzadas que tienen muchas condiciones diferentes y si son verdaderas, falsas o si se devuelve un valor específico, entonces realice una acción. De lo contrario, si no, haz otra cosa o no hagas nada en absoluto. Una secuencia de comandos no puede comprender cosas inesperadas, por lo que el programador tiene que pensar en el futuro y especificar qué debería hacer la secuencia de comandos, si algo sucede. Por supuesto, es imposible pensar en todas y cada una de las posibilidades, pero es posible encontrar muchas de las acciones comunes y menos comunes que se pueden tomar para cualquier cosa que afecte el script. Se llama hacer la escritura idiota a prueba. Hacer que el guión realmente haga algo se tratará un poco más abajo en esta guía.

Codigo:
end
Esto simplemente le dice a la función "End here". Cada función necesita un final para cada condición agregada al script así como también para que la función se cierre y termine. No hay nada más para eso.

Hacer que una criatura diga Hola

Este será el Hello World! guión escrito para la emulación de World of Warcraft:

Codigo:
function Hello(pUnit)
     pUnit:SendChatMessage(14,0,"Hello there!)
end
Esta es una función válida y será algo que se puede llamar en cualquier parte del script. Pero, ¿qué sucede en este guión?

Codigo:
function Hello
Este es el nombre de nuestra función.

Codigo:
(pUnit)
Este es nuestro argumento llamado pUnit. Este es un argumento estándar utilizado para especificar que se trata de una criatura que hace lo que el usuario le dice que haga.

Codigo:
pUnit:SendChatMessage(14,0"Hellow there!")
Aquí viene la magia. El script asigna la acción de enviar un mensaje de chat a la unidad. Es por eso que está escrito como pUnit: SendChatMessage(). El uso de un colon SendChatMessage() es una función que toma tres argumentos:

Codigo:
(type,lang,message)
Type: Esto especifica qué tipo de mensaje está enviando. En este caso, grita. Una lista de diferentes tipos se puede encontrar al final de esta guía.
Lang: Como hay una buena cantidad de idiomas en World of Warcraft, esta función también necesita tener el idioma especificado. En este caso, se usa 0 ya que eso significa Universal. Cualquiera puede entender este mensaje. Una lista de diferentes idiomas se puede encontrar en la parte inferior de esta guía.
Menssage: Aquí es donde va el mensaje de esta función. Tiene que estar incluido entre comillas para mostrar dónde comienza y termina el mensaje.
Estos argumentos deben estar separados por comas.

Codigo:
end
Y aquí terminamos la función para que sepa dónde está su final.
Ahora esta función necesita asignarse a algún tipo de evento. Si no es así, significa que es solo una función almacenada que nunca se usa.

Codigo:
function Hello(pUnit)
     pUnit:SendChatMessage(14,0,"Hello there!)
end

RegisterUnitEvent(EntryID,1,"Hello")
El nuevo elemento es una función de registro. Toma tres argumentos:
(EntryID,Event,Function)
EntryID: este es el EntryID de tu Criatura al que se asignará este script.
Event: qué evento activará esta función. En este caso, es cuando la Criatura entra en combate. Una lista de diferentes eventos se puede encontrar al final de esta guía.
Function: Nombre de la función (en este caso Hello) encerrada entre comillas.

Entonces, cada vez que la criatura con el EntryID especificado se enfrente a la batalla, gritará "Hello there!".
Hay muchas otras funciones que el usuario puede llamar y asignar y muchas funciones de registro diferentes también. Ni siquiera tiene que ser una criatura que la función esté asignada también. Podría ser algo completamente diferente como un objeto de juego o incluso elementos. También podría ser el jugador en sí.
Esta introducción al lenguaje termina aquí.
¡Felicidades por la primera IA básica!

Recursos

Lista de tipos para SendChatMessage():

Codigo:
CHAT_MSG_ADDON                           = -1,
CHAT_MSG_SYSTEM                          =  0,
CHAT_MSG_SAY                             =  1,
CHAT_MSG_PARTY                           =  2,
CHAT_MSG_RAID                            =  3,
CHAT_MSG_GUILD                           =  4,
CHAT_MSG_OFFICER                         =  5,
CHAT_MSG_YELL                            =  6,
CHAT_MSG_WHISPER                         =  7,
CHAT_MSG_WHISPER_MOB                     =  8,
CHAT_MSG_WHISPER_INFORM                  =  9,
CHAT_MSG_EMOTE                           = 10,
CHAT_MSG_TEXT_EMOTE                      = 11,
CHAT_MSG_MONSTER_SAY                     = 12,
CHAT_MSG_MONSTER_PARTY                   = 13,
CHAT_MSG_MONSTER_YELL                    = 14,
CHAT_MSG_MONSTER_WHISPER                 = 15,
CHAT_MSG_MONSTER_EMOTE                   = 16,
CHAT_MSG_CHANNEL                         = 17,
CHAT_MSG_CHANNEL_JOIN                    = 18,
CHAT_MSG_CHANNEL_LEAVE                   = 19,
CHAT_MSG_CHANNEL_LIST                    = 20,
CHAT_MSG_CHANNEL_NOTICE                  = 21,
CHAT_MSG_CHANNEL_NOTICE_USER             = 22,
CHAT_MSG_AFK                             = 23,
CHAT_MSG_DND                             = 24,
CHAT_MSG_IGNORED                         = 25,
CHAT_MSG_SKILL                           = 26,
CHAT_MSG_LOOT                            = 27,
CHAT_MSG_MONEY                           = 28,
CHAT_MSG_OPENING                         = 29,
CHAT_MSG_TRADESKILLS                     = 30,
CHAT_MSG_PET_INFO                        = 31,
CHAT_MSG_COMBAT_MISC_INFO                = 32, 
CHAT_MSG_COMBAT_XP_GAIN                  = 33,
CHAT_MSG_COMBAT_HONOR_GAIN               = 34,
CHAT_MSG_COMBAT_FACTION_CHANGE           = 35,
CHAT_MSG_BG_EVENT_NEUTRAL                = 36,
CHAT_MSG_BG_EVENT_ALLIANCE               = 37,
CHAT_MSG_BG_EVENT_HORDE                  = 38,
CHAT_MSG_RAID_LEADER                     = 39,
CHAT_MSG_RAID_WARNING                    = 40,
CHAT_MSG_RAID_WARNING_WIDESCREEN         = 41,
CHAT_MSG_RAID_BOSS_EMOTE                 = 42,
CHAT_MSG_FILTERED                        = 43,
CHAT_MSG_BATTLEGROUND                    = 44,
CHAT_MSG_BATTLEGROUND_LEADER             = 45,
CHAT_MSG_RESTRICTED                      = 46,
CHAT_MSG_ACHIEVEMENT                     = 47,
CHAT_MSG_GUILD_ACHIEVEMENT               = 48,
Lista de idiomas para SendChatMessage():

Codigo:
 0 = UNIVERSAL
1 = ORCISH
2 = DARNASSIAN
3 = TAURAHE
6 = DWARVISH
7 = COMMON
8 = DEMONIC
9 = TITAN
10 = THELASSIAN
11 = DRACONIC
12 = KALIMAG
13 = GNOMISH
14 = TROLL
33 = GUTTERSPEAK
35 = DRAENEI
Lista de eventos para RegisterUnitEvent():

Codigo:
CREATURE_EVENT_ON_ENTER_COMBAT       = 1,
CREATURE_EVENT_ON_LEAVE_COMBAT       = 2,
CREATURE_EVENT_ON_TARGET_DIED        = 3,
CREATURE_EVENT_ON_DIED               = 4,
CREATURE_EVENT_ON_TARGET_PARRIED     = 5,
CREATURE_EVENT_ON_TARGET_DODGED      = 6,
CREATURE_EVENT_ON_TARGET_BLOCKED     = 7,
CREATURE_EVENT_ON_TARGET_CRIT_HIT    = 8,
CREATURE_EVENT_ON_PARRY              = 9,
CREATURE_EVENT_ON_DODGED             = 10,
CREATURE_EVENT_ON_BLOCKED            = 11,
CREATURE_EVENT_ON_CRIT_HIT           = 12,
CREATURE_EVENT_ON_HIT                = 13,
CREATURE_EVENT_ON_ASSIST_TARGET_DIED = 14,
CREATURE_EVENT_ON_FEAR               = 15,
CREATURE_EVENT_ON_FLEE               = 16,
CREATURE_EVENT_ON_CALL_FOR_HELP      = 17,
CREATURE_EVENT_ON_LOAD               = 18,
CREATURE_EVENT_ON_REACH_WP           = 19,
CREATURE_EVENT_ON_LOOT_TAKEN         = 20,
CREATURE_EVENT_ON_AIUPDATE           = 21,
CREATURE_EVENT_ON_EMOTE              = 22,
 
 
Top