
Results 1 to 10 of 14
Thread: [Ultimate]LUA Guide & Tut
-->
-->
Threaded View
-->
-
27-10-09, 04:54 AM #2
[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")
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")
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');
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")
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 what id is for
Code:function Npc_OnGossip(Unit, Event, player) Unit:GossipCreateMenu(100, player, 0) Unit:GossipMenuAddItem(0, "Name", 1, 50) Unit:GossipSendMenu(player) end
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")
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)
[$.#]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")
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")
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.
me if I have helped you in anyway ^^ Example: Sharing a repack, answering questions... Well you know the rest xD. As long as I help you!