Moony Posted March 13, 2020 Share Posted March 13, 2020 I've got this: Spoiler local function loopVehicles(p) local acc = getPlayerAccount (p) if not isGuestAccount (acc) and isObjectInACLGroup ("user."..getAccountName (acc), aclGetGroup ( "Admin" ) ) then local count = 0 for i, v in ipairs (getElementsByType ("vehicle")) do if v then local occupants = countOccupants(v) if not occupants or occupants == 0 then if getVehicleType(v) == "Trailer" then if not getVehicleTowingVehicle(v) then destroyElement (v) count = count+1 end else destroyElement (v) count = count+1 outputChatBox("Todos los vehículos fueron removidos.", source) end end end end end end addCommandHandler ("cleana", loopVehicles) local loopRadius = 50 local function localLoopVehicles(p) local acc = getPlayerAccount (p) if not isGuestAccount (acc) and isObjectInACLGroup ("user."..getAccountName (acc), aclGetGroup ( "Admin" ) ) then local x, y, z = getElementPosition (p) local localCol = createColCircle (x, y, loopRadius) local count = 0 for i, v in ipairs (getElementsWithinColShape (localCol, "vehicle")) do if v then local occupants = countOccupants(v) if not occupants or occupants == 0 then if getVehicleType(v) == "Trailer" then if not getVehicleTowingVehicle(v) then destroyElement (v) count = count+1 outputChatBox("Los vehículos cercanos fueron removidos.", source) end else destroyElement (v) count = count+1 outputChatBox("Los vehículos cercanos fueron removidos.", source) end end end end destroyElement(localCol) end end addCommandHandler ("clean", localLoopVehicles) function countOccupants(vehicle) if vehicle and getElementType(vehicle) == "vehicle" then local ppl = getVehicleOccupants(vehicle) if not ppl then return false else local counter = 0 for seat, player in pairs(ppl) do counter = counter + 1 end return counter end end end Script found in MTA's community resources. Made by 'Dutchman101'. I made the timers and the chatbox warnings: function Warning1() outputChatBox("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: #FF0000Todos los vehículos explotados y vacíos serán removidos en 30 segundos.", getRootElement(), 0, 0, 0, true) setTimer(function () outputChatBox("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: #FF0000Todos los vehículos explotados y vacíos serán removidos en 5 segundos.", getRootElement(), 0, 0, 0, true) setTimer(loopVehicles, 5000, 1) end, 25000, 1) end Translation: 1. "All blown and empty vehicles will be removed in 30s". 2. "All blown and empty vehicles will be removed in 5s". The 2nd message waits 25 seconds before appearing, and then it should trigger the 'loopVehicles' function. So I thought that by replacing the <loopVehicles> in the timer above with the entire fuction, I'd get the desired script: Spoiler function Warning1() outputChatBox("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: #FF0000Todos los vehículos explotados y vacíos serán removidos en 30 segundos.", getRootElement(), 0, 0, 0, true) setTimer(function () outputChatBox("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: #FF0000Todos los vehículos explotados y vacíos serán removidos en 5 segundos.", getRootElement(), 0, 0, 0, true) setTimer(function () local acc = getPlayerAccount (p) if not isGuestAccount (acc) and isObjectInACLGroup ("user."..getAccountName (acc), aclGetGroup ( "Admin" ) ) then local count = 0 for i, v in ipairs (getElementsByType ("vehicle")) do if v then local occupants = countOccupants(v) if not occupants or occupants == 0 then if getVehicleType(v) == "Trailer" then if not getVehicleTowingVehicle(v) then destroyElement (v) count = count+1 end else destroyElement (v) count = count+1 outputChatBox("Todos los vehículos fueron removidos.", source) end end end end end end, 5000, 1) end, 25000, 1) end addCommandHandler ("cleana", Warning1) In other words, I've got a cleaning function that happens 5 seconds after an output chatbot that happens 25 seconds after the command is entered. I've got: - Bad argument at line 6 ('local acc = getPlayerAccount (p)'). Expected element at argument 1, got nil. - Bad argument at line 7 ('if not isGuestAccount (acc) and [...] then'). Expected element at argument 1, got boolean. - Bad argument at line 7 ('("user."..getAccountName (acc), aclGetGroup ( "Admin" )'). Expected element at argument 1, got boolean. - Line 7: attempted to concatenate a boolean value. Those errors are thrown as soon as the 30 seconds pass (25 + 5 from both warnings). The warnings are visible. I pictured that if the warnings work and the cleaning script works, joining them as such would work. Why am I getting those errors? Link to comment
_Ace Posted March 14, 2020 Share Posted March 14, 2020 variable p and acc are undefined or out of scope, because of the timer creating a function inside the function, remove the local to see if it works Link to comment
The_GTA Posted March 14, 2020 Share Posted March 14, 2020 8 hours ago, Moony said: I've got: - Bad argument at line 6 ('local acc = getPlayerAccount (p)'). Expected element at argument 1, got nil. - Bad argument at line 7 ('if not isGuestAccount (acc) and [...] then'). Expected element at argument 1, got boolean. - Bad argument at line 7 ('("user."..getAccountName (acc), aclGetGroup ( "Admin" )'). Expected element at argument 1, got boolean. - Line 7: attempted to concatenate a boolean value. Those errors are thrown as soon as the 30 seconds pass (25 + 5 from both warnings). The warnings are visible. I pictured that if the warnings work and the cleaning script works, joining them as such would work. Why am I getting those errors? Dear Moony, I assume that your script is serverside, thus the signature of a command handler function looks like: local function commandHandler(player, commandName, args...) In your script above you wrote for the Warning1 command handler: function Warning1() but you should have written... function Warning1(p) to receive the player that executed the command. I have not inspected further errors in the script so please tell us if you have further questions. 1 Link to comment
Moony Posted March 15, 2020 Author Share Posted March 15, 2020 15 hours ago, The_GTA said: Dear Moony, I assume that your script is serverside, thus the signature of a command handler function looks like: local function commandHandler(player, commandName, args...) In your script above you wrote for the Warning1 command handler: function Warning1() but you should have written... function Warning1(p) to receive the player that executed the command. I have not inspected further errors in the script so please tell us if you have further questions. I can't believe it was that easy. It works now! How did you detect it between so many things in the script? The knowledge I had seems to be incorrect. I thought that the arguments inside the parentheses next to the function name (header) didn't have an important effect, other than to set the names of the arguments. I had imagined that leaving it blank would be the same as saying "anything can go there". So why was it stopping the script from workingç? Link to comment
Scripting Moderators ds1-e Posted March 15, 2020 Scripting Moderators Share Posted March 15, 2020 3 hours ago, Moony said: How did you detect it between so many things in the script? Due of error codes, it's easy. Quote - Bad argument at line 6 ('local acc = getPlayerAccount (p)'). Expected element at argument 1, got nil. Function expects element (mostly stored in variable or as parameter), your p is nil. Quote - Bad argument at line 7 ('if not isGuestAccount (acc) and [...] then'). Expected element at argument 1, got boolean. Similar case, but this time you got boolean (false), let's check what returns getPlayerAccount: Quote Returns the player's account object, or false if the player passed to the function is invalid. Your variable p was nil, and therefore function returned false on it's failure. 1 1 Link to comment
The_GTA Posted March 15, 2020 Share Posted March 15, 2020 (edited) 6 hours ago, Moony said: How did you detect it between so many things in the script? I looked at your error log and saw that the getPlayerAccount function did receive a nil as first argument. Then after checking your script I realized that p was nil. Finally I tried to search for p in your script and could not find it's definition, thus the error. Now that the error was known, I tried to repair your script. Since I know that Warning1 is a command-handler in my experience a typical error is forgetting to allocate or misnaming the function parameters in the command-handler signature, like the player. This repair was confirmed by the getPlayerAccount function, which expects a player as first argument. 3 hours ago, majqq said: Due of error codes, it's easy. Function expects element (mostly stored in variable or as parameter), your p is nil. Similar case, but this time you got boolean (false), let's check what returns getPlayerAccount: Your variable p was nil, and therefore function returned false on it's failure. What majqq has described is very similar to what I'd do. He did check the wiki to find that getPlayerAccount returns false because the first argument was invalid. I think this is a good idea. 6 hours ago, Moony said: The knowledge I had seems to be incorrect. I thought that the arguments inside the parentheses next to the function name (header) didn't have an important effect, other than to set the names of the arguments. I had imagined that leaving it blank would be the same as saying "anything can go there". So why was it stopping the script from workingç? Obviously the "anything can go there" assumption is wrong. A command-handler has this very specific signature: void commandHandler(player, cmdName, arg1, arg2, ...) But looking at your first script where you wrote... local function loopVehicles(p) I am pretty sure that you knew that, but you still ... forgot to write it correctly for the "Warning1" function. No idea where this error came from Edited March 15, 2020 by The_GTA 1 Link to comment
Moony Posted March 15, 2020 Author Share Posted March 15, 2020 (edited) I'm certian my issue is that I'm not understanding what goes inside parentheses in the function header. Sometimes it's empty, other it's filled with arguments. This is what leaves me absolutely clueless and confused. I thought that the parentheses had to have the same arguments as the handler, which in this case is: addCommandHandler ( string commandName, function handlerFunction [, bool restricted = false, bool caseSensitive = true ] ) -- That turns into: addCommandHandler ( "cleana", Warning1 [, bool restricted = false, bool caseSensitive = true ] ) Which would leave us with a header similar to: function Warning1 (string commandName, function handlerFunction [, bool restricted = false, bool caseSensitive = true ] )) -- That turns into: function Warning1 ("cleana", Warning1 [, bool restricted = false, bool caseSensitive = true ] )) And that it serves as the same as stating the values beforehand: command = "cleana" function Warning1 (command) -- The function -- end addCommandHandler (command, Warning1) And finally, supposing that my thought process is correct, why would I need to clarify 'p' if 'p' is already being clarified in local acc = getPlayerAccount (p)? I'm struggling a bit putting these doubts into words. If you don't understand, let me know and I'll try to explain myself better. 16 hours ago, majqq said: Due of error codes, it's easy. Function expects element (mostly stored in variable or as parameter), your p is nil. Similar case, but this time you got boolean (false), let's check what returns getPlayerAccount: Your variable p was nil, and therefore function returned false on it's failure. I've seen DB 3 throw a "got boolean" at the end of the error. I noticed you mentioned "false". Does this mean that everytime DB 3 talks about boolean, it's talking about a false statement? I ask this because I learned that boolean can either be 'true' or 'false'. Edited March 15, 2020 by Moony Link to comment
Scripting Moderators ds1-e Posted March 16, 2020 Scripting Moderators Share Posted March 16, 2020 5 hours ago, Moony said: I've seen DB 3 throw a "got boolean" at the end of the error. I noticed you mentioned "false". Does this mean that everytime DB 3 talks about boolean, it's talking about a false statement? I ask this because I learned that boolean can either be 'true' or 'false'. That's correct, it's either true or false. 5 hours ago, Moony said: And finally, supposing that my thought process is correct, why would I need to clarify 'p' if 'p' is already being clarified in local acc = getPlayerAccount (p)? p isn't defined in your code. Test this piece of example code, you should understand after typing /testcmd (server-side code) function myCommand(player, cmd) outputChatBox("player: "..inspect(player).." cmd: "..inspect(cmd)) end addCommandHandler("testcmd", myCommand) 1 Link to comment
The_GTA Posted March 16, 2020 Share Posted March 16, 2020 (edited) 8 hours ago, Moony said: And finally, supposing that my thought process is correct, why would I need to clarify 'p' if 'p' is already being clarified in local acc = getPlayerAccount (p)? Because putting 'p' at the right spot into the parantheses of the command-handlers is the only way to request the player that executed said command handler. If you don't specify the p then you tell Lua that you don't care about p and then you cannot possibly expect p to be defined in any way. 8 hours ago, Moony said: I've seen DB 3 throw a "got boolean" at the end of the error. I noticed you mentioned "false". Does this mean that everytime DB 3 talks about boolean, it's talking about a false statement? I ask this because I learned that boolean can either be 'true' or 'false'. What majqq said is 100% correct. Let me clarify by adding that getPlayerAccount does never return "true", it is only possible that it returns "false" in certain conditions. And you never want it to return "false" so check the argument before calling getPlayerAccount with invalid things! Edited March 16, 2020 by The_GTA 1 Link to comment
Moony Posted March 16, 2020 Author Share Posted March 16, 2020 7 hours ago, majqq said: Test this piece of example code, you should understand after typing /testcmd (server-side code) function myCommand(player, cmd) outputChatBox("player: "..inspect(player).." cmd: "..inspect(cmd)) end addCommandHandler("testcmd", myCommand) I'm aware it should throw some kind of string result about some player. But nothing's happening. DB 3 is not throwing any errors. Out of context: It's funny how some of my replies have quotes of things I supposedly said. Link to comment
The_GTA Posted March 16, 2020 Share Posted March 16, 2020 33 minutes ago, Moony said: I'm aware it should throw some kind of string result about some player. But nothing's happening. DB 3 is not throwing any errors. No, majqq's code is perfect. He wanted to show you how it is done properly, basically what the words inside the parenthesis mean. If you look into the chatbox and compare the output to the script (line 3) you will see that "player" and "cmd" have a different string representation. Just let that sink in. If you get this right then you have possibly solved a big knot in the brain. Link to comment
Moony Posted March 29, 2020 Author Share Posted March 29, 2020 I wanted to revive this little command since I never got it to work. After tens of small changes, I got it to work. I had to use an old format from another script I had. Here's the command majqq made: function myCommand(player, cmd) outputChatBox("player: "..inspect(player).." cmd: "..inspect(cmd), source) end addCommandHandler("testcmd", myCommand) This is what I did: function msgServer () outputChatBox ("player: "..inspect(player).." cmd: "..inspect(cmd)) end addCommandHandler ("sayserver", msgServer) If I leave the function's arguments empty, it sends: "player nil cmd nil". If I put what majqq put (player, cmd), it sends: "player: elem:player[Moony] cmd: "sayserver"" Let's see if I get it right: The inspect function is inspecting the element that triggered the command, which in this case is a player, and that player's name is "Moony". As for the command, it is throwing the simple string that was used to trigger the function. On 16/03/2020 at 06:55, The_GTA said: [...] If you look into the chatbox and compare the output to the script (line 3) you will see that "player" and "cmd" have a different string representation. Just let that sink in. [...] I don't quite get the "..have a different string representation". Do you mean that the string "player" is represented as "elem:player[Moony]"? Link to comment
The_GTA Posted March 29, 2020 Share Posted March 29, 2020 6 minutes ago, Moony said: I don't quite get the "..have a different string representation". Do you mean that the string "player" is represented as "elem:player[Moony]"? Yes. If you typed /testcmd into the chat you would see that (you did). Looking at string representations of variables is a daily driver for debugging MTA:SA Lua scripts. 1 Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now