MMOCoin

Likes Likes:  0
Results 1 to 10 of 10

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #2
    Grunt
    SerialKiller's Avatar
    Join Date
    Jan 2010
    Posts
    36
    Post Thanks / Like
    Rep Power
    17
    Reputation
    38
    [3.0]Gameobject Events

    [3.1] Most Common Gameobject Commands Usage & Events.
    You can't do too much with Gameobjects, some people may argue with me but at least on my lua engine, Gameobjects are relatively limited to teleporting.

    To make a simple teleport portal. All do you is use the player:teleport command in the registered event.


    [NOTE]: Most of these examples are going to be copied and pasted from my server, sorry if some of the coords are messed up

    Code:
    
    function Gameobject_OnUse(Unit, Event, player)
        player:Teleport(mapid, x, y, z)
    end
    
    RegisterGameObjectEvent(GOID, 4, "Gameobject_OnUse")
    
    Now, thats not that interesting. However you can add in a few more things, If the player is in combat, you can make the portal un-usable to them;

    Code:
    
    function Gameobject_OnUse(Unit, Event, player)
        if (player:IsInCombat() == true) then
            player:SendAreaTriggerMessage("You are in combat!")
        else
            player:Teleport(mapid, x, y , z)
        end
    end
    
    RegisterGameObjectEvent(GOID, 4, "Gameobject_OnUse")
    
    Some other things you can do, Is for instance, to avoid people camping where people get ported in in gurubashi, you can write the script with math.random command (I'll add that command in the command list above :X) Ex.

    Code:
    
    function GurubashiPortal_OnUse(Unit, Event, player)
    local Choice=math.random(1, 5) -- Chooses a random number between 1 and 5, That value is stored as the local variable 'choice' 
        if (player:IsInCombat() == true) then
            player:SendBroadcastMessage("You are in combat!")
        else
            if (Choice == 1) then    -- Depending on what number came out of the math.random command,Choice's value can be equal to any of the below values in the if statements. Teleporting a player randomly to 1 of 5 spots in gurubashi arena.
                player:Teleport(0, -13217, 184, 100)
            elseif (Choice == 2) then
                player:Teleport(0, -13269, 212, 100)
            elseif (Choice == 3) then
                player:Teleport(0, -13294.5, 279, 100)
            elseif (Choice == 4) then
                player:Teleport(0, -13171, 337, 100)
            elseif (Choice == 5) then
                player:Teleport(0, -13148, 226, 100)
            end
        end
    end
    
    RegisterGameObjectEvent(98815, 4, "GurubashiPortal_OnUse")
    
    [Note]: SQL Below if you're interested. Arcemu structure
    Code:
    
    INSERT INTO `gameobject_names` VALUES ('98815', '22', '7849', 'Armory Portal to Gurubashi', '', '', '', '', '', '', '9438', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0');
    
    Something i've done is made certain portals only interactable with GM's / donars. And no i didn't find out a way to check if a player is a GM.

    Assuming you don't have over nine thousand Game masters (maybe donars), this shouldn't be too much of a hassle.


    Code:
    
    
    function PortalToThinkBox_OnUse(Unit, Event, player)
    local Name = player:GetName()
    
        if (Name == nil) then
            player:SendAreaTriggerMessage("You cannot enter through here!")
        elseif (Name == "GM name one") then
            player:Teleport(1, 16227.4, 16403.8, -64)
        elseif (Name == "GM name two") then
            player:Teleport(1, 16227.4, 16403.8, -64)
        elseif (Name == "GM name three") then
            player:Teleport(1, 16227.4, 16403.8, -64)
        elseif (Name == "GM name four") then
            player:Teleport(1, 16227.4, 16403.8, -64)
        elseif (Name == "GM name five") then
            player:Teleport(1, 16227.4, 16403.8, -64)
        else
            player:SendBroadcastMessage("You are not a Game Master.")
            player:Teleport(mapid, x, y, z) -- Mall Location is what i use.
        end
    end
    
    -- Or of course, you can set GM/Donar names as variables..
    
    RegisterGameObjectEvent(98814, 4, "PortalToThinkBox_OnUse")
    
    Remember in the example above, The names must be in string form... (Wrapped in quotations) otherwise it will think GMnamefour is a variable with a nil value!

    [3.3] Gameobject Summary and Tips

    Gameobjects can not register events. But they can still play a good role in a bossfight, and a big part in your server if you aren't a fan of pocket teleporters (People teleport in combat / bleh) Traditional ports are the way to go IMO =).

    /facepalm at this pathetic section =)



    [5.0] Generalized Gossip Events


    Gossip commands and usage are generally all the same for Gameobjects, NPC's and items.



    A gossip script has 2 events that need to be registered. (OnGossip, and OnSelectOption / OnSubMenu)


    Code:
    
    RegisterUnitGossipEvent(NPCID, 1, "OnGossip")
    RegisterUnitGossipEvent(NPCID, 2, "OnSubMenu")
    RegisterGOGossipEvent(GOID, 2, "OnSubMenu")
    RegisterGoGossipEvent(GOID, 1, "OnGossip")
    RegisterItemGossipEvent(ITEMID, 1, "Item_OnClick")
    RegisterItemGossipEvent(ITEMID, 2, "OnSubMenu")
    
    The basics of a Lua Gossip script are as follows:

    Code:
     
    function Npc_OnGossip(Unit, Event, player)
    
    end
    
    function Npc_OnSubMenu(Unit, Event, player, id, intid, code)
    
    end
    
    [Note]intid, code, will all be explained later
    "player" is the player who clicked the npc.
    Not sure whatid is for
    
    The Gossip commands and usage all go inside, they are as follows;


    Code:
    
    function Npc_OnGossip(Unit, Event, player)
        Unit:GossipCreateMenu(100, player, 0)
        Unit:GossipMenuAddItem(0, "Name", 1, 50)
        Unit:GossipSendMenu(player)
    end
    
    Those are the three basic commands to create the actual gossip interface. What they do is;

    Code:
    
    function Npc_OnGossip(Unit, Event, player)
        Unit:GossipCreateMenu(textid, player, 0) 
    end
    
    textid: Insert the entryid of the text you want to be displayed before your options: Ex. "Hey there, $N. How can I help you?". You can find the correct entryid in `npc_text` table.
    
    player: Who you are creating this menu for.
    
    0: No clue. i just know when its set to anything other than 0, the npc generally doesn't respond with any action.
    
    
    Code:
    
    function Npc_OnGossip(Unit, Event, player)
        Unit:GossipMenuAddItem(symbolid, "Name of Option", intid, codeflag)
    end
    
    symbolid: Sets the ID of the symbol beside the Option Name.
    Name of Option: Sets the name of the Option
    intid: This is what intid will be set to if this option is selected.
    codeflag: Flags triggering this option to open a input box. (1 and 3 are the flags that work.)
    [Note]: please remember intid is a variable.
    
    Code:
    
    function Npc_OnGossip(Unit, Event, player)
        Unit:GossipSendMenu(player)
    end
    
    player: who you are sending the menu too.
    

    Ok, now that you understand what the commands are, lets get started creating an actual gossip script. I will make 3 examples. One of them will be a teleporter, Another one a guessing game.

    Teleporter
    Code:
    
    function Creature_OnGossip(Unit, Event, player)
        Unit:GossipCreateMenu(100, player, 0) -- Sends a menu to the player with the npc_text entryid of 100.
        Unit:GossipMenuAddItem(0, "Outlands Locations", 1, 0) -- SETS intid to 1!!! And registers Creature_OnSubMenu(If its easier to remember, "OnSelectOption", same thing)
        Unit:GossipSendMenu(player) -- Sends menu to the player.
    end
    
    function Creature_OnSubMenu(Unit, Event, player, id, intid, code)
    
        if (intid == 1) then    -- This is what will happen if you click outlands locations
            Unit:GossipCreateMenu(100, player, 0)
            Unit:GossipMenuAddItem(0, "Hellfire Penninsula", 2, 0)
            Unit:GossipSendMenu(player)
        end
    
        if (intid == 2) then -- When you click on Hellfire Penninsula you get teleported since intID gets set to 2.
            player:Teleport(530, x, y, z) -- usage = (mapid, x, y, z) full list of player commands with usage will be posted later.
        end
    end
    
    RegisterUnitGossipEvent(NPCID, 1, "Creature_OnGossip")
    RegisterUnitGossipEvent(NPCID, 2, "Creature_OnSubMenu")
    
    NOTE: "Unit:GossipMenuAddItem(0, player, 0, 0)", Just becuase it is in an OnGossip function. (id, intid, code) still apply to their fields. For this reason, 0 sets intid to 0.


    Whats happening in the script above, is when you click Outlands Locations, intid gets set to 1, At the point in time you've selected an option, which registers ("Creature_OnSubMenu"), If it doesn't make sense, think of Creature_OnSubMenu as Creature_OnSelectOption. So then that function gets registered. and your send a new menu with outland locations. Upon clicking hellfire penninsula, you clicked an option, which registers Creature_OnSubMenu yet again, and changing intid to 2, Executing the code withing the corresponding If statement.

    Now below, i will make a Number guessing gossip script hopefully explaining what almost no Lua Tutorials contain... (Unit, Event, id, intid, code)


    Code:
    
    function Creature_OnGossip(Unit, Event, player)
        Unit:GossipCreateMenu(100, player, 0)
        Unit:GossipMenuAddItem(0, "Guess a number between 1 and 10!", 0, 3) -- 3 Flags this menu item to open an input box where a player can enter data (Like you do when redeeming a wow trading card game code for a rocket mount on retail ect ect)
        Unit:GossipSendMenu(player)
    end
    
    function Creature_OnSubMenu(Unit, Event, player, id, intid, code)
        if (intid == 0) then
            if (code == "5") then -- code is a variable returned as whatever the player entered in the input box. Remember it is returned as a string (in word form) so whatever is it equal to must be in quotations. Having [if (code == 1) then] it will always return false and execute whats inside the 'else', this being due to anything the player types in the box will return as "<what player typed>".
                player:AddItem(29434, 1) -- Adds an item to the player who clicked.  player:AddItem(itemid, quantity)
            else
                player:SendAreaTriggerMessage("You Guessed wrong.") -- inserts a message into the players chat box in yellow.
            end
        end
    end
    
    RegisterUnitGossipEvent(NPCID, 1, "Creature_OnGossip")
    RegisterUnitGossipEvent(NPCID, 2, "Creature_OnSubMenu")
    
    "5" Is that value that IF what the player entered in the box is equal to, the statement will add an item to the player.
    
    There wasn't much to explain, so i just threw in what there was to know in comments.

    Its been a while since I've updated this, but i thought I'd add this small tip in for gossip scripts;

    When creating a gossip scripts, It gets annoying always having to close and re-open the gossip after you've selected a certain option. For example, Say one of your gossip scripts is to give players food, The player does not want to have to re-open the gossip menu everytime he wants to get a new stack of food! So to keep the same menu active after an option has been selected, check out the example below.


    Code:
    
    function Unit_OnGossip(Unit, Event, player)
         Unit:GossipCreateMenu(100, player, 0)
         Unit:GossipMenuAddItem(0, "Item Selection", 1, 0)
         Unit:GossipSendMenu(player)
    end
    
    function Unit_OnSelect(Unit, Event, player, id, intid, code)
    if (intid == 1) then
         Unit:GossipCreateMenu(101, player, 0)
         Unit:GossipMenuAddItem(0, "Add Food!", 2, 0)
         Unit:GossipMenuAddItem(0, "Add Water!", 3, 0)
         Unit:GossipSendMenu(player)
    end
    
    if (intid == 2) then
         player:AddItem(FoodItemID, amount)
         intid = 1
         Unit:GossipSendMenu(player)
    end
    
    if (intid == 3) then
         player:AddItem(WaterItemID, amount)
         intid = 1
         Unit:GossipSendMenu(player)
    end
    
        
    end
    
    What this does is adds an item to the players inventory, then sets intid to 1, and sends the menu associated to 1 to the player again. Keep in mind the menu being sent must be the one the player was currently on, otherwise it won't work(There is logic behind this but its late and i forget :S). To have properly working back buttons, i believe you still have to make a replica of the menu you want it to go back to.

    Item Gossip

    Theres not much difference between regular gossip events, and ones you'd use with an item.

    Code:
    
    function Item_OnClick(Item, Event, player)
        Item:GossipCreateMenu(100, player, 0)
        Item:GossipMenuAddItem(0, "hello lets telepert", 0, 0)
        Item:GossipMenuAddItem(0, "hello want an item?", 2, 0)
        Item:GossipSendMenu(player)
    end
    
    function OnSubMenu(Item, Event, player, id, intid, code)
        if (intid == 0) then
            player:Teleports(mapid, x, y, z)
        end
    
        if (intid == 1) then
            player:AddItem(itemid, 1)
        end
    end
    
    RegisterItemGossipEvent(ITEMID, 1, "Item_OnClick")
    RegisterItemGossipEvent(ITEMID, 2, "OnSelect")
    

    Above, is an example of an item gossip script. You script the exact same as you would with a Npcs gossip. There is almost no difference.



    Below is a list of player commands usefull when creating gossip scripts.
    Code:
    
    player:AddItem(itemid, quantity) -- Adds item to the players inventory
    player:Teleport(mapid, xcoord, ycoord, zcoord)    -- Teleports the player to the selected coordinates.
    player:SendAreaTriggerMessage("Message") -- Enters a message in the players chat box.
    player:SendBroadcastMessage("Message") -- Enters a message across the players screen, where error messsages are shown
    player:GossipSendPOI(player, Xcoord, Ycoord, icon, flags, data, nameofPOI); -- Flags a coordinate on your main map, and mini map, as a Point of Interest, with the assigned name, icon and coordinates. Leave data as 0. (I almost never use this command, so im not the best person to be explaining it)
    
    Aside from those, i don't believe you use many More.

    [$.#]3x7r4 1Nf0rNm471on

    String Concatenation

    Had to add this in here right now. Concatenation is just joining two strings together. Say if you wanted your boss to cast a spell on a certain person, and call out their name. You'd use string Concatenation.

    Heres an example of having a boss call out a players name.


    Code:
    
    function Creature_OnCombat(Unit, Event)
        Unit:RegisterEvent("Creature_CastSpell", 30000, 0)
    end
    
    function Creature_CastSpell(Unit, Event)
    local name = Unit:GetRandomPlayer(7)
        Unit:FullCastSpellOnTarget(
        Unit:SendChatMessage(14, 0, "Enjoy sum frostbewltz"..name) -- "Enjoy sum frostbewltz" is the first part of the string, and 'name' is the variable your joining together.
    end                                               -- The two dots are what is joining them together.
    
    RegisterUnitEvent(NPCID, 1, "Creature_OnCombat")
    
    Creature yells: Enjoy sum frostbewltz VisionOneThousand
    
    two periods and two alone, are what you use to join two strings together when you want to do something like above. Or when your debugging a stupid script that won't work, and you can't figure out why a certain value even though set, will never be equal to another value.

    Code:
    
    local number = 5
    
    function Creature_OnCombat(Unit, Event)
        Unit:RegisterEvent("Creature_OnCastSpell", 1000, 1)
    end
    
    function Creature_OnCastSpell(Unit, Event)
    local plr = Unit:GetRandomPlayer(0) -- Gets a random player
    local name = plr:GetName()
        Unit:CastSpellOnTarget(11, name)    -- Using CastSpellOnTarget, it was bugged at one point and would ALWAYS cast the spell on itself.
        Unit:SendChatMessage(14, 0, "name is equal to"..name.."Is that who the spell was cast on?") -- If the spell casts on himself, the command is bugged, if it casts on 'name' (Whoever was said ingame) then it works.
    end
    
    RegisterUnitEvent(NPCID, 1, "Creature_OnCombat")
    
    Debugging.

    When making a Lua script for your first time. You are going to get a LOT of errors. Most errors are caught by the lua Engine on startup. But some get printed on the console while your script is running ingame (If your trying to add 1 to a variable with a nil value).
    Heres a screenshot of what the errors can look like on startup.



    [NOTE]: No i don't use a repack, i just still use the Ac-web folder from when i used to =P
    It will tell you what line the error is on, which is usually enough to go find whats wrong, but it also tells you whats wrong. even though sometimes it feels like its always saying the same thing.

    Heres a list(that i can remember) of debugging errors i've ran into;

    Code:
    
    Forgetting a Left Parethisis to close a Function/Command.
    Unit:SendChatMessage(41, 0, "The Lava Around Sarthiron Begins to Churn"
    
    Forgetting a comma inside the Parameters of a Command.
    Unit:SendChatMessage(41, 0 "The Lava Around Sarthiron Begins to Churn")
    
    Concatenating a string with a nil value.
    function Creature_OnCombat(Unit, Event)
        local name        -- Nil value, forgot to put player:GetName()
        Unit:SendChatMessage(14, 0, "how come you be agroing me "..name)
    end
    
    Adding an integer with a nil value.
    function Creature_OnCombat(Unit, Event)
        count = count + 1 -- When the creature enters combat, count was never previously given a value, so it is nil, and it is being added to 1. To fix this you'd write 'local count = 0' at the top of the script.
    end
    
    Adding an integer to a string.
    function Npc_OnGossip(Unit, Event, player)
        Unit:GossipCreateMenu(100, player, 0)
        Unit:GossipMenuAddItem(1, "Guessing Game", 0, 3)
        Unit:GossipSendMenu(player)
    end
     
    function Npc_OnSubMenu(Unit, Event, player, id, intid, code)
        codeplusone = code + 1 -- Code (Whatever the player wrote in the text box) will always return as a string, trying to add it to 1 will give you an error.
        if (code == codeplusone) then
            player:AddItem(29434, 20)
        end
    end
     
    Forgetting or adding an extra 'end' to a function / if statement.
    function Creature_OnCombat(Unit, Event)
        if (Unit = nil) then
            print"awmah gawd this creature doesn't exist and its attacking me!"
        elseif
            if (Unit ~= nil) then
                print"phew this creature exists"
                -- Should be an End here.
        end
    end
    
    Using lowercase letters.
    function Creature_OnCOmbat(Unit, Event)
        unit:SendChatMessage(14, 0, "Why is this not working?") -- Lowercase unit at the start of the command.
    end
     
    
    As you can see most of these errors are from spelling mistakes (Where the Lua Engine also tells you what line the error is on), However when a certain phase isn't registering and you can't figure out why or where to look. Use of the print command can come in handy, To give you an idea of where to look.

    The usage of the print command is as follors

    Code:
    
    print"insert debug message here"
    
    print("Insert Message here")
    
    Below is how it could be used when you're having a problem with your script

    Code:
    
    local count = 0
    
    function Creature_OnCombat(Unit, Event)
        Unit:RegisterEvent("Creature_PhaseOne", 1000, 1)
    end
    
    function Creature_PhaseOne(Unit, Event)
        count = count + 1
        if (count == 1) then
            Unit:SendChatMessage(14, 0, "Im gonna cast a spell on you.")
        elseif (count == 4) then
            Unit:SendChatMessage(14, 0, "Im gonna send a chat message!")
        elseif (count == 5) then
            Unit:SendChatMessage(14, 0, "Watchout this script is about to break")
        end
    
        if Unit:GetHealthPct <= 80 then
            -- register a new event.
        else
            Unit:RegisterEvent("Creature_PhaseOne", 1000, 1)
            print("count is equal to"..count) -- This will print in the console every second what count is equal to. And then you can figure out why it isn't looping like you want it to.
                              -- The reason is, count was never reset back to 0 when it was equal to 5. so you would've found count would'v continuously went up.
        end
    end
    


    If you find you're events are accelerating faster and faster casting a spell inside a function until the server crashes check the interval count on the end of when you register an event; I've done once.

    Code:
    
    function Creature_OnCombat(Unit, Event)
    local name = player:GetName()
        Unit:SendChatMessage(14, 0, "Why are you agroing me"..name)
        Unit:RegisterEvent("Creature_CastSpell", 1000, 0) -- Put it as infinite, which registered the event when the event was registered.
    end
    
    function Creature_CastSpell(Unit, Event)
        Unit:CastSpell(insertIDhere)
        
        if Unit:GetHealthPct() <= 80 then
            -- register new event
        else
            Unit:RegisterEvent("Creature_CastSpell", 1000, 1) -- You can guess where this led too
        end
    end
    
    If you get an error about Unknown symbol near 'insert line of code here' Just rewrite that line, not really sure what causes it.

    ================================================== ==================

    That brings us to the end of this tutorial, Hopefully you've learned something or had any questions you had answered. And remember, Sometimes just doing the boring work of 15 extra If statements / functions is worth having a move fun boss fight for.

    Hopefully you can use what you've learned to be innovative and creative in your scripts.


    This tutorial is finished, but i will still be adding things to it. PM me if you are curious how to do certain things or use certain commands. I will PM you back and then add an example and Explanation to this guide! Its win win.
    Last edited by Apple; 20-02-10 at 09:09 PM. Reason: changed text colour



  2. Related Threads - Scroll Down after related threads if you are only interested to view replies for above post/thread

 

 

Posting Permissions

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