Jump to content

DiSaMe

Helpers
  • Posts

    1,447
  • Joined

  • Last visited

  • Days Won

    32

Everything posted by DiSaMe

  1. I played MTA SA in 2007 several times but because it was the non-scriptable, Race version, it didn't mean much to me. But things changed in 2008, when Deathmatch version was released. For the next several years, I spent lots of time scripting, because that was what I loved doing the most, and I don't regret it the least bit. I could perhaps have made better decisions regarding various details, but I would still have spent hours upon hours scripting either way. Joining in 2007-2008 means MTA was already in the middle of action. I miss those days, and I'm not sure how I feel about "then vs now". On one hand, seeing lots of new members makes me happy that MTA is gaining popularity that it deserves. On the other hand, it often seems to me that few people from those days are still around, that things have changed and they will never be the same again. But seeing several people senior to me posting now in this topic contradicts my usual perceptions, which is very comforting . It's great that in addition to new members coming, MTA community still has active members from the old days. I have some plans to get back into scripting, because there are things I was supposed to make many years ago, but didn't. Well, actually, I did try scripting a while ago, and it was as enjoyable as it had always been. That's when I remembered what I had been missing. This evokes nostalgia, and I don't think I have even played MTA VC
  2. The only way I can think of that I know would work is, opening and reading the model file using fileOpen/fileRead to retrieve the UV data into a table. Then drawing it with dxDrawLine or dxDrawPrimitive. In other words, your script needs to parse the DFF files, which may be quite some work if you're not familiar with DFF format - unless there's some library that does it for you, but I'm not aware of any. Plus you can't just access the original game files using file functions, there needs to be a DFF file in the resources - which may also be the reason it's all done on custom cars in that video.
  3. Maybe this has something to do with non-power-of-2 dimensions? If so, then 16x16 or 32x32 would give a better result than 20x20. I don't see an obvious reason why it would be like that, since if it can properly load the data coming from a file, it should be able to load the same data coming from a string. But it all depends on what's happening inside dxCreateTexture. I guess there might be some indirection involved, like drawing the texture to a buffer and then reading it to produce the final texture, which could degrade the quality for non-power-of-2 textures.
  4. You can use split to split the string into tokens and convert each of them to numbers. local xyz_str = guiGetText(edit_box) local xyz = split(xyz_str, ",") -- xyz is now a table of tokens if #xyz == 3 then -- check if there are exactly 3 coordinates local x, y, z = tonumber(xyz[1]), tonumber(xyz[2]), tonumber(xyz[3]) if x and y and z then -- check if each coordinate is a valid number -- code to execute if coordinates were parsed successfully else -- code to execute if not all coordinates are valid numbers end else -- code to execute if there aren't exactly 3 coordinates end This is a good start, but the space characters have to match exactly, and the numbers can only be non-negative integers. I was going to improve the pattern to allow arbitrary number of spaces, but then I remembered non-integers and negative numbers and thought it would be too much hassle to get it right. With split, we allow tonumber to take care of all number formats and space characters.
  5. You can do that in two ways. The first way is the way you worded it - damage gets disabled or enabled when a player enters or exits the vehicle. To do that, you need these events: onPlayerVehicleEnter or onVehicleEnter - to detect when a player enters the vehicle onPlayerVehicleExit or onVehicleExit - to detect when a player exits the vehicle And this function to toggle the damage: setVehicleDamageProof Also, it depends on whether it has to work just for the driver seat or all seats. If you want it for the driver seat only, then you need to check if the seat parameter is 0 in vehicle enter/exit events. If you want it for all seats, then in vehicle exit event you need to retrieve the list of players in the vehicle using getVehicleOccupants and check if it is empty - so the damage will only be enabled if there are no other players remaining in the vehicle. The second way is to check every time the vehicle is damaged, and cancel the damage if it's occupied. This has to be done client-side because only client-side damage events can be cancelled. You need this event to detect when the vehicle gets damaged: onClientVehicleDamage And call this function from within that event to cancel the damage: cancelEvent If you need it for the driver seat only, use getVehicleOccupant to check if there's a player in the seat 0. For all seats, retrieve the list of players in the vehicle using getVehicleOccupants and check if it is non-empty.
  6. It seems like you're asking two different questions here. If you want to detect actual collisions of the object (instead of just origin point of the object, which Spakye's post assumes) near the player, you could cast lines in several directions from the player and see if any of them detects an object. It may be sufficient if you just need to detect large objects (terrain, buildings), but not that reliable for smaller ones since collision checking lines are likely to miss the objects. What points do you pick for line of sight? Collisions mainly consist of boxes, spheres and meshes. For boxes and spheres (the former of which are used by some buildings), it can be objectively determined whether a point is "inside" or "outside", so perhaps if you cast some line from the object's position to some nearby point, the collision gets detected, which is why it happens to work for you with buildings. But objects of arbitrary shape use meshes, and there's no "inside" for meshes - a mesh is just a bunch of triangles put together to form a surface. When the line of sight crosses the surface, a collision is detected. A primitive solution is to use getGroundPosition or getRoofPosition to check if there's anything above the point you're checking. But it will fail if there are ceilings. Or you could choose several points on the "outside" so that at least one point would be visible from any place that is "outside". Then, whenever you want to check if some position is "outside", use processLineOfSight between that position and all of your chosen points. If at least one of them is visible from that position, that means it is "outside". This solution should be reliable, but manually choosing the visibility points beforehand means it will only work in that area. If the area you want to cover is large, that means lots of work (unless you make a script that automatically picks the points for you), plus you need to limit the number of points being checked because lots of processLineOfSight calls will be bad for performance.
  7. It's not clear from the code and other info you've given what exactly the problem is. I mean if location is meant to indicate that the character is newly created, you need to pass it to this code when the player creates a new character. How creation/selection of characters is done in your script, that's another thing, we don't know that.
  8. I'm glad that was helpful
  9. I'm not sure if I understood what your problem is because it doesn't make sense to somehow get some Z coordinate from two XY points and some angle which was used to get one of those XY points. But I'll assume this is what you're trying to achieve: you have two points, origin and target, and you want to get a third point, which is in the same direction from origin as target is, but at arbitrary distance. So you could effectively push the target towards or away from origin. Is that right? If so, then it's some basic vector math. local newDistance = 50 -- set dX, dY, dZ to offset from origin to target local dX, dY, dZ = targetX-originX, targetY-originY, targetZ-originZ -- using Pythagorean theorem, calculate the length of dX, dY, dZ vector local oldDistance = math.sqrt(dX*dX + dY*dY + dZ*dZ) -- multiply each component dX, dY, dZ by newDistance and divide by oldDistance -- so newX, newY, newZ becomes the offset from origin to your desired point local newX, newY, newZ = dX*newDistance/oldDistance, dY*newDistance/oldDistance, dZ*newDistance/oldDistance -- add origin to newX, newY, newZ newX, newY, newZ = originX+newX, originY+newY, originZ+newZ -- newX, newY, newZ now contains the coordinates we're looking for newDistance/oldDistance expression repeats 3 times so we can calculate it once, store it in a variable and reuse for each component. Also, multiplication/division line can be combined with addition line. Then we get this: local newDistance = 50 local dX, dY, dZ = targetX-originX, targetY-originY, targetZ-originZ local oldDistance = math.sqrt(dX*dX + dY*dY + dZ*dZ) local multiplier = newDistance/oldDistance local newX, newY, newZ = originX+dX*multiplier, originY+dY*multiplier, originZ+dZ*multiplier
  10. The global environment (the table holding the global variables) can be accessed using variable _G. local playerName = getPlayerName( player ) local variableName = "Timer"+playerName _G[ variableName ] = setTimer ( function() end, 1000, 0 ) However, building variable names is usually not recommended for generic manipulation of data. Instead of putting the timers into global variable space, you can create your own table specifically for timers: -- at the top of the script playerTimers = {} -- then, somewhere in the code local playerName = getPlayerName( player ) playerTimers[ playerName ] = setTimer ( function() end, 1000, 0 ) But I suspect that's still not exactly what you want to do. Should the timer be linked to player's name, or to the player? If it's linked to the player's name, then if the player changes their name during the game, playerTimes[playerName] will no longer refer to the timer created before the change. If that's not what you want, you can bypass the retrieval of the name and just use the player element directly as table key: -- at the top of the script playerTimers = {} -- then, somewhere in the code playerTimers[ player ] = setTimer ( function() end, 1000, 0 )
  11. DiSaMe

    Follow Ped

    You can make the ped perform actions using setPedControlState, with accelerate, vehicle_left and vehicle_right being the most important controls you would want to use for driving. You also need to retrieve the relative placement between ped's and player's cars, using functions such as getElementPosition and getElementRotation and some math. All these things need to be done repeatedly so that the control states would be updated as the elements move. If you also want to make the ped follow the roads (instead of going straight towards the player), then it gets more complicated because the script has to do pathfinding.
  12. You can check which seat the player occupies using getPedOccupiedVehicleSeat function. Other functions involving vehicle seats are getVehicleOccupant and getVehicleOccupants.
  13. Now the question is much clearer. You can query the information about elements using functions like getElementsByType, getElementChildren and getElementData. So if you want to create a list in the GUI that represents a list of elements (like teams or skins), you can do so using getElementsByType and looping through the list of elements and creating a GUI element for each element in the list. getElementData allows you to retrieve attributes such as team name so you can pass the result to GUI functions to have it show up in the GUI. If you use getElementData on map elements from within the client side scripts (like, during the creation of GUI), you need to have <sync_map_element_data>true</sync_map_element_data> in meta.xml of any running resource. But usually a better way to use the team data from the map is to retrieve it on the server side into a table in the beginning, then pass that data to triggerClientEvent when you want to display the spawn selection window for the player.
  14. Depends on how you define 'gamemode', because a gamemode is just another script. mapmanager and other related resources provide a standard way to do some things, but you don't have to use them - in fact, I don't remember ever doing that. I'll assume your confusion is the same as mine was a long time ago, which is getting anything to work at all, so that with the gamemode you would have a minimally playable game. There are several (per-player) things you need to do. First, a player is not physically present in the game world upon joining the server. You need to call spawnPlayer to make them appear. Also, their camera is set to some position where only the sky is visible. To make the player's camera follow the player, call setCameraTarget, passing the player element to both arguments. And last, the screen is black when you start. You have to call fadeCamera for that. That's how the player gets to run around in the game world. The rest is up to your imagination.
  15. You can do that using processLineOfSight function. You cast a ray between two points and it will return information about the surface that it hits, including the material ID.
  16. Perhaps the distinction should be drawn between what can only be controlled by scripts and what can be changed by other means. Position can change because of physics, which is why we want MTA to sync it, but control states cannot be changed by anything but scripts. If the script fully controls them anyway, it makes sense to let it take care of making them consistent. Also, there would be a benefit in syncing some other things besides position (assuming they're not synced already), such as whether the ped is knocked down. It's another thing related to physics that can make a big difference.
  17. Well, that clears it up. I thought there was a possibility that it was changed, but I wasn't thinking of it as something that's supposed to be changed. I would argue that making our own data to describe tasks and using it on all clients independently can give better results than having MTA sync the peds' actions, because high level actions allow more accurate predictions than low level ones. Think "follow a particular element" versus "accelerate and steer right". The former can give acceptable results with much longer sync intervals because the latter will usually become obsolete quickly. This is in contrast to player sync, where primitive actions are the highest level actions we have, which I guess makes player sync a more complicated subject than ped sync.
  18. But my question was, are ped actions resulting from setPedControlState, setPedAimTarget and several other functions even synced? It's understandable that setPedEnterVehicle needs to be synced, because it directly involves other elements. But setPedControlState directly involves just the ped, so is it still synced? If it is, then you're right about why using isElementSyncer would be necessary, but if it's not, then ped state will be inconsistent between clients either way, and all clients should control the ped to make it more consistent, otherwise, as I said, the ped will appear to teleport around while standing still, to everyone but the syncer.
  19. I'm a bit late to the party, but... Shouldn't the client side part of controlling be done on all clients? In other words, are peds' actions synced? I don't know how much it has changed since I last scripted peds, but I was under the impression that it's just placement and velocity that are synced, but actions are not - in which case every client, not just the syncer, should set the control states and other control-related parameters, otherwise non-syncers will see the ped changing position but not actually performing any actions.
  20. Oh, okay. It was the wording that confused me
  21. Yes, peds are more popular than they used to be, it's just that I was expecting them to be even more popular. Not that I have any particular plans to return to scripting, but it's a possibility. I love these videos! I might have gotten some things right, but my goal was to make ped scripting easy so that even beginners could do it. Didn't come close enough because I only implemented very basic tasks. Was thinking of implementing pathfinding but never did. Analyzing how the game does it may help getting the peds behave the way they do in original game, but I'm not a fan of this approach. Reimplementing original behavior wouldn't be satisfying enough, I always wanted peds to perform complex tasks regardless of how the game does it. I'm not sure if I understood what you're saying. I mean I didn't do anything special regarding that. But you're making it sound like I did something that I didn't actually do. When I was playing around with nodes from original game, I found that there were many redundant nodes (or so it looked). But I created my own paths in the end (which is what I created npchlc_traffic_editor for), and obviously, I wouldn't create nodes that I find redundant. So Rockstar created more nodes in their paths than I created in mine. That's it. If I remember correctly, it's just a vector that tells lane position relative to the node position. When you drag while creating a node in the editor, that's when you set RX and RY.
  22. You're right. But I already could tell there was something wrong with the code even then. Which is why I always considered it an unresolved matter from the beginning. Never stopped thinking it would be nice to make a better ped system. You could say it's not pressure, but motivation. In addition, by making the resource I wanted to demonstrate that ped scripting is not really that hard, and encourage more people to try it, hoping that after a while we would have more ped/traffic resources. That didn't come true to the extent that I was hoping
  23. Wow, I'm very happy to see my scripts are still relevant, thanks! But it can be a negative thing as well, I mean it wasn't supposed to end up this way, back then I tried to improve the script, then I tried to make a new, a more advanced ped system from scratch but didn't have enough time, and to make things even worse, the code I wrote then looks horrible to me now So happy to feel appreciated, yet the fact that everyone's focused on my work that still wasn't satisfying enough to myself, gives me this unpleasant feeling that I gotta clean up this mess, gotta finish the work I once started but I don't know when I'm going to try scripting on MTA again Conversion of game paths to my path format sounds interesting, but making my own paths instead of converting the ones from the game was the reason I came up with my format and traffic editor to begin with. I was having trouble understanding some things in the game's format, and the paths have things like multiple nodes in a straight line, which needlessly uses more data. Now, to the documentation details. node_conns tells the connection ID from node IDs. That is, node_conns[node1_id][node2_id] = connection_id. Also, node coordinates are decimal fixed-point numbers, not floats, and RX/RY each takes 2 bytes as opposed to 4. Reading the value as integer and dividing it by 1000, you get the actual value. I had some problems converting between bytes and floats, and integers were faster to process. Finally, traffic lights. The value 3: "PED" means red for all cars, and that's when the peds cross the road. Normally it would work according to pedestrian traffic lights, but as far as I know, those are neither synced, nor scriptable - at least they weren't when I made the resource.
  24. DiSaMe

    Money Hack

    Money limit is 999 999 999 in GTA SA. 10 times more than you're checking against.
  25. DiSaMe

    Money Hack

    I agree. I was expecting it to be easy even without the code because there are few ways for cheaters to falsify the variable values. Turns out I thought wrong.
×
×
  • Create New...