Jump to content

Investor

Members
  • Posts

    111
  • Joined

  • Last visited

Everything posted by Investor

  1. You're going to need to have the resource bone_attach installed and running on your server.
  2. The easy but inefficient way would be to use element data to sync the list of visible/hidden components. However it is preferable to use events: Have the server authoritatively control which components are visible and which aren't, by sending an event to all clients (or all clients within streaming proximity) regarding any changes in component visibility; and have the server also track these details to send the visiblities data to players connecting afterwards (or entering streaming range).
  3. giveWeapon is server-only. CEF can only trigger to client. You need to bridge the client to the server using a server-event. Taking money from the player should also happen on the server, but you probably shouldn't trust the client to tell the server the price, instead the server should look up the price for a given item independently, in a table stored on the server side. Additionally getPlayerMoney(getRootElement()) should be getPlayerMoney() with no parameters.
  4. The skill value is looked up in the SQL table weaponstats. Since you're already accounting for all the weapon skills possible, let's hypothetically say you want to add stamina stat to this. What you'd do is add a new column in the weaponstats SQL table called "stamina", and then edit this script's skills table by adding [22] = "stamina". The actual value for that stat will be in the SQL table. E.g. owner ak47 m4 ... stamina 23 1000 1000 ... 560 35 600 500 ... 600 So for player with charID 23, the poll[1]["stamina"] will be 560, for poll[1]["m4"] it will be 1000. For charID 35, these will be 600 and 500 respectively. When originally recommending that code, I didn't realise that all the skills were already added, which means you probably won't be adding or removing anything from it, but at least it's still a cleaner code design.
  5. You should show us the code which handles closing whatever it is that disappears forever. Perhaps it uses destroyElement where is should use guiSetVisible.
  6. local skills = { --[skillID] = columnName [77] = "ak47", [78] = "m4", [69] = "pistol", [70] = "silencedpistol", [71] = "deagle", [72] = "shotgun", [73] = "sawnoff", [74] = "spas", [76] = "mp5", [79] = "sniper", } local owner = charID dbQuery( function(qh) local poll = dbPoll(qh,0) local row = poll[1] if not row then return false end -- don't continue if poll[1] is empty (no rows found in weaponstats for this owner) for skillID, columnName in pairs(skills) do -- iterate the table defined above whose key-value pairs are [skill ID] = table column name setPedStat(player, skillID, row[columnName]) end end, {},connection,"SELECT * FROM weaponstats WHERE owner=? LIMIT 1", owner ) This is a little cleaner and more maintainable design. If you add more columns in your weaponstats db-table, all you have to do is update the skills table.
  7. dbQuery(function(qh) local poll = dbPoll(qh,0) for _,v in ipairs(poll) do local ak47 = v["ak47"] -- first of all, this is defined locally to this scope only so it doesn't exist outside the anonymous function(qh) end owner = 1 -- this definition seems very out of place. It should come before dbQuery as it's used in it's parameters end,{},connection,"SELECT * FROM weaponstats WHERE owner=?",owner) setPedStat(player, 77, ak47) -- this executes right after dbQuery but before the dbQuery's callback function, hence ak47 is not defined The solution could look something like this local owner = 1 dbQuery( function(qh) local poll = dbPoll(qh,0) for _,v in ipairs(poll) do -- if the poll result only has one row, it would be better to use local ak47 = poll[1]["ak47"] instead of this loop local ak47 = v["ak47"] setPedStat(player, 77, ak47) end end, {},connection,"SELECT * FROM weaponstats WHERE owner=?",owner)
  8. Presumably you have a line that goes something like this local itemsTableState = getElementType(unknown_variable) well, you need to add local clickedElementModel = getElementModel(unknown_variable) and then elseif itemsTableState == "object" then if clickedElementModel == 2332 then -- if the element model is a safe tabStartX = drawCategoryTab(tabStartX, tabStartY, "main", "safe", "Safe") end end But you haven't provided enough lines for me to know what is the name of the variable storing the clicked element, so I've named it unknown_variable here.
  9. Investor

    Time

    If you mean how many hours have passed since a player was last online, all you have to do is store a timestamp when he quits or logs out (via setAccountData perhaps) and compare that to the current timestamp to get the number of seconds passed, from which you can easily calculate the number of hours.
  10. doesn't seem to appear in the provided script, which could mean encoding problems. Anyway, while checking the code I also found it to contain a couple U+FEFF characters (ZERO WIDTH NO-BREAK SPACE). The bytes 0xFEFF are apparently also used by UTF-8 for BOM (Byte Order Mark) which could be part of encoding issues, perhaps. Best would be to simply filter out invisible and special characters which shouldn't be there.
  11. The difference is that only a player can issue a command, though an event's source could be any element type. This is why the wiki uses 'player' for command source variable, but you're free to use whatever name you want.
  12. Wrong section I think. Modelling would be more appropriate.
  13. dutyAllow[key] is a nil value (doesn't exist). You probably wanted dutyAllow[k]
  14. XML is only useful for configurations which you want to be able to change through a normal text editor, but even for that case, JSON is probably faster and easier. SQL is best for pretty much anything else.
  15. Could be related to issue 634 as its solution changed some stuff regarding question marks within a query.
  16. What kind of client function do you need? Client functions mostly require a client because it doesn't make sense to run them unless there is a game client with rendering. There may exist workarounds on the server side for certain functions (such as isElementOnScreen is possible to calculate on the server given a camera position, rotation, fov, clipping start and clipping end, etc.), while others are impossible without a full client (such as collecting a dxScreenSource screenshot) and nonsensical (e.g. drawing dx, CEGUI etc without a client to look at it).
  17. bool isPedOnGround ( ped thePed ) float getGroundPosition ( float x, float y, float z ) getGroundPosition is client-side only and requires the world to be streamed in at that position at the time of calling the function, but if the player is above it it should be loaded.
  18. Sound isn't working because you expect music_select to be 1 to play a sound but it's never defined, so it's nil, not 1. function Ativador_Musica(Musica_Selecionada) setElementData ( localPlayer, "Mensagem", "Sim ") setTimer ( function() setElementData ( localPlayer, "Mensagem", "true" ) end, 14000, 1 ) if music_select == 1 then -- where is music_select defined? did you mean Musica_Selecionada? Musica = playSound ( "sounds/lvl.mp3" ) end end addEvent( "PlaySound", true ) addEventHandler( "PlaySound", root, start_music )
  19. A workaround to this is forcefully cutting the line with a ZWSP (zero-width space), which is an invisible character that allows word-wrappers to break apart a line at a more convenient position. Since there's no other breaking characters in a long line of text like that one, you'll probably want to insert a ZWSP right after each punctuation sign. Ultimately, the fix must come from MTA or CEGUI developers, to make the word-wrap break after punctuation signs (that would make sense, right?). function addZWSP(str) return string.gsub(str, "%p", function(x) return x..utfChar(0x200D) end) -- replace all punctuation signs (%p) with itself followed by UTF character 0x200D (ZWSP) end This will allow the word-wrapper to break after any punctuation sign, for example, question marks.
  20. Investor

    shader issue

    float gTime : TIME; float scrollSpeed = 1.0; float3x3 getTextureTransform() { float posU = -fmod((gTime/20)*scrollSpeed,1); float posV = 0; return float3x3( 0, 1, 0, 1, 0, 0, posU, posV, 1 ); } technique tec0 { pass P0 { TextureTransform[0] = getTextureTransform (); TextureTransformFlags[0] = Count2; } } Try this (no guarantee it'll work, I'm not a shader coder). Also, this will probably look glitchy if you continuously change the speed - you should set it only once and not change it once it's scrolling or it may jump forward or back instantaneously. The parameter you need to set with dxSetShaderValue is "scrollSpeed".
  21. The first question basically depends on whether your players will tolerate lag (hint: GUI is supposed to be responsive). If it's something like GUI, it's best to update it on the client as if it was received by the server but set a timer to revert the GUI to server-state unless you hear back an acknowledgement event from the server (i.e. that the operation was executed without error) (don't unconditionally accept any sync event, in addition to any procedural checks (making sure the data is in valid format, etc) and so on, always safeguard and send back a kind of not-acceptable acknowledgement event when the event isn't accepted by the server for, among other, anti-cheat purposes). For stuff which could give an unfair advantage or other bonuses/cheats like godmode, it would definitely be better to run the request by the server and back before any client changes are actually shown. Instead of instant change, you could show a spinning progress icon until you hear an acknowledgement event from the server (i.e. that the operation was executed without error) Higher ping will make GUIs seem less responsive if you run it by the server before actually making changes visible. Additionally, make sure to saveguard the server from accepting illegitimate sync events, so clients can't change their--or others'--data on a whim. Refreshing GUI for players in same colshape would be best done on client receive sync packet, individually per player if possible, or refresh the whole list when one player's data changes.
  22. dxDraws aren't element so they cannot emit events. As mentioned above, the closest thing you can use is onClientClient, and manually check if the client cursor X and Y are within the bounds of the dxDrawImage. That or use a dxgui API like dgs which already have that coded.
  23. toJSON and fromJSON should work perfectly fine as long as you don't put elements and non-element userdata, which it seems you don't do. What do you mean by "it returns nil"? The triggering of the event returns nil? or it delivers a nil on the client side? Perhaps try sending it over as JSON still and fromJSON it on the client side.
  24. You could perhaps do a hash check. Get the SHA256 (or MD5 but it's not considered secure nowadays) hash of the decrypted data and compare it against the hash that you know it should be, and only if they match proceed to engineLoadDFF/engineLoadTXD. E.g. local dffFile = fileOpen("files/"..file_dff) local dffData = fileRead(dffFile, fileGetSize(dffFile)) dffData = base64Decode(teaDecode(dffData, file_key)) fileClose(dffFile) local txdFile = fileOpen("files/"..file_txd) local txdData = fileRead(txdFile, fileGetSize(txdFile)) txdData = base64Dec if hash("sha256", dffData) ~= "enter_the_SHA256_hash_that_the_dff_data_should_have" then return false end -- abort function if hashes mismatch after decryption if hash("sha256", txdData) ~= "enter_the_SHA256_hash_that_the_txd_data_should_have" then return false end -- ditto -- ... local dff = engineLoadDFF(dffData) -- in case of incorrect key, shows warning here local txd = engineLoadTXD(txdData) -- and here. (bad path)
×
×
  • Create New...