Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 04/04/21 in all areas

  1. I don't know why I even have to point this out since this is something I figured out automatically in my early days of MTA scripting. But it seems necessary because I see people using Lua tables but not taking advantage of their flexibility. Very brief overview of tables as arrays Anyway, Lua tables are often used as arrays - that is, data structures that store values under consecutive integer keys starting at 1 (0 in most other languages, but that's another story), making a sequence. Various functions that operate on tables, including those in table namespace, treat them as arrays. Take this example: local fruits = {} table.insert(fruits, "apple") table.insert(fruits, "banana") table.insert(fruits, "lemon") table.insert(fruits, "orange") It creates an empty table, then uses table.insert to insert values. Because table.insert treats the table as an array and because it inserts at the end of the sequence if position argument is omitted, we end up with values "apple", "banana", "lemon" and "orange" values under keys 1, 2, 3 and 4 respectively. Using index operator [], you can retrieve the associated value from the key: -- assuming standalone Lua, using print -- replace with outputChatBox or another output function if running in MTA print(fruits[1]) -- outputs: apple print(fruits[2]) -- outputs: banana print(fruits[3]) -- outputs: lemon print(fruits[4]) -- outputs: orange Tables as sets However, table keys don't have to be integers. You can use any value except nil and nan. Strings, other tables, MTA elements. Therefore, if the order of values is irrelevant and the values are unique, instead of inserting the value under some key, you can use that value itself as the key. And set the associated value to true: local fruits = {} fruits["apple"] = true fruits["banana"] = true fruits["lemon"] = true fruits["orange"] = true Now we have a table with keys "apple", "banana", "lemon" and "orange", while the associated value true is only used to indicate the presence of key and nothing else. That effectively makes the table a set, a collection of unique values with no particular order. Usage and comparison Insertion So we have two different ways to insert values: -- array table.insert(fruits, "apple") -- set fruits["apple"] = true This alone doesn't say much. Both operations are simple and take a roughly constant amount of time to execute. However, it makes other operations very different. Removal Because arrays require you to know the key to remove the value, you have to loop through the array to find it. In contrast, with sets you can just assign nil (because nil is the value for unassigned fields): -- array function removeFromArray(array, value) for i, v in ipairs(array) do if v == value then table.remove(array, i) end end end removeFromArray(fruits, "banana") -- set fruits["banana"] = nil Arrays are very inefficient for this if there is a large number of values, because the more values there are in total, the longer the removal of a single value will take - whereas removing from the set will take more or less the same. Checking if exists Checking for presence of a value is a lot like removal, you need to know where the value is, so arrays require looping. With sets, you just retrieve the associated value. If the checked value exists, the associated value will be true, otherwise it will be nil. -- array function existsInArray(array, value) for i, v in ipairs(array) do if v == value then return true end end return false end if existsInArray(fruits, "lemon") then print("found") else print("not found") end -- set if fruits["lemon"] then print("found") else print("not found") end Arrays are again inefficient in the same way. Looping Looping is roughly the same, but as far as I know, Lua tables are optimized to be used as arrays, so I guess looping may be a little faster for arrays than sets. I have never checked this myself. -- array for key, value in ipairs(fruits) do print("found value: "..value) end -- set for value in pairs(fruits) do print("found value: "..value) end Notice that ipairs is used for the array and pairs is used for the set. pairs will work for the array as well, but the order will be unspecified. ipairs is meant to be used on arrays, it starts at index 1 and increments until no value is found. Size retrieval Lua has length operator #, which returns the array length when used on tables. But there is no built-in operator or function to retrieve the total number of fields in a table, so it takes more to get the size of a set. -- array local count = #fruits print("fruit count: "..count) -- set function getSetSize(set) local count = 0 for value in pairs(set) do count = count+1 end return count end local count = getSetSize(fruits) print("fruit count: "..count) This makes size retrieval much more efficient for arrays than sets because the more values the set has, the longer it takes to loop through them. That's speaking of sets in their simplest form though. You can have a structure like this: local fruits = { count = 0, values = {} } And modify the count every time a value is inserted or removed. Then you can retrieve the size simply by reading fruits.count, which is efficient. But then other operations have to be altered too so we're not getting into this here. Checking if empty Checking if a collection is empty means checking if its size is 0. For arrays, nothing changes, but for sets it can be done efficiently. -- array if #fruits == 0 then print("array is empty") else print("array is not empty") end -- set if next(fruits) == nil then print("set is empty") else print("set is not empty") end next is a Lua function for traversing the table. It's used by pairs too, called once for each pair. But here we call next directly. Its first returned value is one of the keys in the table, or nil if no key is found. Conclusion For some of the most common operations, sets are both more efficient and simpler to operate on than arrays. In its simplest form, it loses against array in size retrieval, but you can keep track of size separately. When you want to store unique values and their order is unimportant, using tables as sets is probably the right choice. Syntax summary: tbl = {} -- insertion tbl[value] = true -- removal tbl[value] = nil -- checking if exists if tbl[value] then end -- looping for value in pairs(tbl) do end -- checking if empty if next(tbl) == nil then end
    2 points
  2. Hey folks So, I joined this community back in 2008, when MTA SA DM DP1 was released. It was great. I played in servers. I scripted stuff. The scripting part is especially important here, because I was amazed to see what possibilities to customize the game MTA SA gives to the scripters, and that's what got me involved so much. It was by scripting on MTA that I got lots of coding experience. I had such a great time that 2008 was one of the most memorable years for me, because I can still remember the good moments, including my first time playing the non-race version (I played MTA SA Race in 2007, but only a little bit, and didn't think much of it) and my first attempts to script. As time went by, I set goals for myself. I thought of making my own server with my own gamemode. I didn't just want it for my own gains, I wanted it for the good of MTA, too! I wanted to make use of MTA scripting possibilities, to let the greatness of MTA be known! However, as I still wasn't that good at scripting nor at setting goals (they were huge), I wasn't exactly being productive. I experimented a lot and learned a lot, but apart from that, it didn't really go anywhere. After a few years of playing around, I realized my goals weren't going to come true. I decided I just wanted to be useful to MTA community. That's when I made and released a few scripts, including Drawtag, Gravity gun and NPC traffic. Later I made my own server after all, with a gamemode very different from what I had originally planned. But I was too busy with crap in my life to continue working on it, so I had to end it. I didn't want to abandon MTA. All those dreams that never came true. But I didn't see any other way. I stopped playing and scripting on MTA. Eventually I drifted away and stopped visiting this forum altogether. During the time I was away, I was just living life, but not really feeling like I was enjoying it. There were ups and downs. You know, everyone goes through different phases of life. But now I feel bad about it. It wasn't necessarily my fault that I left, but it was my fault that I didn't come back for so long. Now that I finally did, it seems there have been people who were looking for me, but I don't even know if it's of any use to reply to messages I received 3 to 5 years ago. I'm regularly on YouTube though, but even there, often I didn't feel like replying to comments right away and forgot about them later. I'm feeling like a busta who ran away and left his homies when there was no reason to. I'm feeling like I have betrayed MTA because it gave me so much, but I didn't manage to benefit it as much as I thought it deserved. Things have surely changed around here while I was gone. I see there are admins and moderators who weren't even on this forum when I left. And honestly, I don't remember many people in particular. I don't remember well who was and who wasn't here back in those days. I don't know if anyone here misses me. I'm so out of touch. Kinda sucks, doesn't it? After wandering for years, I'm finally back home, but I'm not even sure if it's still the same home that I've been missing because I don't even know if people here are still the same people that I left. But I see some usernames that look familiar and I can take comfort in that. MTA seems to be doing much better than before. I didn't expect it to become so popular! I'm supposed to be happy about this, because it was my dream to see MTA achieve the popularity that it deserves. But it feels like yet another thing I missed out on. I wasn't a part of MTA community during the time that it grew so much. What a shame. Unfortunately, I don't have plans to resume MTA scripting, not big ones at least. It's a pity, seeing how MTA now has scripting features that I used to dream of. But I just don't think I currently can focus on it. Still, it feels tempting to try. I'm curious, how much have peds been improved? In the old days, I would run into problems because the peds would lose information about health, ammo and many other things, when they got streamed out, so I couldn't have them properly synced and had to resort to workarounds. What about model/texture replacing? I see there are some new related functions, so this functionality must have been improved, right? I remember trying to import Liberty City and Vice City back in 2010, and I managed to convert Liberty City, but I couldn't load it all at once, because 512 MB of RAM was not enough to replace that many models at the same time. And replacing the models dynamically (based on distance to the player) wasn't working well, there were bugs and some models weren't actually getting replaced. My scripts website is no longer there. I still have the files, but I see someone made a GitHub repository and uploaded the resources there, so I guess it's okay as it is. The resources are available to everyone and I'm thankful for that. If I ever decided to make scripts for the community to use, I would start from scratch rather than continue working on the old ones. The same can be said about the server I had, I have the gamemode and the database, but if I wanted to run a server again, I would start the gamemode all over. While the future of my involvement in MTA scripting is uncertain, I'm seeking to be active on this forum once again. I want to be in touch with MTA and the community. Maybe I should try helping people in scripting section or something like that. Perhaps make some tutorial. I'm much better at programming than I used to be. I'm working on my own game engine, but I don't want to make it sound like I'm doing something big or anything like that. This is another thing that I took my time to play around with. I started it long ago, I learned a lot, but I have little results. Either way, it was MTA that inspired me to do it. And I have an idea to make a common scripting interface for MTA and my engine so that scripts made using this interface would work on both. Not stating that's what's going to happen, I'm just thinking of ways to make scripts for MTA even when I have to focus on something else. With things I learned in the recent years, some MTA script ideas that I once considered difficult to implement, look much easier now. Hell, even if I made the mistake of leaving MTA for so long, these years were still far from wasted. That's pretty much all I wanted to say for now. I left for several years, now I feel bad about it, "but now I'm back, and I know what I've been missing". Not sure how much I'm going to be involved in MTA scripting, if at all, but I just want to be a part of this community again.
    1 point
  3. Unfortunately handling doesn't affect helicopters to increase speed, it's some sort of GTA limitation.. maybe it can be fixed in MTA some day
    1 point
  4. I can offer my candidacy, I have been playing for 410 hours, I know the server well, the administrator knows me UndecomingMedic9
    1 point
×
×
  • Create New...