-
Posts
696 -
Joined
-
Last visited
-
Days Won
3
Everything posted by Dzsozi (h03)
-
How I could check (or prevent)lag/bad optimization
Dzsozi (h03) replied to Cronoss's topic in Scripting
The second function has a problem returning the occupied vehicle, I don't know if that could be the cause of the problem you are having, or is that just a typo while you were writing the examples on forum. function toggleLights(playerSource, cmd) local vehicle = getPedOccupiedVehicle(playerSource) -- use playerSource instead of thePlayer, thePlayer is not defined so this will return an error and toggling lights won't happen if (vehicle) then Yes, this would cause lag and lots of unnecessary data flow. You don't have to get a mysql result everytime you lock/start a vehicle. If I were doing toggleLock and toggleEngine functions for vehicles, I would just simply use them when a player types a command / presses a key, as you are doing, inside those toggleLock and toggleEngine functions simply use setVehicleLocked and setVehicleEngineState like function toggleLock(vehicle, state) if not vehicle then return false end setVehicleLocked(vehicle, state) return true end For the command you would do function lockCommand(player, command) local vehicle = getPedOccupiedVehicle(player) if vehicle then toggleLock(vehicle, not isVehicleLocked(vehicle)) end end addCommandHandler("lockveh", lockCommand) Keep the actual toggle functions seperate from the command functions, that way it will be easier for you to see, utilize and use those functions later as well. Then have a different save resource or function to save the data to mysql. You can make a timer every 5 seconds to call the saving, and inside the save function you would get every desired vehicle and their state of engine and locks to update mysql data with the new ones. This would make data usage and network flow much more less in my opinion, other than calling for mysql everytime a player types a command; imagine if they start spamming. Of course you can make anti-spam checks, but overall that way would be much more inefficient. Also there is a resource that you can use to check the usage of resources: performancebrowser - Multi Theft Auto: Wiki I believe it is already included in default MTA resources. -
Try muzzle_texture* instead of muzzle_texture4 engineApplyShaderToWorldTexture(theTechnique, "muzzle_texture*")
-
Possibility to create functioning ladders, create a ladder without the custom object, for default world ladders, or create a brand new one. Only vertical ladders are supported with Z rotation. Features one custom object. Easy to use functions, ~240 lines of code. Sprint button for fast climbing Jump button for jumping off a ladder Forward button for climbing up Backward button for climbing down You can basically create any length ladder with correct positions, since you can adjust offsets for start and end positions, so shifting leadders in the ground is a possibility to match the height of a building. Ladder is using collision tuboids for player detection. Contains a "/getladderpos" utility command to get the corrected position and rotation in front of player, copies Vector3 and int rotation to clipboard. Power of creating more interesting maps, possibility and an idea for a new "ladder parkour" gamemode, or just create more interesting roleplay / deathmatch / other scenarios by adding climbable ladders to the environment. I am planning to add custom animations, these default ones are good for now, and default world ladder positions in the future. I'm waiting for your feedback, let me know if you like it and/or have any suggestions!
-
Getting an error even after using loadstring()
Dzsozi (h03) replied to Dzsozi (h03)'s topic in Scripting
Thank you again! I will try to make and implement it! Really appreciate your time, have a nice day! -
Getting an error even after using loadstring()
Dzsozi (h03) replied to Dzsozi (h03)'s topic in Scripting
Finally, thank you so much!! This is what I was looking for, I just couldn't figure out how to implement it, I already knew in my mind that I will have to make 2 tables for this. For some reason I thought I can make the 'update' and 'destroy' functions in the same table as the 'new' function, turns out I can't if I want to avoid bad things to happen. Now I have this setup at the beginning and it works fine as intended local Highlight = {} --Highlight.__index = Highlight -- I DONT THINK I WILL NEED THIS ANYMORE setmetatable(Highlight, {__call = function(_,...) return Highlight:new(...) end}) -- calling Highlight will call the Highlight:new method local HighlightConstructor = {} HighlightConstructor.__index = HighlightConstructor -- I NEED THIS INSTEAD playerHighlight.style returns given style, playerHighlight.new or playerHighlight:new doesn't work like I wanted to. Yes, I knew that, thank you for giving a heads up! I changed it from . to : because you did it that way as well in your response, I am not sure tho what difference it makes in this case. I mean it should make no difference right here, if I am correct, since I am not using self inside the Highlight:new method. Anyways thank you once again! I learned new stuff and I am happy for that, also I can finally finish this resource xd EDIT: By the way, can I get rid of CREATED_HIGHLIGHTS and make it part of Highlight table? Will it work with a Highlight = {created = {}} setup or something like this? Or should I just keep them seperate? Since I was thinking about making methods like Highlight.getAllByElementType and such so I can get every created highlight of vehicles for example. -
Sending table data to shader array problem
Dzsozi (h03) replied to Dzsozi (h03)'s topic in Scripting
I am still in need of help about sending different Vector3 values to an array inside HLSL, then reading those different Vector3 values in HLSL. -
Getting an error even after using loadstring()
Dzsozi (h03) replied to Dzsozi (h03)'s topic in Scripting
For more explanation, please read the comments I made in the scripts as well; I am sorry, but I don't really understand how should I change my code. Could you please provide me a solution for this? So I have a Highlight table, each time this table gets called, a new Highlight is being created for the given element variable (I would like to make it function like the default MTA OOP stuff, like Vehicle(model, position) instead of Vehicle.new(model, position), so I have this setup here: local CREATED_HIGHLIGHTS = {} local Highlight = {} Highlight.__index = Highlight setmetatable(Highlight, {__call = function(_,...) return Highlight.new(...) end}) function Highlight.new(element, style, color, flashSpeed, intensityOrThickness) if not isElement(element) then return false end if CREATED_HIGHLIGHTS[element] then return false end local data = setmetatable({}, Highlight) -- this has something else to do with it I guess -- set variables -- data.element = element -- and so on return data end And I have methods for it like Highlight:update() and Highlight:destroy(), the way I did it for example: function Highlight:destroy() if not CREATED_HIGHLIGHTS[self.element] then return false end if self.shader then self.shader:destroy() end CREATED_HIGHLIGHTS[self.element] = nil return true end When I create a new highlight for the localPlayer, like: local playerHighlight = Highlight(localPlayer, "outline", {255,0,0,255}, 0, 1) Now everything works fine above, highlight gets created, I can access the data with playerHighlight.thickness and such, BUT I can then use the playerHighlight table (which should contain only data, like style, thickness etc) to create a new highlight on a totally different element like: local dumpster = Object(1337, localPlayer.position + Vector3(0,3,1)) print(playerHighlight.new(dumpster, "fresnel", {100,200,255,255}, 2, 0.5)) -- returns table, I don't want to use .new here -- how can I make it return nil, or avoid calling of .new, but keep the :update() and :destroy() methods -- I would like playerHighlight to contain only the data given before Now I understand that the data table inherits from Highlight table at the Highlight.new function, so to the data table the methods get passed as well, but how should I change it so it won't inherit all the functions, I would like to access actual data and only methods with colon (:update, :destroy), not with dot (.new) . So my guess is that this line should be changed to something else instead of Highlight, I imagine local data = setmetatable({}, Highlight) -- change Highlight to what? Am I missing the creation of another table? Sorry if it looks like I am asking the same question twice, I am not ignoring your reply but I don't understand your explanation @IIYAMA, I mean I don't understand how should I implement it in this case. -
Getting an error even after using loadstring()
Dzsozi (h03) replied to Dzsozi (h03)'s topic in Scripting
UPDATE: I got rid of the loadstring()() injection concept for this Class.lua script because it looks unnecessary, I will just make classes independently in resources because it is almost the same effort to do right now for what I would like to achieve, so I just changed local Highlight = {} --instead of Class() -- Highlight:new to Highlight.new, and inside the .new function local data = setmetatable({}, {__index = Highlight}) However, I can still call .new function in the testing section with -- testing local playerHighlight = Highlight(localPlayer, "fresnel", {0,255,0,255}, 0, 1) -- creating new Highlight class for player local dumpster = Object(1337, localPlayer.position) playerHighlight.new(dumpster) -- [[ I DON'T WANT TO DO THIS :/ ]] -
Getting an error even after using loadstring()
Dzsozi (h03) replied to Dzsozi (h03)'s topic in Scripting
That's how I did it in the first place, but I came up with an easier, and imo clenaer looking injector for lua files, this is how I did it: ooplib/Class.lua (however, if I make Class = {} a local variable, I get Attempt to call global 'Class' nil value error, I am curious why?) Class = {} Class.__index = Class setmetatable(Class, {__call = function( _,... ) return Class.new(...) end }) function Class.new(properties) local self = setmetatable(properties or {}, Class) return self end ooplib/infuse.lua function getFileContent(filePath) if not filePath then return false end if not fileExists(filePath) then error("Can't open '"..filePath.."' (file doesn't exist)", 2) return false end local f = fileOpen(filePath, true) local content = f:read(f.size) f:close() return content end function classTemplate() return getFileContent("Class.lua") end otherresource/testscript.lua loadstring(exports["sa_ooplib"]:classTemplate())() -- inject the Class.lua file's content local Highlight = Class() -- call the Class function from the injected script Highlight.__index = Highlight setmetatable(Highlight, {__call = function(_,...) return Highlight:new(...) end}) -- making this so I can call Highlight() function Highlight:new(element, style, color, flashSpeed, intensityOrThickness) -- create a Highlight class local data = setmetatable({}, {__index = self}) -- COULD BE A PROBLEM HERE? Change self to what? Or is it okay like this? -- set variables data.element = element -- and so on return data end -- testing local playerHighlight = Highlight(localPlayer, "fresnel", {0,255,0,255}, 0, 1) setTimer(function() local dumpster = Object(1337, localPlayer.position) playerHighlight:new(dumpster) -- [[ I DON'T WANT TO DO THIS :/ ]] end, 2000, 1) But as you look at the testscript.lua script, I commented a line which I have new problems with. I can call the :new method from the returned playerHighlight data. How can I avoid doing that? Now I imagine that I would have to change the __index from self to something else? local data = setmetatable({}, {__index = self}) Am I missing steps on setting up the Class.lua script? -
engineSetModelLODDistance setFogDistance setFarClipDistance Combining these functions should do the trick if you are trying to make the view distance higher. In some cases using setFarClipDistance should be enough. Also there are setVehiclesLODDistance and setPedsLODDistance Take a good look on these functions' wiki pages, high values for some of these could cause fps lag. Some of these functions' maximum values are also locked to a certain value.
-
Getting an error even after using loadstring()
Dzsozi (h03) replied to Dzsozi (h03)'s topic in Scripting
UPDATE: I think I found the cause of the problem; if I make the Class table a global variable instead of a local variable, the script works, debugscript outputs 'xd' from testscript.lua as intended. But wouldn't the loadstring function make the script look basically like this? --[[ after using loadstring(createClass())() I imagine the script would have local Class = {} Class.__index = Class setmetatable(Class, {__call = function( _,... ) return Class.new(...) end }) function Class.new() local self = setmetatable({}, Class) return self end at the beginning, after that comes the part down below | | V ]] local testClass = Class() testClass.name = "xd" function testClass:getName() return self.name end print(testClass:getName()) So I don't understand why making the 'Class' table as a local variable would be a problem. Is it because the type is defined as 'shared' in the meta, that's why I should make it a global variable?? UPDATE: I changed Class.lua type from 'shared' to 'server' to match testscript.lua type, made Class a local table again, and I got the error again, so I don't understand really why it should be a global variable. Anyways, the fix was changing function createClass() return [[ local Class = {} Class.__index = Class setmetatable(Class, {__call = function( _,... ) return Class.new(...) end }) function Class.new() local self = setmetatable({}, Class) return self end ]] end to function createClass() return [[ Class = {} Class.__index = Class setmetatable(Class, {__call = function( _,... ) return Class.new(...) end }) function Class.new() local self = setmetatable({}, Class) return self end ]] end in case if you need this for your scripts. I would still appreciate if somebody could answer my questions regarding that problem! -
Hello! Lately I've been trying to make every script in OOP for simplicity. Since you have to define metatables and setup classes and methods for OOP to work properly, I tried to make an export function for it so I can create classes more easily. But when I was trying to do that and test it, I get an error message, which says: And I don't really understand the reason why. What am I doing wrong? Right now I have 2 lua files, one of which contains the class creation, which is the following: Class.lua (set to 'shared' type in meta) function createClass() return [[ local Class = {} Class.__index = Class setmetatable(Class, {__call = function( _,... ) return Class.new(...) end }) function Class.new() local self = setmetatable({}, Class) return self end ]] end and I have a test script, which is in the same resource, just a different lua file: testscript.lua (set to 'server' type in meta) loadstring(createClass())() local testClass = Class() testClass.name = "xd" function testClass:getName() return self.name end print(testClass:getName()) As you can see I am using loadstring() function to infuse the class creation to the testscript.lua, but despite the fact I still get an error about Class() function being nil, why? Also, I have the Class.lua (which is set as 'shared') before anything else in the meta, so I really don't understand what causes this error. Just in case if you were wondering, here is the meta.xml: <meta> <oop>true</oop> <script src="Class.lua" type="shared"/> <script src="testscript.lua" type="server"/> </meta> Right now this is the full resource basically. Thank you for your answer in advance!
-
That could be a solution as well. I don't know the way you made your script since you didn't post it. But I would say that with my example you wouldn't need to check spamming with the onPlayerCommand event, I think it would make things easier. Also, the timer in my example is not necessary, I thought you would like to add 2.5 seconds delay to destroy the object, for some reason. But yes, in my opinion, if you are using this table method it would make things much easier for you to handle. Here's a little bit simpler version without the 'delay' timer, you could test it to see the difference for yourself. local SMOKERS = {} function isPlayerSmoking(player) if SMOKERS[player] then return true end return false end function startSmoking(player) if isPlayerSmoking(player) then outputChatBox("You already have a cigarette.") return false end SMOKERS[player] = {} SMOKERS[player].cigarette = createObject(...) -- fill this with the correct data setPedAnimation(player, "-", "-",false,false,false,false) -- set anim to smoking, you have to correct this exports["pAttach"]:attach(SMOKERS[player].cigarette, player) -- some more stuff you have to do, fill the bone positions and more return true end function stopSmoking(player) if not isPlayerSmoking(player) then outputChatBox("You don't have a lit cigarette.") return false end setPedAnimation(player) exports["pAttach"]:detach(SMOKERS[player].cigarette, player) destroyElement(SMOKERS[player].cigarette) SMOKERS[player] = nil -- i don't think you need spam protection if you are using the table method, because the player can only start to smoke again if we set the table value of him to nil return true end Also, this way each player has their "own" cigarette. If you were using local variables for the object, and have 2 players, you couldn't destroy player 1's cigarette because the variable gets a new userdata value when you are creating the cigarette object for player 2. I hope I was understandable with my statements.? Note that I didn't test the script in game!
-
My guess is that when executing the command while doing the smoking, the local variables ('smoking', which is the cigarette object I suppose) gets overwritten by a new userdata, the same goes for the timer. Try using a table structure for things like this, that way you can make a difference between players, something like: local SMOKE = { players = {}, } function startSmoking(player) if SMOKE.players[player] then return false end -- this is needed so you can't start smoking if you are already doing it SMOKE.players[player] = {} SMOKE.players[player].cigarette = createObject(...) -- fill this with the correct data SMOKE.players[player].stopTimer = nil setPedAnimation(player, "-", "-",false,false,false,false) -- set anim to smoking, you have to correct this exports["pAttach"]:attach(SMOKE.players[player].cigarette, player) -- some more stuff you have to do, fill the bone positions and more return true end function stopSmoking(player) if not SMOKE.players[player] then return false end -- check whether we should continue running the script, if the player is not smoking then don't execute furthermore if isTimer(SMOKE.players[player].stopTimer) then -- make sure to always kill the timer to avoid the glitch you were experiencing killTimer(SMOKE.players[player].stopTimer) SMOKE.players[player].stopTimer = nil end setPedAnimation(player) -- remove the animation if not SMOKE.players[player].stopTimer then -- check if the timer exists, just for safety SMOKE.players[player].stopTimer = setTimer(function() -- you want to always create the timer, so that's why it's outside the if isTimer statement exports["pAttach"]:detach(SMOKE.players[player].cigarette, player) -- detaching before destroying the object, idk if it's necessary to include detach if you destroy the object, maybe you can delete this line destroyElement(SMOKE.players[player].cigarette) SMOKE.players[player] = nil end, 2500, 1) end return true end Also with this method you can check for the currently smoking players and make a function for it, like: function getSmokingPlayers() return SMOKE.players end But this getSmokingPlayers() function is only necessarry if you would like to get the smoking players in other resources, so you could make an export for it. If you were going to loop it then the index will be the player and the value will be a table, you could make something like: function stopSmokingAllPlayers() for player, data in pairs(getSmokingPlayers()) do -- NOTE THAT: getSmokingPlayers() is the same as SMOKE.players, you could also do that, only in the same script/resource tho print(type(data.cigarette)) -- should output 'object' in the debugscript stopSmoking(player) end return true end I have not tested this script, but I think it should work fine.
-
Sending table data to shader array problem
Dzsozi (h03) replied to Dzsozi (h03)'s topic in Scripting
Update: As I was playing around with setting the shader value in the lua, I figured out that I can actually set the gradient color just fine, but I needed to use it like this: self.shader:setValue("colors", 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1) But that's not how I would like this script to work. How can I use/read arrays inside arrays in the shader? Now it is clear for me that the problem must be inside the shader's for loop, I don't know how to select arrays inside arrays. Could somebody explain please how this should look like? -
Hello dear people of the MTA community! I started experiencing with shaders, I would like to learn shader writing, also would like to create a simple gradient drawing resource for the community, but to finish that project, first I must come to the community for some help. ? I've watched about 7 hours of Unity HLSL tutorial and read many documents and forums to just understand the basics and to know what is what and etc. Surprisingly I understood it fairly quickly, so I jumped into re-writing the unefficient gradient shader I made before. So to the point: I would like to make the gradient shader based on an array of colors, the maximum colors you can specify for a gradient would be 8. My problem is that for some reason only the first color from the array (colors[0]) gets passed to the shader, the rest remain "unspecified"(?). However, I don't get any errors, and the shader seems to be working fine when adding more colors in script (the red color gets shifted accordingly), but they are simply just transparent, also when trying to debug with return colors[1]; it doesn't output any colors (should output green color, colors[2] should output blue only). A more compact question of the problem is: How do I pass data from lua to a shader array? I don't know if the problem is in the lua or the shader file, my guess is that there is a problem in the lua script file, when setting the shader property. Let me show you a screenshot of the problem: This gradient should go from red to green to blue, but only red color gets noticed by the shader script. Here are my codes: gradient.fx #include "util.fx" //this is not necessary right now, all I have here is inverseLerp and rotationMatrix functions half4 colors[8]; int colorCount; half4 PixelShaderFunction(float2 uv : TEXCOORD0) : COLOR { //float4 finalColor = lerp(colors[0], colors[1], uv.x); //return colors[1]; //doesn't output anything!!! ??????!!?!? half4 finalColor = colors[0]; for ( int i = 0 ; i < colorCount ; ++i ) { finalColor = max(0, lerp(finalColor, colors[i], uv.x)); // using max to prevent going into negative values } return finalColor; } technique tec0 { pass P0 { PixelShader = compile ps_2_0 PixelShaderFunction(); } } parts of gradientC.lua where I update and create the gradient function Gradient.new(x, y, w, h, rotation, colorTable, gradientSize, rotateToCenter) if not tonumber(x or y or w or h) then return false end --if rotateToCenter == nil then rotateToCenter = false end local data = setmetatable({}, Gradient) data.shader = DxShader(":sa_gradient/res/gradient.fx", 0, 0, false, "other") data.id = #CREATED_GRADIENTS+1 data.position = Vector2(x, y) data.size = Vector2(w, h) data.rotation = tonumber(rotation) or 0 data.gradientSize = tonumber(gradientSize) and math.max(0, math.min(1, gradientSize)) or 0.5 data.colors = type(colorTable) == "table" and colorTable or {Vector4(1,0,0,1), Vector4(0,1,0,1), Vector4(0,0,1,1)} data.colorCount = #data.colors --data.rotateToCenter = rotateToCenter CREATED_GRADIENTS[data.id] = data return data end function Gradient:update() if not self.shader then return false end --self.shader:setValue("rotateToCenter", self.rotateToCenter) --self.shader:setValue("rectangleSize", self.size) --self.shader:setValue("rotation", self.rotation) --self.shader:setValue("gradientSize", self.gradientSize) self.shader:setValue("colors", unpack(self.colors)) -- MY GUESS IS THAT THE PROBLEM IS HERE, IDK THO :(( self.shader:setValue("colorCount", self.colorCount) CREATED_GRADIENTS[self.id] = self return true end I also have few more questions regarding MTA and shaders: - Should I use half4 instead of float4? I know there is a difference between quality if I remember correctly, but does it make things run faster in MTA? - I seen in a tutorial video that fragment / pixel shader doesn't actually use TEXCOORD0 for position, and that you can use TEXCOORD1, TEXCOORD2 etc to be any kind of data? Is this the case in MTA as well, or it is some Unity thing? What would be a solution for this problem? I like making things compact and simple, so that's why I use tables/arrays for the colors, that way I don't have to make different shader files for 2 or 3 or 4 color gradients. Thank you for your help in advance! Sorry for tagging, but I don't know how many people are experienced with shaders when talking about HLSL and MTA, I know one for a fact, maybe you could help me out quickly @Ren_712
-
Dark spots on vehicle parts, bad shading(?)
Dzsozi (h03) replied to Dzsozi (h03)'s topic in Modelling
UPDATE 2: I changed Spec/Ref Blend back to default, which is I believe is 0.09, also repeated the steps in this tutorial on every poly surface of the chassis and doors And exported and imported the model again to 3ds max, then exported again for the game, now it seems like the problems have been fixed for now. -
Hi! I was trying to make a custom vehicle based on the idaho and the vice city premier. It turned out fine it was working, except the normals/shading/reflection. I don't know why, and I can't figure out how to fix it, but I have some strange darker parts on my vehicle, but it's fine in 3ds max. I am using kam's scripts and 3ds 2010. I did weld vertices at a 0.001 setting and with 4 pixels target. I did parts of this tutorial (as I mentioned above the smoothing, UV mapping the 2nd channel (xvehicleenv128)) I also did mess around with the material settings, but I am using an Ambient of 0.45, Spec, Diff of 1, Glossiness of 20 and Spec/Ref Blend of 0,5 so I don't know if the problem is there. I also did reset the normals on the chassis and the doors, by converting the model to editable poly, and using the Edit Normals modifier from the dropdown list. Nothing seems to fix the issue. What am I missing here? The model looks kind of flat as well, or IDK, it looks strange. How can I fix this? I would like to achieve a SA style default vehicle look. Thank you for the help in advance! UPDATE: I managed to achieve some steps in a good direction by closing my 3ds scene file, opening a new one, importing this model and not doing 0,001 welding, then exporting again, now my model looks like this:
-
OOOOOOO I get it now, thank you so much for your quick response and time! I managed to do it, it is working now as expected. Have a nice day/night, thanks again @The_GTA!
-
So do I make a new table with a variable name let's say for example previousMenu, then set the previousMenu[menuID] to be a new table, then repeat this process each time a button gets clicked? If I understand you correctly, I am not so sure. I would be really grateful if you could provide me an example of what you are suggesting, if I am not correct.
-
Sorry I messed up one function above and couldn't edit the post anymore, here's the working one: function stepBackInMenu() currentMenu = previousMenu currentMenuID = previousMenuID return true end
-
Hello! I made a script which can render menus with infinite sub menus in it. I am using a table for that. Everything seems to be working fine, but when I was trying to create the Back button for the menus, including sub menus, I crash into a small problem. I don't really know how should I make this step back function for all of the sub menus, since I can step back to only the previous one, not the one before that. Here is an example table for the menus: MENU = { [1] = { ["category"] = "options1", ["sub"] = { [1] = { ["category"] = "options1-1", ["sub"] = { [1] = { ["category"] = "options1-1-1", ["sub"] = { [1] = {option = "change1"}, }, }, }, }, [2] = { ["category"] = "options1-2", ["sub"] = { [1] = {option = "change2"}, }, }, }, }, [2] = { ["category"] = "options2", ["sub"] = { [1] = { ["category"] = "options2-1", ["sub"] = { [1] = {option = "change1"}, }, }, [2] = { ["category"] = "options2-2", ["sub"] = { [1] = { ["category"] = "options2-2-1", ["sub"] = { [1] = {option = "change2"}, }, }, [2] = { ["category"] = "options2-2-2", ["sub"] = { [1] = {option = "change2"}, }, }, [3] = { ["category"] = "options2-2-3", ["sub"] = { [1] = {option = "change2"}, }, }, }, }, }, }, } And here's how I handle the rendering and clicking: local sx, sy = guiGetScreenSize() local RENDER = {} RENDER.state = true RENDER.hover = {} RENDER.hover.menuID = 0 RENDER.hover.itemID = 0 RENDER.hover.back = nil local currentMenu = MENU local currentMenuID = 0 local previousMenu = currentMenu local previousMenuID = currentMenuID function render() if RENDER.state then RENDER.hover.menuID = 0 RENDER.hover.itemID = 0 RENDER.hover.back = nil local menuX, menuY = sx/2-200, sy/2 for menuID, menuData in ipairs(currentMenu) do menuY = sy/2+(30*menuID) if isMouseInPosition(menuX, menuY, 100, 25) then RENDER.hover.menuID = menuID RENDER.hover.itemID = menuData.option and menuID or 0 end local hovering = RENDER.hover.menuID == menuID dxDrawRectangle(menuX, menuY, 100, 25, hovering and tocolor(100, 100, 100, 150) or tocolor(0, 0, 0, 150)) dxDrawText(menuData["category"] or menuData.option, menuX+10, menuY+5, 0, 0, tocolor(255, 255, 255, 255)) end if currentMenuID ~= 0 then local backX, backY = menuX, sy/2 local backHover = isMouseInPosition(backX, backY, 100, 25) dxDrawRectangle(backX, backY, 100, 25, backHover and tocolor(200, 0, 0, 150) or tocolor(100, 0, 0, 150)) dxDrawText("< Back", backX+10, backY+5, 0, 0, tocolor(255, 255, 255, 255)) if backHover then RENDER.hover.back = true end end end end addEventHandler("onClientRender", root, render) function stepBackInMenu() previousMenu = currentMenu previousMenuID = currentMenuID return true end addEventHandler("onClientClick", root, function(button, state) if button == "left" then if state == "down" then if RENDER.hover.menuID ~= 0 then if RENDER.hover.itemID == 0 then previousMenuID = currentMenuID previousMenu = currentMenu currentMenuID = RENDER.hover.menuID currentMenu = currentMenu[currentMenuID]["sub"] end end if RENDER.hover.back then stepBackInMenu() end end end end) What would be the most optional way to handle every sub menu's back button to step back in to the actual previous menu? I can't seem to figure it out by myself so I would really appreciate some help from you. Thank you in advance!
-
setTimer and getTickCount - desynced blinkers
Dzsozi (h03) replied to Dzsozi (h03)'s topic in Scripting
Thank you so much, this seems to fix the problem. You are absolutely right, it went by me that I should use a variable for the current tick as well. This is what I was looking for, thank you for the help guys. I'm sorry but I don't really want to make this resource depend on another one. However, I will consider making it client side, since as IIYAMA mentioned, /shownetstat gets a little bit higher values, I haven't really used this command before for debugging, so I don't really understand it yet, fortunately packet loss doesn't happen. Thank you for educating me again, have a nice day! -
setTimer and getTickCount - desynced blinkers
Dzsozi (h03) replied to Dzsozi (h03)'s topic in Scripting
But for sure I have to rework it on client side to make the checks, right? Would it be more efficient? -
setTimer and getTickCount - desynced blinkers
Dzsozi (h03) replied to Dzsozi (h03)'s topic in Scripting
So, should I implement your servertimesync resource to my core resources, and make the light checks on client side, using exported servertimesync function?