Jump to content

Addlibs

Members
  • Posts

    1,060
  • Joined

  • Last visited

  • Days Won

    9

Everything posted by Addlibs

  1. Can you provide a screenshot/video of what your code currently produces, and an annotated screenshot of what you want to achieve? I tried running the code you provided to get an idea of what you're trying to do but the code is incomplete, lacks the definition of the render target (i.e. its size is missing), uses non-standard drawing functions, etc. I don't understand the use of string.len(core) here. String length = number of characters, which suggests horizontal scrolling but the positions scrolled indicate vertical scrolling. I also don't understand the variables used (please, name your variables, it makes helping so much easier): what are x2, y2, z1, z2?
  2. Because the code uses get, credentials should be in the meta.xml like so: <settings> <setting name="hostname" value="" /> <setting name="username" value="" /> <setting name="password" value="" /> <setting name="database" value="" /> <setting name="port" value="" /> </settings> Now onto the code problem: mysql_connect is not a built-in MTA function, but rather a server module which you need to install to be able to use that function. Most modules today are quite deprecated because most of their functionality can be found built-in into MTA, for example, mysql_connect can be replaced with dbConnect. Indeed, all of the mysql_* functions in the code you provide can be replaced with appropriate db* functions. If you choose not to rewrite the code, you can try to install the module, https://wiki.multitheftauto.com/wiki/Modules/MTA-MySQL, but be aware, it was last updated in 2012. It is really old and may not even work anymore with the latest versions of MTA.
  3. Setting their initial velocity appears to work mostly, however, missiles gain speed very quickly on their own, try spawning one with 0 initial velocity, to a speed between 0.5 to 2 greater than target speed - I've tested with the target aircraft at default max speed of 1.5, the missiles follow with just around 2.8 speed. If the target aircraft is at speed 3, missiles follow it with velocity of up to 4.5. If you want to target a missile at a particular location, you can, as you said yourself, calculate that from two positions: local initialPosition = Vector3(0, 0, 0) local targetPosition = Vector(300, 300, 0) local differenceVector = targetPosition-initialPosition local directionVector = differenceVector.normalized local missileInitialSpeed = 1 local missileDirectionVector = directionVector * missileInitialSpeed You do not necessarily need any callbacks, you can change any element's velocity at any point. If you want to implement your own guidance system, you can adjust missile positions on the client side every frame, every 2 frames, etc. with onClientRender and either a loop of all missiles, a loop of missiles in a table, or just selecting a particular missile with single variable. Projectiles can also store element data if necessary.
  4. The wiki's arguments list suggests setControlState only works on players, not any ped. Have you tried setPedControlState client-side? You can trigger it by firing off an event from the server that's handled on the client side. This may need a lot of synchronisation code though, as a client won't receive this event when connecting after the resource was started, nor if the resource starts and triggers onResourceStart before the client side is ready.
  5. Addlibs

    Brodcast Error

    Likely caused by the line if not (Team.isInTeam(target)) then return false end The two options you have is to either return an empty table, or to verify the return value of getTeamPlayers when putting it as an argument to setPlayerVoiceBroadcastTo, ensuring it is indeed a table before passing it.
  6. This is because you're explicitly checking if row 1's status column is equal to 2, rather than making this check per-row. If you want it per row, you need to iterate over each returned record like so for i = 1, #checkpedingQuery do local row = checkpedingQuery[i] if row.status == 2 then -- or row["status"] (this is entirely equivalent, just different syntax, but the second one lets you plug a variable in there instead of a static string, the first version only works with static compile-time -- i.e. when the script loads -- strings) iprint(row) end end -- or for index, row in pairs(checkpedingQuery) do if row.status == 2 then -- same remark as above iprint(row) end end
  7. guiCreateButton is a persistent button - it creates a button element, not renders a button for a frame -- you should never call it in onClientRender except in if-statements which you know will only execute once when necessary (i.e. not every frame, and only if the previously created button was destroyed). Setting elementd to false in your code merely stops creating new buttons -- it does not delete the previously created buttons (yes, buttons, plural. You're creating hundreds of buttons every couple seconds depending on the FPS of the client). This code event = guiCreateButton(16, 20, 250, 40, "Take", false) addEventHandler ( "onClientGUIClick", event, Tokens ) and this code function eventshows () if elementd == false then dxDrawImage(500*sW, 120*sH, 370*sW, 470*sH, "img/event.png", 0, 0, 0, tocolor(255, 255, 255, 255), true) end end addEventHandler ( "onClientRender", getRootElement(), eventshows ) should generally never exist in the same function
  8. A sizable chunk of ACL rights are function rights-- these rights only matter for resources, as player cannot invoke functions directly. All these functions are documented on the wiki on pages named after them. For players, commands rights are the main way to control access. Each command in the list is implemented either in MTA or in a resource. The MTA commands are outlined in Server Commands on the wiki. The remaining commands are from resources, such as admin (the default admin panel). In the case of the admin panel, command rights also control the enabled/disabled state of GUI buttons corresponding to those commands, i.e. the Ban button is not clickable if the user has no right to command.ban. There are some additional ACL rights such as general rights, these may control things like access to particular functionality of a resource, e.g. general.tab_resources controls the access to the Resources tab of the admin panel. For the rights related to particular resources, you need to check if the resource has documentation of these commands, or infer the purpose from the code.
  9. Unable to enter You cannot enter the vehicles, because they are client-side only vehicles -- as it says on the reference wiki, "Note: Vehicles (and other elements) created client-side are only seen by the client that created them, aren't synced and players cannot enter them. They are essentially for display only." To solve this, you need to spawn the vehicles on the server side, preferably with the parent ID as the model, then send information to all clients (and remember the vehicle's model for newer clients connecting later on) that the client-side model ID needs to be changed, and setElementModel client-side over that vehicle. The easiest way to do this is with element data: setElementData on the server, onClientElementDataChange and onClientElementStreamIn with getElementData on the client. Models not changing You seem to be allocating a new model ID every time you want to spawn a vehicle, rather than reusing an ID which has been assigned a modded DFF and TXD. To solve this, you should be using engineRequestModel in the same function you load the mods, that is, where engineImportTXD and engineReplaceModel are. For example, -- vehicles = { -- ["txd_and_dff_name_with_ext"] = {parentID = 429, dynamicID = nil --[[ this entry gets filled at runtime ]]} -- } function allocateAndSkinVehicles() -- renamed function to better reflect its new purpose local txd, dff; for id,vehicle in pairs(vehicles) do if fileExists("vehicles/" .. id .. ".txd") and fileExists("vehicles/" .. id .. ".dff") then local modelid = engineRequestModel("vehicle", vehicle.parentID) -- request a new ID for this vehicle txd = engineLoadTXD("vehicles/" .. id .. ".txd") engineImportTXD(txd, id) dff = engineLoadDFF("vehicles/" .. id .. ".dff") engineImportDFF(dff, id) outputChatBox("Model ID "..id.." changed correctly.") vehicle.dynamicID = id -- save the allocated ID to the vehicle's entry else outputChatBox("Model ID "..id.." couldn't change. REASON: vehicles/".. id ..".txd or vehicles/".. id ..".dff does not exist.") end end end addEventHandler("onClientResourceStart", resourceRoot, allocateAndSkinVehicles, false) -- changed triggering to happen on resource start This way, when the server tells you to change a vehicle's client-side model, either by element data or though events, you need to look up vehicles[customID].dynamicID to get the actual allocated model ID with the particular modification on the vehicle. Note this implementation allows you to use strings for customID, doesn't have to be a number; all it requires is there are .txd and .dff files with that exact name in the ./vehicles directory.
  10. Reference site also mentions that this function is client-only, with the big red "Client-side function" text on the top-right of the page. This means you cannot use this function in a server-side script. "global.lua" is, I assume, both client and server: the server's debug log is telling you that this function is not defined (i.e. is a nil value).
  11. engineRequestModel of type "vehicle" with parent ID 481. This function returns to you an newly allocated ID which you can use with engineReplaceModel and engineImportTXD. However, these IDs do not work server side at all, and are not synchronized across clients either. Client 1's ID for mod 1 may be 100, while Client 2 refers to that same mod as 106. You will need to track these IDs by linking them with something like a model name, perhaps the .dff file's name/path. Server spawns the parent model, sets element data like "model" to "my/mods/mod1.dff". Clients listen for onClientElementStreamIn and onClientElementDataChange to detect this spawn, check if the model's already allocated and assigned, if so, setElementModel clientside to the custom ID for this particular client, else, allocate model, load dffs and txds, setElementModel clientside to newly allocated ID and save the newly allocated ID with the model's dff name/path so subsequently it can be discovered without loading again. Or you could load all anticipated models early, onClientResourceStart. If you strictly control resource loading order and each resource's custom replaces, you can reasonably predict which mod will have which ID, but again, this isn't guaranteed in any way -- maybe it works now but in the future it won't, so don't assume the loading order.
  12. You need to spawnPlayer and fadeCamera on onPlayerJoin.
  13. Don't use getPlayerName (this takes a player element as input and returns a string) but rather getPlayerFromName (this takes a string as input and returns a player element). Note that you will need to add extra code to handle the player connecting and disconnecting, as the player element will change when a client reconnects.
  14. One of the parameters of the dgs mouse click event: In other words, the equivalent of onClientGUIClick is onDgsMouseClickUp, not onDgsMouseClick. The latter is indeed triggered for every mouse button activity (for the press and for the release) while the cursor is over the element. CEGUI click is registered when you release the mouse button while over the element, giving the user an option to cancel a misclick by holding the mouse button, dragging the cursor off the element and releasing.
  15. In that case, you should double check you're not calling showConfirmDelete twice; you can either inspect / show your code for that, or you could add an outputDebugString call at the beginning of the function to see how many times its output. You could use outputDebugString(debug.traceback()) to get information on where exactly the function was called from. If it's being called from a function that handles an event, perhaps the event is triggered multiple times, once per player, perhaps.
  16. The reason one of the copies don't work is because you check if the click event's source is the element in the table buttons and override the values in that table when creating a duplicate copy. If you want both windows to work properly, you should avoid the if source == [some element] then and instead add a false argument after the handler function in addEventHandler. For example addEventHandler("onDgsMouseClick", buttons[11], function() triggerServerEvent("vehlib:deleteVehicle", localPlayer, id) closeConfirmDelete() playSuccess() end, false) That false means the function should not be called for any element other than the element the event is bound to, button[11] at the time the handler was attached; the binding does not change if you later change what buttons[11] references.
  17. When incrementing the attempts counter, check if it just surpassed 10 (that is, it was below 10 before the increment and is now equal or greater than 10), and if so, either start a timer for 24 hours to clear the lock, or store the current timestamp + 86400 sec, and ensure the next time the user attempts to do the same thing, the current timestamp is greater or equal to the previously stored timestamp (of course all of this, per IP). Something like this: local attempts = {} local lockouts = {} function isIPLockedOut(ip) -- check if the lockout needs to be cleared if (lockouts[ip]) then -- if ip was locked out before if (lockouts[ip] < getRealTime().timestamp) then -- if lockout timestamp hasn't been reached return true else -- if lockout timestamp is in the past, lockouts[ip] = nil -- clear the lockout and continue the function attempts[ip] = 0 -- clear the attempts count end end local offenseCount = attempts[ip] or 0 if (offenseCount >= 10) then return true -- if count is above 10, return true end return false -- otherwise return false end function incrementOffenseCount(ip) local offenseCount = attempts[ip] or 0 -- default to 0 offenses if not set if (offenseCount >= limit) then -- if limit exceeded lockouts[ip] = getRealTime().timestamp + 86400 -- lockout for 24h else -- otherwise attempts[ip] = offenseCount + 1 -- increment offense count end end -- example usage function attemptLogin(player, username, password) local ip = getPlayerIP(player) if isIPLockedOut(ip) then local seconds = lockouts[ip] - getRealTime().timestamp local hours = math.floor((seconds%86400)/3600) local mins = math.floor((seconds%3600)/60) outputChatBox(string.format("You've attempted this action too many times. Your IP is blocked for %dh %02dm.", hours, mins), player, 255, 0, 0) else if getAccount(username, password) then logIn(player, username, password) else incrementOffenseCount(ip) -- only call this within a conditional block on isIPLockedOut(ip) == false outputChatBox("Wrong username or password", player, 255, 0, 0) end end end For the above provided code, make sure you only ever call incrementOffenseCount if isIPLockedOut returned false, otherwise you'll be resetting the lockout timer.
  18. You could use getRealTime to get the current timestamp, calculate the seconds remaining until the next scheduled time point (which you can calculate with getTimestamp), and setTimer for the many milliseconds.
  19. It's also important to note the server script usually starts before the client script is ready (especially when the client needs to download the scripts and files), meaning an client-bound event dispatched on onResourceStart can turn up ignored for not being added client-side (as the client script isn't running yet). Best way to correct that is have the client send an event to the server when it is ready (i.e. when the resource starts client-side, after all necessary downloads -- onClientResourceStart), and the server's event handler for that event to triggerClientEvent back.
  20. You cannot directly send an SMS using MTA. However, you can use fetchRemote to communicate with external web APIs such as SMS texting services. These services are typically not free, however. You can send emails with one-time passcodes for free if you already have an HTTP server, using PHP's mail() function for example, or a full SMTP server if you have one. These would be triggered by making a request to a particular webpage/server (that is, fetching/requesting the remote page), which can be done though the aforementioned fetchRemote function.
  21. Every onClientGUIClick event handler's attachment needs propagate set to false: addEventHandler("onClientGUIClick", theButton, function() -- ... end, false -- add a false after the function's end (4th argument of addEventHandler) ) Otherwise the event is attached to the given element's/button's element tree, meaning the event being triggered on any child element or parent element will trigger the handler, which is not what you want with GUIs. The other workaround is, in each function, adding an if-block with condition checking the event's source (this isn't the most efficient though, since the function will still be called unnecessarily, just that it won't do anything. addEventHandler("onClientGUIClick", theButton, function() if source == theButton then -- verify the event's source is the button you attached this function to -- do whatever the function does end end)
  22. if vehType == "Automobile" or "Monster Truck" or "Quad" or "Bike" then evaluates as true because "Monster Truck" evaluates true because meaning it isn't false or nil, "Quad" and "Bike" are likewise evaluated as such. What you probably intended was if vehType == "Automobile" or vehType == "Monster Truck" or vehType == "Quad" or vehType == "Bike" then
  23. Can you also check your mta/logs/clientscript.log file for warnings or errors in your script at the time of crash? Changing getRootElement() to root is mostly a stylistic change, doesn't really impact the functionality of the code at all, except saving you a couple calls. Regarding this code, this code contains a potential vulnerability: Seems like source and player are referring to the same thing? Perhaps it'd be best to assert (i.e. assert(source == player, "Source and player mismatch") -- this will print out the second argument in the debug box if the first argument's evaluation is false) that they are equal, or only use one of these variables. It seems like whoever triggers this event can cause a player's to be teleported but not receive the createCharacter event, perhaps by mistake in your code or by a hacked client sending off maliciously crafted events with a source mismatching the player argument. Regarding your initial issue: Is the createCharacter event triggered anywhere else, and how is the event responsible for callCharacterCreation triggered? A minor correction to my previous statement: I actually tested this and it turns out I was slightly wrong - addEventHandler does not let you register the same function with the same event multiple times, but if its attempted, it prints an error in the debug box (and log), so your render function probably not being called multiple times per frame as I've suggested previously.
  24. How is createCharacter triggered? I think I might see the problem. Do you have a lot of elements spawned (vehicles, peds, objects, etc. even if they're out of the streaming range)? It seems your handler function for createCharacter is attached to the root element and all its children. If you trigger it on the root element, rather than, for example, the target's player element, then what actually happens is the same event is dispatched on each element with the given element as its source, and your handler is attached to be called on any child of root, in other words, your handler gets executed as many times as there are elements. In other words, if you have n elements in the element tree, your handler attaches an new event handler for onClientRender n times! Your createCharacterPanel function gets called n times per frame, or 60n times for a client running 60 fps. A quick fix would be to one of the following: change the triggerClientEvent calls everywhere to use the target player as source (since players rarely have any child elements, the event gets dispatched only once per trigger) (likely the best option here), OR add the fourth argument to addEventHandler for createCharacter set to false, to make the handler only get called for the root element and not its children (less preferable; however you should add that to the onClientRender handler attachment regardless), and/or add an if check in the handler to verify that source == getRootElement() (least preferable option as it means your function still gets called tens or hundreds of times only to exit early when you could avoid calling it at all in those circumstances) Doing options 1 and option 2 and/or 3 at the same time will break functionality, as you'll call with a player as source but the function will expect root and only root, disallowing its children (and the player is a child element of root)
  25. By crash do you mean the MTA client crashes, or are you saying your script "crashes" (i.e. stops working?) If it's an MTA client crash, perhaps you're doing something you're not supposed to be doing in the onClientRender handler function. Apart of dx calls, what other functions do you call within createCharacterPanel? Any create* functions in there? All create* functions outlast a frame and its possible you're spawning so many of them you cause a crash due to loading/streaming, or run out of memory. Perhaps its the setCameraMatrix? Does your client ever crash when suddenly streaming in a different part of the map? Does it happen on different computers or only for you?
×
×
  • Create New...