Jump to content

IIYAMA

Moderators
  • Posts

    5,972
  • Joined

  • Last visited

  • Days Won

    191

Everything posted by IIYAMA

  1. IIYAMA

    Console

    You can inspect resource usage with the performancebrowser: http://SERVER_IP:HTTP_PORT/performancebrowser/ (It will ask you to login with your ingame admin account) Might be, it also depends what is spammed. For example a command (attached to a synced database query) can be more impactful than just a chat message.
  2. I tested your code and it works fine. But keep in mind that in your current setup it is used as an auto complete feature. Typing `Jo` makes auto complete John available. Also when you press your arrow-down key, it should act more as the options tag as @FLUSHBICEPS referring to.
  3. When loading code, you are putting a kind of chunk/function around it. So basically this: function(player) return getPlayerName(player) == 'owner' end Looks more or less like this: -- pcall(loadstringed) is calling this chunk/function: function () function(player) return getPlayerName(player) == 'owner' end end So in order to solve this: return function(player) return getPlayerName(player) == 'owner' end local success, theFunc = pcall(loadstringed) local success2, isOwner = pcall(theFunc, testPlayer) See also xpcall for better error handling: https://www.gammon.com.au/scripts/doc.php?lua=xpcall
  4. The generic answer is, you need to create a resource that serves as manager > and rewrite each gamemode, so that their usage can be scoped(data/elements/events) for specific players. Best is to get inspiration from an already existing Multi Game Mode resource. Since this is really a lot of work and complexity. Explaining the process from A to B would take too much of my time (sorry).
  5. Try this: triggerClientEvent ( (function () local players = getElementsByType("player") for i=1, #players do if players[i] == source then table.remove(players, i) break end end return players end)(), -- IIFE (Immediately Invoked Function Expression) "runOurClientEvent", root )
  6. When the resource starts a new resourceRoot element will be created. This element is destroyed when the resource stops. It is therefore not a good idea to attach eventHandlers to the resourceRoot's of other resources. (Unless you keep track of start/stop resources) In your current example you mentioned the eventName onPlayerFirstSpawn. The player makes it's first spawn. From a semantic perspective, the player is therefore the one activating the event. And I expect it therefore to be used as the source of that event. The element above a player is the root element and should be used for the eventHandler of that event. The root element is not deleted when restarting resources. But never the less, here is how to solve the resource validation issue: addEventHandler("<eventName>", root, function () local resource = getResourceFromName( "<resourceName>" ) if not resource then return end if source == getResourceRootElement(resource) then -- The source is from the correct resource end end) Another way to keep the resource start up in order is to use the tag: <include resource="resourceName"/> https://wiki.multitheftauto.com/wiki/Resources
  7. Looks nice! Just some side notes, feel free to ignore those. I recommend not do these kind of animations serverside. You are basically sending data to the client/player every 20 milliseconds, which might causing network trouble on a not local server. Just set the end-value serverside. And trigger an even clientside + do the animation there. Also the GTA default money animation can be displayed with setPlayerMoney (unless of course you want to use a custom transition): https://wiki.multitheftauto.com/wiki/SetPlayerMoney
  8. Try this one instead: https://wiki.multitheftauto.com/wiki/GetPedTargetEnd Note: The returned values can be nil.
  9. I understand that you want to do the calculations your self. But if you are using a matrix, you really do not have to think about all that complex and brain exploding stuff. https://wiki.multitheftauto.com/wiki/Matrix local x, y, z, rx, ry, rz x, y, z = getElementPosition(getPedOccupiedVehicle(source)) rx, ry, rz = getElementRotation(getPedOccupiedVehicle(source)) local vehicleMatrix = Matrix ( Vector3(x, y, z), Vector3(rx, ry, rz) ) local offsetX, offsetY, offsetZ = 0, 0, 0 local newPosition = vehicleMatrix:transformPosition ( Vector3(offsetX, offsetY, offsetZ) ) SpawnedObject = createObject(987, newPosition.x, newPosition.y, newPosition.z) setElementRotation(SpawnedObject, rx, ry, rz, "ZYX") Note: You can do all of this with less lines.
  10. Just a note. Instead of doing a source validation. -- The source for this event is always 'resourceRoot' if source ~= resourceRoot then reportNaughtyness( eventName, client, "source" ) return end You can also disable propagate: addEvent("onRaiseTheRoof", true) addEventHandler("onRaiseTheRoof", resourceRoot, function(arg1, arg2) end, false -- < disable propagate ) While it does not report naughtiness, it is very easy to add.
  11. It is called a Wrapper function. It is used to add extra functionality too an existing function. For example the setElementPosition function. It's syntax is now: --[[ Syntax: setElementPosition ( element theElement, float x, float y, float z [, bool warp = true ] ) -- https://wiki.multitheftauto.com/wiki/SetElementPosition ]] All arguments except for warp are required. An example wrapper function: local _setElementPosition = setElementPosition -- Re-define original function (so that it is still accessible) function setElementPosition (element, x, y, z, warp) -- Overwrite the existing setElementPosition with your wrapper function (it is overwritten, because the function name is the same) if not x then x = 0 end if not y then y = 0 end if not z then z = 0 end return _setElementPosition(element, x, y, z, warp) -- calling the original function end The x, y, z parameters do not have to be filled in any more. They are by default set to 0. The new syntax would be now: --[[ Syntax: setElementPosition ( element theElement, [ float x = 0 ], [ float y = 0 ], [ float z = 0] [, bool warp = true ] ) -- https://wiki.multitheftauto.com/wiki/SetElementPosition ]] Is this wrapper function useful? Not really. ?
  12. Change isMapVisible() to isPlayerMapVisible(). https://wiki.multitheftauto.com/wiki/IsPlayerMapVisible isMapVisible is an OOP method. Used like this (if OOP is enabled): localPlayer:isMapVisible()
  13. Just a side note (you probably already know this: this can be the same as source, but it doesn't have to be. For example here: local myButton = createButton(0.5, 0.5, 0.1, 0.1, "Click me!", true) addEventHandler("onClientGUIClick", resourceRoot, function() outputChatBox("Button clicked!") end) this is always resourceRoot While source in this set-up is always a GUI element of this resource. For @Xwaw See image below, is the element tree, where you can see some of the main parent elements in MTA. root at the very top is the parent for ALL elements within your game: This includes players, resources(resourceRoot's) > maps/'scripted created elements' and everything that hangs directly under those. resourceRoot is the main parent of each resource. Which can be used to listen to events created by elements that are part of a specific resource. Info: https://wiki.multitheftauto.com/wiki/Element_tree
  14. @JeViCo Just wondering if cutting the process in smaller parts would give you the same effect (you never know): local width, height = dxGetPixelsSize ( rawData ) local rawDataTex = dxCreateTexture(width, height) dxSetTexturePixels (rawDataTex, rawData)
  15. While the admin acl does have this privilege, that doesn't mean that the resource is a part of it. Instead of giving admin a right that it already has. Add the resource to the admin group. <group name="Admin"> <!-- <<< --> <object name="resource.FILL_IN_THE_RESOURCE_FOLDER_NAME"></object> </group> Note: <group> and <acl> are two different tags. <group name="Admin"> <object name=""></object> <!-- user.<accountName> or resource.<resourceName> --> <acl name="Admin"></acl> <!-- ACL rights linked to this group --> </group> <acl name="Admin"> <right name="" access="false"></right> </acl>
  16. There is a difference in /refresh and /refreshall /refresh Refresh resource list to find new resources /refreshall Refresh resources and restart any changed resources https://wiki.multitheftauto.com/wiki/Server_Commands#refresh Maybe you did /refresh and not /refreshall?
  17. According to wiki: setWaterLevel ( 100, -- level, true, -- [ bool includeWaterFeatures = true, true, -- bool includeWaterElements = true, true, -- bool includeWorldSea = true, true, -- bool includeOutsideWorldSea = false ] )
  18. You could add a return here: https://gitlab.com/IIYAMA12/draw-distance/-/blob/master/scripts/main_c.lua#L156 If the map does not match your list.
  19. I believe the error is about: $input = mta::getInput(); + use MultiTheftAuto\Sdk\Mta; mta > Mta use MultiTheftAuto\Sdk\Mta; $input = Mta::getInput();
  20. There are some methods to speed up rendering, but that is only going to work if you can modify the content. https://developer.mozilla.org/en-US/docs/Web/CSS/text-rendering https://developer.mozilla.org/en-US/docs/Web/CSS/image-rendering https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering
  21. That is indeed the case. Syntax: bool triggerClientEvent ( [ table/element sendTo = getRootElement(), ] string name, element sourceElement [, arguments... ] ) Optional argument sendTo is not filled in, therefore it will send to all. To fix that: triggerClientEvent(source, "Emoji5:activarEfecto", root, source ) triggerClientEvent(source, "Emoji5:activarEfecto", root ) triggerClientEvent(source, "Emoji5:activarEfecto", source ) -- or for better performance
  22. This resource basically increases the draw distance for all objects. If you want to increase FPS, you have to make compromises which elements you want to skip. At this line you can add a condition or ask someone to create one for you: https://gitlab.com/IIYAMA12/draw-distance/-/blob/master/scripts/main_c.lua#L53
  23. A dead coroutine means that this: local SCAN_WORLD = coroutine.create(function() end) function has ended it's execution in some way. Either by an error or just running until the very end. I recommend to start the next async call just before the yield. This will eliminate the problems of resuming dead coroutines. So: STREET_LIGHTS.SCAN_TIMER = setTimer(resumeScan, 1000, 0) addEventHandler("onClientResourceStart", resourceRoot, function() if not isTimer(STREET_LIGHTS.SCAN_TIMER) then STREET_LIGHTS.SCAN_TIMER = setTimer(resumeScan, 1000, 1) end return true end) Run the code for X amount of time and start the resume timer there: (see a version of your current method below) local MAX_EXECUTION_INTERVAL = 3 -- ms local maxExecutionTime = 0 -- inside of the loop if getTickCount() > maxExecutionTime then STREET_LIGHTS.SCAN_TIMER = setTimer(resumeScan, 1000, 1) coroutine.yield() end You might consider balance the STREET_LIGHTS.SCAN_TIMER timer out with the max execution time. function resumeScan() maxExecutionTime = getTickCount() + MAX_EXECUTION_INTERVAL return coroutine.resume(SCAN_WORLD) end ---> math.abs(x) % 100 == 100 This will never be true 100 % 100 = 0 99 % 100 = 99 101 % 100 = 1 500 % 100 = 0 You might consider using 0 math.abs(x) % 100 == 0 if math.abs(x) % 100 == 0 then SCAN.current.x = x print"yield" STREET_LIGHTS.SCAN_TIMER = setTimer(resumeScan, 1000, 1) coroutine.yield() end
  24. A coroutine is a kind of thread type, which you can use to put a function to a temporary stop. The coroutine.create method requires a function and returns the coroutine. local co co = coroutine.create(function () end) The coroutine.yield method stops the thread, when it is called inside of the function. local co co = coroutine.create(function () coroutine.yield() end) To start a coroutine you can must call the method coroutine.resume, the first argument has to be the coroutine. local co co = coroutine.create(function () print("A") coroutine.yield() print("B") end) coroutine.resume(co) -- print A -- but does NOT print B To resume the coroutine after yield, just call coroutine.resume again. local co co = coroutine.create(function () coroutine.yield() print("B") end) coroutine.resume(co) -- start -- coroutine.yield() coroutine.resume(co) -- print B Add an async function of any kind (timer) and you are ready to go. local co co = coroutine.create(function () print("A") coroutine.yield() print("B") end) coroutine.resume(co) -- print A setTimer(function () coroutine.resume(co) -- print B end, 5000, 1)
×
×
  • Create New...