• Content Count

  • Joined

  • Last visited

Community Reputation

104 Excellent


About MrTasty

  • Rank
    Road Dawg


  • Location
    United Kingdom
  • Occupation
    Scripting Guru

Recent Profile Visitors

2,889 profile views
  1. Individual clients don't have a peer-to-peer connection between each other, so you have to run everything via the server. When a client wants to send a message, relay it through the server via triggerServerEvent and then triggerClientEvent to all clients (with a single call). Anyway, if you're going to do something like that, as a kind of optimization, you may as well just have the /say handler on the serverside instead of the client if all the client does is send it to the server. If you want to play sounds/info2.mp3 when localPlayer uses /say you could just play the sound via chat->NewMessage if source == localPlayer
  2. I'd suggest to not collect debug log for every client, as that will very quickly fill up with irrelevant logs as well as duplicates per every client if an error comes up for all players for example. It would be best to either limit it to collecting debug log from a very small sample of people, or keep on every client a buffer of the last x lines of debug, and send it over if they make a bug/glitch report or something.
  3. MrTasty

    db. update

    triggerServerEvent( "savem9cko", getLocalPlayer(), m9cko) -- line 8 Sends the value of the variable m9cko (which is the text of the editbox) as the 1st parameter of the event savem9cko.
  4. MrTasty

    db. update

    On the client side: guiGetText triggerServerEvent On the server side: addEvent addEventHandler dbExec
  5. MrTasty

    Check BD

    Depending on whether you're using an external MySQL, local SQLite database or built-in SQLite registry.db. For the first two, you need to create a connection via dbConnect. The last one only requires the use of executeSQLQuery. You'll need to do all of it on the server side, using events to send the nickname from the GUI to the server. The query string is pretty much the same between MySQL and SQLite: SELECT [columns1, column2, ...] FROM [table] WHERE [column1] = ? AND [column2] = ? So if you want to check for a nickname being registered, you'll want to do something like this: -- for external MySQL or local SQLite dbQuery( function(queryHandle) -- callback func local result = dbPoll(queryHandle, 0) if #result >= 1 then -- record with such nickname exists else -- no record for this nickname end end, dbConnection, "SELECT nicknane FROM accounts WHERE nickname = ? LIMIT 1", strPlayerNickname ) -- for internal registry.db local result = executeSQLQuery(dbConnection, "SELECT nickname FROM accounts WHERE nickname = ? LIMIT 1", strPlayerNickname) if #result >= 1 then -- record with such nickname exists else -- no record for this nickname end The '?' are used for parameter binding, which is the easiest and probably the safest way to prevent SQL injection. I only select 'nickname' as we don't need any extra information. "LIMIT 1" prevents the SQL server from looking for more that one record, since that already falsifies the proposition that there is no record with that nickname. Note: I am not sure if the given code works out of the box -- not tested. I haven't scripted on MTA for a while and I am unsure of the exact structure of the SQL query return. You might need to do some debugging with iprints if it doesn't work.
  6. MrTasty


    It's quite hard to understand your problem. Is the problem that you don't have a MySQL server or that you don't know it's address/hostname? If you don't have one, you'll need to set one up. If you have a VPS or some other hosting, this should be pretty easy, especially with things like cPanel, and you can always Google around if you're not sure. If your hosting is MTA server-only, then you'll probably want to either find a rentable MySQL database, or migrate to a VPS or something where you can run more than just an MTA server.
  7. MrTasty

    xml vs json

    In which scope does it appear as nil? Right after loading it or later on somewhere else? I have a feeling this is about scope of variables: you load the data into a local variable which means it's only accessible in that same scope/block/function you're working in. Have you tried adding a debug output for 'loadedData' right after fromJSON'ing it?
  8. This is because is on the default whitelist. Clients must give permission to open addresses, so you need to requestBrowserDomains (as you have correctly done). However, you should use the callback argument in that function (or "onClientBrowserWhitelistChange" event) to know that the user gave permission and only then attempt to load the page. Trying to load it before permission has been granted won't load it.
  9. MrTasty

    Local voice chat

    I've just released a 3D proximity based voice chat resource which I had sitting on my disk being unused. Initially wanted to wait until MTA's voice system is updated to Opus and voice volumes are fixed as they're extremely quiet still.
  10. This is line 150: elseif ( #exports.DENmysql:query( "SELECT * FROM accounts WHERE serial = ?", getPlayerSerial( source ) ) >= 2 ) then The problem is simple. The query exports.DENmysql:query( "SELECT * FROM accounts WHERE serial = ?", getPlayerSerial(source)) failed and returned a boolean instead of a table, thus the # (length operator) raised an error. P.S. Use code blocks next time. It's very unhelpful to share code without line numbers. Also, you should provide more info as well. Saying "need help" isn't going to attract people willing to help. Also, share only relevant lines of the code, please? It's annoying to have to scroll through 400 lines of code when we're just interested in 1 line.
  11. Yeah. If the browser is local, it's local only, and cannot communicate with the internet on it's own. This is because local browsers enable extended JavaScript functionality, namely, calling events etc. in MTA. If this was allowed, a malicious website would be able call events and exploit client-sided code, perhaps even the server-side integration of it. Browsers that can communicate with the internet, have that functionality disabled for that reason. Technically you could get around this by loading the contents through fetchRemote and injecting that into a local browser, but as mentioned above, this would be very difficult to get images and anything else that loads in a separate request unless you parse the fetch's return as a browser would and make those additional requests through fetchRemote too. This would likely also be a lot slower than a non-local browser.
  12. A lot of issues in the serverside code. VehicleHit is a function defined within a function, which, while legal, doesn't make sense unless you're making a local function. VehicleHit is called by a timer started outside the qm function, meaning that qm must be called (via hitting a marker) within 1000 ms of starting the serverside code. Additionally, the timer does not send over any special parameters but your VehicleHit function expects a hitElement parameter and checks that it's a player element. You're sending a nil. qd event is only declared but never actually used. qd2 and qd4 aren't even declared on the serverside.
  13. addEventHandler("onClientConsole", localPlayer, function (text) local args = split(text, " ") -- split the text by spaces local command = table.remove(args, 1) -- remove the first word from the args table and put it into the "command" variable outputConsole(command) end ) This should work, but I haven't tested it. This is clientside code by the way. You can use onConsole on the server but I believe that won't trigger for commands handled by a command handler.
  14. Then you probably just want to do setWeaponProperty(32, "pro", "flags", 0x000800) -- toggle 'can use 2x guns at same time' flag -- or setWeaponProperty(32, "pro", "flag_type_dual", false) -- turn off flag_type_dual (I've never used this method, can't attest as to whether it works)
  15. setWeaponProperty(30, "poor", "flags", 0x000002) -- toggle 'only needs arm to aim' setWeaponProperty(30, "poor", "flags", 0x000800) -- toggle 'can use 2x guns at same time' -- etc. You need to use the numbers from to toggle them between on and off. If you want to know if it's on, use function isWeaponFlagSet(weapon, skill, flagBit) return bitAnd(getWeaponProperty(weapon, skill, "flags"), flagBit) ~= 0 -- collects the current weapon bitflags, filters them using a bitwise And operation to only retain bits of flagBit, and checks if it's not 0 end or if you prefer, you can use this function to explicitly enable or disable rather than switch flipping current state -- Set or clear an individual weapon flag bit function setWeaponPropertyFlag( weapon, skill, flagBit, bSet ) local bIsSet = bitAnd( getWeaponProperty(weapon, skill, "flags"), flagBit ) ~= 0 if bIsSet ~= bSet then setWeaponProperty(weapon, skill, "flags", flagBit) end end -- from setWeaponProperty wiki example