[Tutorial] Lua (Big explained) for Emulators!

This is a discussion on [Tutorial] Lua (Big explained) for Emulators! within the WoW Private Servers board part of the WoW forum category; Hello One of my friends had writted a very cool Lua guide for Emulators. So here you go: Greetings everyone ...

Results 1 to 3 of 3
  1. #1
    ahlmo is offline Member
    Array
    Join Date
    Jun 2009
    Posts
    44
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Rep Power
    11
    Reputation
    8

    [Tutorial] Lua (Big explained) for Emulators!

    Hello One of my friends had writted a very cool Lua guide for Emulators.
    So here you go:

    Greetings everyone and welcome to Sjoerd's basic Lua Scripting tutorial for World of Warcraft. With this tutorial I will clearly and step for step learn you about the basics of a boss encounter. Make sure you are reading this tutorial step by step if you are a beginner

    Introducion

    1. Lua
    2. Events
    3. Spells
    4. Phases
    5. Extra additions


    LUA

    Lua is a great program for much games like World of Warcraft. The main thing to learn Lua is because it's one of the most used languages and one of the easiest to understand in games. With Lua you will get a great rank in developing at servers with a high community.

    EVENTS

    The Events are the ones who start a script. The most used Events are OnCombat, OnLeaveCombat, OnKilledTarget and OnDeath. I will clearly explain those basic Events to you and how to use them.

    2.1. OnCombat
    2.2. OnLeaveCombat
    2.3. OnKilledTarget
    2.4. OnDeath

    OnCombat

    OnCombat means when the player enters the in-combat range of the boss. When the player enters combat with the boss, then the script basicly starts. Here is an example how an OnCombat phase should look like with no events.



    Code:
    function Boss_OnCombat(pUnit, Event)end
    Let me explain these things to you:

    function, the functions tell the script what to do.

    Boss, this is the name of my boss, I have called him Boss because there isn't a better name for this tutorial. You can replace this name with your own name, Boss doesn't have anything to deal with what kind of boss it is.

    OnCombat, this is the name of the function, at this point, the funcion is the OnCombat Event.

    (pUnit, Event), I haven't put these things seperate because they are a must at every function. pUnit means the NPC, this doesn't mean you have to change pUnit into the name of your NPC, another thing about pUnit is that it doesn't have to be pUnit everytime. You can change pUnit in another name too. The only rule about this is that you can't have two names like pUnit and Unit, remind yourself on that. And Event is the Event, meaning with 'Event is the Event' is because the Event is OnCombat.

    end, this means the end of the function. You only have to put one end because it ends on one function, will explain later about this at Phases.

    Now we all had these explainations, we are going to make some changes in the OnCombat phase.

    With these changes I mean that we are going to let the NPC talk when a player enters in-combat range, watch what I'm going to change.



    Code:
    function Boss_OnCombat(pUnit, Event)
    pUnit:SendChatMessage(14, 0, "Welcome to my lair!")
    end
    This will let the NPC yell "Welcome to my lair!" Let me explain this about how I did this.

    pUnit, here is pUnit again, pUnit is always used for things like this, and to cast spells, but I'm coming back on that later.

    SendChatMessage, this will let the NPC send a chat message which the players can read

    (14, 0, "Welcome to my lair!") I haven't put these things separate because they are all together. The number 14 means that he yells the chat message, the number 0 means that it is universial so that everyone can understand it. The text "Welcome to my lair!" is the text the NPC yells in universial, make sure you are putting it between "".

    I'm going to show you some other languages and about in what sort of type he can say it:

    How he can say it:



    Code:
    12 –- Means that the NPC says something13 –- Means that the NPC whispers something14 -- Means that the NPC yells something
    In what sort of language he can say it:



    Code:
    0 -- Universal, means everyone can understand it1 -- Orcish2 -- Darnassian3 -- Tauron6 -- Dwarfs7 -- Common8 -- Demonic9 -- Titan13 -- Gnomish14 -- Trolls33 -- Gutterspeak35 -- Draenei
    Ok, this were the basics of an OnCombat Event, lets go to the other Events.

    OnLeaveCombat

    This is the OnLeaveCombat Event. The OnLeaveCombat Event is when the boss leaves combat with his opponents. You can have text with this too, but there is something else added to it also.



    Code:
    function Boss_OnLeaveCombat(pUnit, Event)pUnit:SendChatMessage(14, 0, "You are to scared for my powers?!")pUnit:RemoveEvents()
    end
    As you can see it's the same as OnCombat. But now I've added pUnit:RemoveEvents() add it. The reason why I'm doing this is because when you leave combat with him. It will remove all the current events, like casting spells and other things.

    Now we are moving on the the next event.

    OnKilledTarget

    The OnKilledTarget event is not hard at all. You don't need to have pUnit:RemoveEvents() at this event. The reason why? I'll explain, when the boss kills an enemy, the script continues. If you put RemoveEvents() at is, he will start from the beginning. We don't want that ofcourse.



    Code:
     
    function Boss_OnKilledTarget(pUnit, Event)
    end
    Ofcourse, you can add more things to it. Like when he kills an enemy, he gets stronger or something. For that, we will use pUnit:CastSpell(). CastSpell() means that he casts a spell in Area of Effect, or on himself. You can look the spell ID's at Wowhead: Dataz! We need more dataz!., or www.thotbot.com. How to get those ID's? I'll explain. I want that my boss gets stronger everytime. I'll try to find the spell "Growth", I'm typing Growth at the search button of wowhead. Going to Uncategorized spells and I click on the spell I wanted. Now I'm at the page: Growth - Spell - World of Warcraft. As you can see the spell ID is on the end. This is how you find spells. Now, back on pUnit:CastSpell(). Now I've got the spellID. I need to copy and paste it into the brackets of CastSpell(), means the (). Lets add the pUnit:CastSpell() now to the event.



    Code:
     
    function Boss_OnKilledTarget(pUnit, Event)
    pUnit:CastSpell(36300)
    end
    You can have text at it too ofcourse. If he gets stronger everytime, lets think of some text who fits in it.



    Code:
     
    function Boss_OnKilledTarget(pUnit, Event)
    pUnit:SendChatMessage(14, 0, "Your worthless blood feeds me!")pUnit:CastSpell(36300)
    end
    So, this was the OnKilledTarget event, not so hard is it?

    OnDeath

    The OnDeath event is just as easy as the others. You need to have pUnit:RemoveEvents() too and ofcourse, chatmessages are always welcome.



    Code:
     
    function Boss_OnDeath(pUnit, Event)
    pUnit:SendChatMessage(14, 0, "That's impossible! Nooo!")pUnit:RemoveEvents()
    end
    I don't have much to explain about only the main thing here, is the put the chatmessage above pUnit:RemoveEvents(). Why? Because otherwise it removes the events before he sends the chat message and it won't say anything then.

    Ok! This were the explainations about all the basic Events in a boss encounter. How to put them in a script? I'll show you!


    Code:
     
    function Boss_OnCombat(pUnit, Event)
    pUnit:SendChatMessage(14, 0, "Welcome to my lair!")
    end
     
    function Boss_OnLeaveCombat(pUnit, Event)
    pUnit:SendChatMessage(14, 0, "You are to scared for my powers?!")pUnit:RemoveEvents()
    end
     
    function Boss_OnKilledTarget(pUnit, Event)
    pUnit:SendChatMessage(14, 0, "Your worthless blood feeds me!")pUnit:CastSpell(36300)
    end
     
    function Boss_OnDeath(pUnit, Event)
    pUnit:SendChatMessage(14, 0, "That's impossible! Nooo!")pUnit:RemoveEvents()
    end
    It looks nice now, but how are these events activated? Well, really simple, you need to register these events with:



    Code:
     
    RegisterUnitEvent(EntryID, 1, "Boss_OnCombat")
    RegisterUnitEvent(EntryID, 2, "Boss_OnLeaveCombat")
    RegisterUnitEvent(EntryID, 3, "Boss_OnKilledTarget")
    RegisterUnitEvent(EntryID, 4, "Boss_OnDeath")
    This is the registering part of the events, I'm going to explain you step by step how it works.

    RegisterUnitEvent, means that it registers the kind of event.

    EntryID, here you need to put the EntryID of your NPC.

    1, this shows what type of event it is. 1 means that it's the OnCombat event. 2 means OnLeaveCombat, 3, means OnKilledTarget and 4 means OnDeath. Those are basics, do not mess with these numbers, just put them at the right place.

    "Boss_OnCombat", this is the name of the event, if you got another name on the OnCombat event, you need to change to name of it in the registering part too.

    How do I put the registering part in the script? Simple, I'll show you!


    Code:
     
     
    function Boss_OnCombat(pUnit, Event)
    pUnit:SendChatMessage(14, 0, "Welcome to my lair!")
    end
     
    function Boss_OnLeaveCombat(pUnit, Event)
    pUnit:SendChatMessage(14, 0, "You are to scared for my powers?!")pUnit:RemoveEvents()
    end
     
    function Boss_OnKilledTarget(pUnit, Event)
    pUnit:SendChatMessage(14, 0, "Your worthless blood feeds me!")pUnit:CastSpell(36300)
    end
     
    function Boss_OnDeath(pUnit, Event)pUnit:SendChatMessage(14, 0, "That's impossible! Nooo!")
    pUnit:RemoveEvents()
    end
     
    RegisterUnitEvent(EntryID, 1, "Boss_OnCombat")
    RegisterUnitEvent(EntryID, 2, "Boss_OnLeaveCombat")
    RegisterUnitEvent(EntryID, 3, "Boss_OnKilledTarget")
    RegisterUnitEvent(EntryID, 4, "Boss_OnDeath")
    Just down the whole script, you don't need to have function, end or whatever to it. This is the whole Registering part of the events.

    Now, you should know how the events are working. Lets move to the next part

    Last edited by ahlmo; 09-20-2009 at 06:52 AM.

  2. #2
    ahlmo is offline Member
    Array
    Join Date
    Jun 2009
    Posts
    44
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Rep Power
    11
    Reputation
    8
    SPELLS

    Alright! The part who shows what sort of boss it is, the part who shows how hard the boss is, the part shows how great the boss is!

    Spells have everything to do with what type of boss it is and how hard it is. Without spells, the boss is nothing, but you know. Let me show you some ways how to have spells.


    Code:
     
    CastSpell() --Working
    FullCastSpell() --bugged
    CastSpellOnTarget() --bugged/Working
    FullCastSpellOnTarget() --working
    I have showed you in the first part how to find an ID of a spell. So, I don't need to explain that anymore. And you know how CastSpell() works so I'm going to skip that too.

    FullCastSpell(), this means that he casts an Area of Efect spell with casttime or a spell on himself.
    Example:


    Code:
     
    function Boss_Spell(pUnit, Event)
    pUnit:FullCastSpell(SpellID)
    end
    CastSpellOnTarget(), this is that he casts a spell on a target. You need to have the ID in the brackets ofcourse. But there is another thing you need to have on it, I'll red it up what I'm changing.


    Code:
     
    function Boss_Spell(pUnit, Event)
    pUnit:CastSpellOnTarget(SpellID, pUnit:GetMainTank())
    end
    As you can see there is something new added. "pUnit:GetMainTank()". This means that he will target the main tank (the one with the highest treath). There are more targets he can target. I will show you which you can target more and how to use them.


    Code:
    pUnit:GetMainTank() -- He will target a player with the highest treathpUnit:GetRandomPlayer(0) -- He will target a random playerpUnit:GetRandomPlayer(1) -- He will target a player in short rangepUnit:GetRandomPlayer(2) -- He will target a player in mid rangepUnit:GetRandomPlayer(3) -- He will target a player in longe rangepUnit:GetRandomPlayer(4) -- He will target a player with manapUnit:GetRandomPlayer(5) -- He will target a player with ragepUnit:GetRandomPlayer(6) -- He will target a player with energypUnit:GetRandomPlayer(7) -- He will target a player who is not the main tank
    If you want to let him target someone else, just remove "pUnit:GetMainTank()" and put another target in it, by example someone in short range: "pUnit:GetRandomPlayer(1)".

    FullCastSpellOnTarget(), this is the same as CastSpellOnTarget() but this is now with casttime, looks like the same as CastSpell() and FullCastSpell(). You just need to use the same format as you did with CastSpellOnTarget().

    Alright, now you know how to set the spells in an event, I'm going to show now how to register them.

    Registering the spells has much to do with timing. I can't explain it really good in words now, so let me show an example. I will be using the OnCombat phase.

    Code:
     
    function Boss_OnCombat(pUnit, Event)
    pUnit:SendChatMessage(14, 0, "Welcome to my lair!")
    pUnit:RegisterEvent("Boss_Spell", 5000, 0)
    end
     
    function Boss_Spell(pUnit, Event)
    pUnit:FullCastSpellOnTarget(SpellID, pUnit:GetMainTank())
    end
    I will be explaining this step by step:

    pUnit:RegisterEvent, this will register the event "Boss_Spell". Without registering it, then it will not work.

    ("Boss_Spell", this is the name of the event what the boss registers.

    , 5000, 0), Now, the boss will register the function every 5000 miliseconds so, every 5 seconds. 1000 miliseconds = 1 second. The 0 means how many time it registers. The 0 here means that it registers every 5 seconds forever. You can replace the 0 by another number, by example 2. Then it will register only 2 times so he casts the spell 2 times and not forever.

    function Boss_Spell(pUnit, Event)
    pUnit:FullCastSpellOnTarget(SpellID, pUnit:GetMainTank())
    end, this is the event of a spell. As you can see, it contains 3 simple lines. The function, the spell and the end. This event looks very much on the oncombat phase. Most events do look like eachother. But it is just about what they are for. I named my function "Boss_Spell" because it's simple to understand in this tutorial. If you are making your own scripts, I recommend to not use Boss_Spell1 or something. Because when you are making more scripts, there could be a script interferne. This means that it will use the script of another script and your script for the boss in one. Use the name of your NPC and the name of your spell, like "KelThuzad_FrostBolt" but this could be simple way "Kel_FrostBolt" as long as you have the same name as the name in the registering part.

    Now you should know:

    How to make an event with a spell
    How to register the event
    How to lookup the spell
    How to make it target someone else

    Lets move on the to next part of our journey to Lua knowledge!
    Last edited by ahlmo; 09-20-2009 at 06:55 AM.

  3. #3
    ahlmo is offline Member
    Array
    Join Date
    Jun 2009
    Posts
    44
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Rep Power
    11
    Reputation
    8
    PHASES

    Phases are great to use in a script. With phases you can make the boss do spells at an x amount of %. This is great because then you need to make tactics for a boss. By example a custom made boss. You are in a raid and the raid leader says something like: "Back up everyone! He's almost at x %" or something like that. How cool is that. Well, enough talking, I'm going to learn you how to make and use phases.

    4.1 Phases at x amount of %
    4.2 Phases at timing

    PHASES AT X AMOUNT OF %

    The first topic we will discuss about phases is phases at x amount of %. This is the most used kind of phase. I will show you how a basic phase at x amount of % looks like.



    Code:
     
    function Boss_Phase1(pUnit, Event)
    if pUnit:GetHealthPct() <= 50 then
    pUnit:RemoveEvents()
    end
    end
    This looks like a phase with no events. Let me explain everything to you.

    function Boss_Phase1(pUnit, Event), I've tought you this in the first chapter. So I don't need to explain further about it. The only thing that has changed is the name to "Boss_Phase1". It's easier to remember to use "Phase1", "Phase2" instead of other names. But remember that the name must be the same as in the registering part.

    if, if is a GREAT statement in all of LUA. "if" is used to make things are true or false. Further explanation is following.

    pUnit:GetHealthPct(), if is before this actually. This shows that "if" the pUnit (boss) gets the percent of health (GetHealthPct()) then it will start the phase.

    <= 50, this means that the phase will start at exact 50%. You can use "<" instead of "<=". "<" is used that it won't start at the exact percent and "<=" will start at the exact percent.

    then, if you are using "if" then you must use "then" at it. This shows that "if" blabla "then". Really easy to understand.

    pUnit:RemoveEvents(), you are probarly wondering, why am I putting "pUnit:RemoveEvents()" in the middle of a script? I'll tell you why. When the boss reaches 50% HP, he will start a whole new phase, so that means he must remove all the events, with events I'm including the spells. He will not cast the same spells anymore and starts with other spells or the same spell. Use your imagination!

    end
    end, two ends? Why? Because "function" and "if" are a statement. If you are using them in one event, you need to let it end on two ends.

    Now you know the basics of how to make a phase at x amount of %. We will start adding some new things in the phase. I will show at the end of this part how to register it so don't worry about that.

    Example:



    Code:
     
    function Boss_Phase1(pUnit, Event)
    if pUnit:GetHealthPct() <= 50 then
    pUnit:RemoveEvents()pUnit:SendChatMessage(14, 0, "You're only halfways!")
    pUnit:FullCastSpellOnTarget(SpellID, pUnit:GetMainTank())pUnit:RegisterEvent("Boss_Spell1", 5000, 0)
    end
    end
    You have learned about the chat message, spells and registering. As you noticed you can register spells at a phase too. It's like it is starting a new script, isn't it.

    Now you know how to make a phase at x amount of %. I will show you how to register it. Because without registering then it won't work!.

    Example:



    Code:
     
    function Boss_OnCombat(pUnit, Event)
    pUnit:SendChatMessage(14, 0, "Welcome to my lair!")
    pUnit:RegisterEvent("Boss_Spell", 5000, 0)
    pUnit:RegisterEvent("Boss_Phase1", 1000, 0)
    end
     
    function Boss_Spell(pUnit, Event)pUnit:FullCastSpellOnTarget(SpellID, pUnit:GetMainTank())
    end
     
    function Boss_Phase1(pUnit, Event)
    if pUnit:GetHealthPct() <= 50 then
    pUnit:RemoveEvents()
    pUnit:SendChatMessage(14, 0, "You're only halfways!")pUnit:FullCastSpellOnTarget(SpellID, pUnit:GetMainTank())pUnit:RegisterEvent("Boss_Spell1", 5000, 0)
    end
    end
     
    function Boss_Spell1(pUnit, Event)
    pUnit:FullCastSpellOnTarget(SpellID, pUnit:GetMainTank())
    end
    It actually isn't hard to register phases. It's just you need to register it every second, or 5 seconds, whatever you want. The point is that you can register it once because then the phase won't work. You always need to put a 0 at the registering part of phases at x amount of %. At timing it's different, but I will explain that later.

    Now you should know how to:

    Make a phase at x amount of %
    Register a phase at x amount of %

    PHASES AT TIMING

    Now you know how to make phases at x amount of %. Now it's time to make phases with timing, they are pretty fun too, the only thing is the timing what is pretty hard sometimes. I'll be showing how a basic phase with timing and without any events looks like:



    Code:
     
    function Boss_Phase1(pUnit, Event)
    pUnit:RemoveEvents()
    end
    As you can see I haven't put "if pUnit:GetHealthPct() <= x" at it. It doesn't need that because this is timing. And if you don't got "if" then you don't need an extra end, simple isn't it? I will make a phase now who gots events:



    Code:
     
    function Boss_Phase1(pUnit, Event)
    pUnit:RemoveEvents()pUnit:SendChatMessage(14, 0, "You have to count now instead of watching my percents!")
    pUnit:FullCastSpellOnTarget(SpellID, pUnit:GetMainTank())pUnit:RegisterEvent("Boss_Spell1", 5000, 0)
    end
    This looks pretty much as the phase with percents. The only thing is that "if pUnit:GetHealthPct() <= x" is gone and the extra end. But, there is another things that is different, and that is registering.

    You should register phases with timing once instead of forever. And the milliseconds should be different too.

    Example:



    Code:
     
    function Boss_OnCombat(pUnit, Event)
    pUnit:SendChatMessage(14, 0, "Welcome to my lair!")
    pUnit:RegisterEvent("Boss_Spell", 5000, 0)
    pUnit:RegisterEvent("Boss_Phase1", 25000, 1)
    end
     
    function Boss_Spell(pUnit, Event)
    pUnit:FullCastSpellOnTarget(SpellID, pUnit:GetMainTank())
    end
     
    function Boss_Phase1(pUnit, Event)
    pUnit:RemoveEvents()
    pUnit:SendChatMessage(14, 0, "You have to count now instead of watching my percents!")
    pUnit:FullCastSpellOnTarget(SpellID, pUnit:GetMainTank())pUnit:RegisterEvent("Boss_Spell1", 5000, 0)
    end
    end
     
    function Boss_Spell1(pUnit, Event)
    pUnit:FullCastSpellOnTarget(SpellID, pUnit:GetMainTank())
    end
    pUnit:RegisterEvent("Boss_Phase1", 25000, 1), This means phase1 will start in 25 seconds. I actually have nothing to say about this further.

    Actually, we are almost at the end of our tutorial. Now you should know how to make a basic boss script. I will be showing an example of a little boss script I made and it has all the features where we have discussed about!

    Enjoy



    Code:
     
    function Legares_OnCombat
    (pUnit, Event)pUnit:SendChatMessage(14, 0, "Welcome to my lair!")pUnit:RegisterEvent("Legares_FireBreath", 6000, 0)
    pUnit:RegisterEvent("Legares_BlastWave", 9000, 2)
    pUnit:RegisterEvent("Legares_Phase1", 27000, 1)
    end
     
    function Legares_FireBreath(pUnit, Event)
    pUnit:CastSpell(36876)
    end
     
    function Legares_BlastWave(pUnit, Event)
    pUnit:FullCastSpell(23039)
    end
     
    function Legares_Phase1(pUnit, Event)
    pUnit:RemoveEvents()pUnit:SendChatMessage(14, 0, "Are you giving up now?!")
    pUnit:FullCastSpellOnTarget(57628, pUnit:GetRandomPlayer(1))pUnit:RegisterEvent("Legares_FireBreath", 6000, 0)
    pUnit:RegisterEvent("Legares_Phase2", 1000, 0)
    end
     
    function Legares_FireBreath(pUnit, Event)
    pUnit:CastSpell(36876)
    end
     
    function Legares_Phase2(pUnit, Event)
    if pUnit:GetHealthpct() <= 50 then
    pUnit:RemoveEvents()
    pUnit:SendChatMessage(14, 0, "You're only halfway!")pUnit:CastSpellOnTarget(56939, pUnit:GetMainTank())
    pUnit:RegisterEvent("Legares_BlastWave", 5000, 0)
    pUnit:RegisterEvent("Legares_Phase3", 1000, 0)
    end
    end
     
    function Legares_BlastWave(pUnit, Event)
    pUnit:FullCastSpell(23039)
    end
     
    function Legares_Phase3(pUnit, Event)
    if pUnit:GetHealthPct() <= 1 then
    pUnit:RemoveEvents()
    pUnit:SendChatMessage(14, 0, "I'm dieing... leave me... alone...")pUnit:FullCastSpell(23039)
    end
    end
     
    function Legares_OnLeaveCombat(pUnit, Event)
    pUnit:SendChatMessage(14, 0, "You are to scared for my powers?!")pUnit:RemoveEvents()
    end
     
    function Legares_OnKilledTarget(pUnit, Event)
    pUnit:SendChatMessage(14, 0, "Your worthless blood feeds me!")pUnit:CastSpell(36300)
    end
     
    function Legares_OnDeath(pUnit, Event)
    pUnit:SendChatMessage(14, 0, "That's impossible! Nooo!")pUnit:RemoveEvents()
    end
     
    RegisterUnitEvent(EntryID, 1, "Legares_OnCombat")
    RegisterUnitEvent(EntryID, 2, "Legares_OnLeaveCombat")RegisterUnitEvent(EntryID, 3, "Legares_OnKilledTarget")
    RegisterUnitEvent(EntryID, 4, "Legares_OnDeath")
    EXTRA ADDITIONS

    I will be giving some tips about how to make Lua easier for you.

    First of all, it's the best thing to get Notepad++. This shows the number of lines, the statements and you can see when you forgot an end, bracket or whatever. Download: SourceForge.net: Notepad++: Files
    How to make it easier for the people who need to read your script? Use comments at each line what's a bit difficult, how? Just do "--" after the line, and it will show up green in Notepad++, then you're writing a comment and the Lua engine will completly ignore it.



    If you have any questions, don't be afraid to ask. I'll try to help.
    I know all about lua =)

    -Ahlmo
    -Editted my Ahlmo

    -Credits to sjoerdman
    Last edited by ahlmo; 09-20-2009 at 07:02 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •