====== Getting Trigger variables using scripts ====== ===== ActionAttr List ===== ^ Name ^ Value ^ Description ^ | Position | 1 | Position | | AreaIns | 2 | Area | | Number | 3 | Value | | String | 4 | String | | Boolean | 5 | Boolean | | Player | 6 | Player | | PlayerGrout | 7 | Player Set | | BlockType | 8 | Block type | | ItemType | 9 | Prop type | | Creature | 10 | Creature | | ActorID | 11 | Actor type | | CreatureGroup | 12 | Creature Set | | Timer | 13 | Timer | | EffectType | 14 | Special effect type | | SiteGroup | 15 | Location group | | AreaGroup | 16 | Area group | | NumberGroup | 17 | Value group | | StringGroup | 18 | String group | | BooleanGroup | 19 | Boolean group | | BlockTypeGroup | 20 | Block type group | | ItemTypeGroup | 21 | Prop type group | | CreatureTypeGroup | 22 | Creature type group | | TimerGroup | 23 | Timer group | | EffectTypeGroup | 24 | Effect type group | ((TABLE FROM [[developer_center:developer_editor:script:datatype#obtain_trigger_variable|Datatypes - Obtain trigger variable]])) ===== Why would you want to get trigger variables ===== If you are in this tutorial, chances are, you probably want to create games using both scripts and triggers, the best of both worlds, and there are methods that allow us to do just that, it is also useful as you can use the trigger variables as cross-script variables, mini world does not allow the use of the **require** method((More info about [[https://www.lua.org/pil/8.1.html|Require]] here)) so that's a great alternative to the require as it allows us to access and use variables that can be used in all the scripts ===== How to get global variables ===== To get global variables it's easy as we have methods to do so, they are the getGlobalVarByName that as you may have guessed from the name, lets you get the value of a global variable and setGlobalVarByName which lets you change the value of a global variable ==== getGlobalVarByName ==== Lets talk about this method first. This method takes two parameters: * actionattr: number (The type of variable) * msg: string (The name of the variable) And returns: * [[developer_center:developer_editor:script:miniapi_tutorialerrorhandling|Errorcode]] * Value (Depends) We will do an use example after explaining the next method. ==== setGlobalVarByName ==== This method changes the value of the trigger variable that we gave. It takes three parameters * actionattr: number (The type of variable) * msg: string (The name of the variable) * val (depends on actionattr) And returns: * [[developer_center:developer_editor:script:miniapi_tutorialerrorhandling|Errorcode]] === Use example === Lets say that we want to make that when a creature is defeated a variable goes up by one, we will do that part with triggers, and when that variable is more than or equal to five, we will send a message to all players that says "You won!" and then we reset that variable back to 0, we will do that part with scripts === Trigger === {{:developer_center:developer_editor:script:devplustriggernew.png?nolink&400|}} === Script === We start by creating a function, in this functions params are not necesary and adding the [[wp>Event_(computing)#Event_handler|Listener]] with the **Actor.Die** (Creature dies) event and the function we created, i won't go into too much detail with this as this was explained in [[developer_center:developer_editor:script:miniapi_tutorialevent|Event tutorial]] **The code should look like this:** function CreatureDefeated() end ScriptSupportEvent:registerEvent([=[Actor.Die]=], CreatureDefeated) We then add to the function the **getGlobalVarByName(actionattr,msg)** method, as we explained at the start of this tutorial, the **actionattr** method is the type of the variable that we want to get, you may be wondering, how can i know, and the answer is that this table has every type of variable possible and its value **Table** ^ Name ^ Value ^ Description ^ | Position | 1 | Position | | AreaIns | 2 | Area | | Number | 3 | Value | | String | 4 | String | | Boolean | 5 | Boolean | | Player | 6 | Player | | PlayerGrout | 7 | Player Set | | BlockType | 8 | Block type | | ItemType | 9 | Prop type | | Creature | 10 | Creature | | ActorID | 11 | Actor type | | CreatureGroup | 12 | Creature Set | | Timer | 13 | Timer | | EffectType | 14 | Special effect type | | SiteGroup | 15 | Location group | | AreaGroup | 16 | Area group | | NumberGroup | 17 | Value group | | StringGroup | 18 | String group | | BooleanGroup | 19 | Boolean group | | BlockTypeGroup | 20 | Block type group | | ItemTypeGroup | 21 | Prop type group | | CreatureTypeGroup | 22 | Creature type group | | TimerGroup | 23 | Timer group | | EffectTypeGroup | 24 | Effect type group | ((TABLE FROM [[developer_center:developer_editor:script:datatype#obtain_trigger_variable|Datatypes - Obtain trigger variable]])) ----- My variable is a number, so the actionattr is 3, but after seeing the table you may start to wonder, what about the **msg** parameter? it's the name of the variable we want to get, the variable i created is called "MyTestVal" so the **msg** i must use is "MyTestVal", but if your variable name is different then you must use your variable name as your "**msg**". Common errors: function CreatureDefeated() local result = VarLib2:getGlobalVarByName(3,"MyTestVal") end ScriptSupportEvent:registerEvent([=[Actor.Die]=], CreatureDefeated) This error is common, its because getGlobalVarByName returns **2** values(errorcode and then the value) instead of just the value, if you try to use the **result** variable you will either get 0 (ErrorCode.OK No errors) or 1001 (ErrorCode.FAILED there was an error) the fix to this is to add another variable (**local result, value = VarLib2:getGlobalVarByName(3,"MyTestVal")** Tip: If you won't use a variable that it's returned by any method, you can use _ instead of the variable name, the "_" tells lua that variable won't be used, you can use the "_" multiple times, example: _,_, PlayerList = World:getAllPlayers(-1) while if you didn't use the "_" you would have to declare it like this result, PlayerNum, PlayerList = World:getAllPlayers(-1) **The code should look like this:** function CreatureDefeated() local result, value = VarLib2:getGlobalVarByName(3,"MyTestVal") end ScriptSupportEvent:registerEvent([=[Actor.Die]=], CreatureDefeated) **or** function CreatureDefeated() local _, value = VarLib2:getGlobalVarByName(3,"MyTestVal") end ScriptSupportEvent:registerEvent([=[Actor.Die]=], CreatureDefeated) Both do the same. but the former is a better idea if you want to handle any possible errors that may occur. We then add an if statement that checks if value is greater than or equal to 5 and if its true then send a message to the player that says "You won!" and also sets our variable back to 0, the setGlobalVarByName method also has actionattr and msg, so we can copy them from our getGlobalVarByName, but the last parameter (val) is the value that we want the variable to be, in this case, 0 **The code should look like this:** function CreatureDefeated() local result, value = VarLib2:getGlobalVarByName(3,"MyTestVal") if value >= 5 then Chat:sendSystemMsg("You won!", 0) VarLib2:setGlobalVarByName(3,"MyTestVal",0) end end ScriptSupportEvent:registerEvent([=[Actor.Die]=], CreatureDefeated) **or** function CreatureDefeated() local _, value = VarLib2:getGlobalVarByName(3,"MyTestVal") if value >= 5 then Chat:sendSystemMsg("You won!", 0) VarLib2:setGlobalVarByName(3,"MyTestVal",0) end end ScriptSupportEvent:registerEvent([=[Actor.Die]=], CreatureDefeated) ===== How to get player (private) variables ===== Like with global variables, with private variables we also have methods that allow us to get the values that are stored in them, the methods both follow the same structure as the global variable ones, the only change is that we first need to specify the id of the player that we want to obtain his private variale ==== getPlayerVarByName ==== This time we will talk about the private counterpart of the getGlobalVaByName method. This method takes three parameters: * objid:number (The uid of the player we will get the var value) * actionattr: number (The type of variable) * msg: string (The name of the variable) And returns: * [[developer_center:developer_editor:script:miniapi_tutorialerrorhandling|Errorcode]] * Value (Depends) We will do an use example after explaining the next method. ==== setPlayerVarByName ==== This method changes the value of the private variable that we gave to the player that has the uid that we gave it. It takes four parameters * objid: number (The uid of the player we will get the var value) * actionattr: number (The type of variable) * msg: string (The name of the variable) * val (depends on actionattr) And returns: * [[developer_center:developer_editor:script:miniapi_tutorialerrorhandling|Errorcode]] === Use example === This time we will do something different, with the scripts we will do something similar, where when a player defeats a monster we will add 1 to the monsters the player has defeated, and when the player defeats a number of monsters, let's say its 5 we will display "{PlayerNickname} has leveled up" where **{PlayerNickName}** it's a placeholder for the player's name === Trigger === {{:developer_center:developer_editor:script:devplustriggernewprivate.png?nolink|}} === Script === Now, for this we will need a bit more experience with the basics as we are using something called a **numeric for loop** ((More info here [[https://www.lua.org/pil/4.3.4.html| Lua numeric for page]] and a while loop ((More info here [[https://www.lua.org/pil/4.3.2.html| while loop page]] We start by doing the same as we did with the other example, we create a function that does not need args, we add the [[wp>Event_(computing)#Event_handler|Listener]] and we add a while true loop inside the function we created, code should look something like this: function CreatureDefeated() while true do threadpool:wait(1) end end ScriptSupportEvent:registerEvent([=[Game.Start]=], CreatureDefeated) the **threadpool:wait(seconds)** function is really important as if we do not add it, our game could crash, we then add inside the while loop a **World:getAllPlayers(-1)** -1 means all players, and we add three variables as this method returns: * [[developer_center:developer_editor:script:miniapi_tutorialerrorhandling|Errorcode]] * The number of players * A list of all the player's ids But we will only need the list, after that we then add a numeric for loop with i = 1, PlayerListLength and inside that list we add the getPlayerVarByName method, we already know how to get the actionattr and the message so we will pass to the objid after showing the code The code should look something like this: function CreatureDefeated() while true do local _,_,PlayerList = World:getAllPlayers(-1) for i=1, #PlayerList do local result, value = VarLib2:setPlayerVarByName(PlayerList[i],3,"MyPrivateTestVar") Chat:sendSystemMsg(value) end Trigger:wait(1) end end ScriptSupportEvent:registerEvent([=[Game.Start]=], CreatureDefeated) After seeing the code, you may wonder, why are we using PlayerList[i], the answer resides on how the for loop works, the for loop works like this for initialvalue, endvalue, increment, the initial value is where we are defining the initial value of i, endvalue that is the value i will increment to and when it reaches that value, it will stop and increment which its optional and if not specified is equal to 1, the # value is equal to length of, so we are saying, the initial value of i is 1 and its the endvalue will be the PlayerList length (The current number of players) so, if there are 4 players, the playerlist length will be 4 and so, it will execute until i is equal to the end value (4 times) so what [i] does it that it calls the element in the position i of the table, let's show you with a little example ^ Player ^ Position in table ^ | NotSoPr17 | 1 | | PvpGamesAreGreat | 2 | | MiniWorldPlayer | 3 | | ILoveMiniWorld | 4 | so we know that there are 4 players so the length of the playerlist will be 4, then we do the for statement for i=1, #playerlist (we know playerlist is 4 so it will be executed and i will increment by 1 until i is equal to 4) i -> 1 (NotSoPr17) i -> 2 (PvpGamesAreGreat) i -> 3 (MiniWorldPlayer) i -> 4 (ILoveMiniWorld) So basically PlayerList[i] is the id of the player in the position i After this, we add an if statement that checks if the player's variable value is greater than or equal to 5, the code should look something like this function CreatureDefeated() while true do local _,_,PlayerList = World:getAllPlayers(-1) for i=1, #PlayerList do local result, value = VarLib2:setPlayerVarByName(PlayerList[i],3,"MyPrivateTestVar") if value >= 5 then end end threadpool:wait(1) end end ScriptSupportEvent:registerEvent([=[Game.Start]=], CreatureDefeated) After this, when a player defeats more than 5 monsters or players the code inside the if will execute, after this we add a **local _,playerNick = Player:getNickname(PlayerList[i])** that gets the nickname of the current player and we create a function that takes a content and a playerlist and displays a message to them, the function will use the for statement for this **the function should look something like this:** function SendToAllPlayers(content,funcplayerlist) for i=1, #funcplayerlist do Chat:sendSystemMsg(content, funcplayerlist[i]) end end After this, we add to our if statement that checks if the value is greater than or equal to 5 and we use the setPlayerVarByName method with the objid as playerlist[i] **If you are confused, which is natural when learning something new, here is the code** function SendToAllPlayers(content,funcplayerlist) for i=1, #funcplayerlist do Chat:sendSystemMsg(content, funcplayerlist[i]) end end function CreatureDefeated() while true do local _,_,PlayerList = World:getAllPlayers(-1) for i=1, #PlayerList do local result, value = VarLib2:getPlayerVarByName(PlayerList[i],3,"MyPrivateTestVar") if value >= 5 then local _,playerNick = Player:getNickname(PlayerList[i]) SendToAllPlayers(playerNick .. " has leveled up!", PlayerList) VarLib2:setPlayerVarByName(PlayerList[i],3,"MyPrivateTestVar",0) end end threadpool:wait(1) end end ScriptSupportEvent:registerEvent([=[Game.Start]=], CreatureDefeated)