Dzsozi (h03)

Members
  • Content Count

    643
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by Dzsozi (h03)

  1. Exports do not work across clientside and serverside. I meant to write "... to get the variables from another resource". The question is how can I return something like vehicle.fuel in a different resource when hitting a marker for example. But I guess I will just stick to element data then with a custom data system, at the moment I really don't know any other solutions, triggering back and forth sounds a lot of inefficient and unnecessary work. But how can I call a method from a different resource like I mentioned above? In vehicleScripter resource how do I call the vehicleCreator:toggleEngine function, or is there any way to just use vehicle:toggleEngine? Do I make an exported function to get the vehicleCreator table? Or what is the solution for this?
  2. Alright, I am getting closer to what I need, but I think I am not doing something correctly, also I am still stuck at the "variable-data-transferring" between client and server. I rewrote the script based on your comments and Daniel Lett's videos, now it looks a little bit different. -- i got this function from Daniel's video function Class(tbl) -- set a metatable on the passed tbl parameter -- __call property -- create a new table -- on that new table, set __index to our class -- call a constructor method on the class -- return our new table setmetatable(tbl, { __call = function(cls, ...) local self = {} setmetatable(self, { __index = cls }) self:constructor(...) end }) return tbl end ------ local db = exports["sa_db"]:getConnection() local numberToBoolean = { [0] = false, [1] = true, } local switchToOverrideLights = { [0] = 1, [1] = 2, } --local VEHICLE_FUEL_CONSUMPTION = 0.006 -- not using it yet --local VEHICLE_START_KEY = "J" local totalSavedVehicles = 0 local totalTemporaryVehicles = 0 vehicleCreator = Class({ vehicles = {}, newVehicle = function(self, model, position, rotation, save) if not tonumber(model) then return outputDebugString("[vehiclecreator] 'model' parameter is required when creating a vehicle", 2) end if not position then return outputDebugString("[vehiclecreator] 'position' parameter is required when creating a vehicle", 2) end rotation = rotation or Vector3(0,0,0) local vehicle = Vehicle(model, position) if save then totalSavedVehicles = totalSavedVehicles + 1 dbExec(db, "INSERT INTO vehicles (id, model, position, rotation) VALUES (?, ?, ?, ?)",totalSavedVehicles,model,toJSON({x = position.x, y = position.y, z = position.z, int = 0, dim = 0}), toJSON({rx = rotation.x, ry = rotation.y, rz = rotation.z})) else totalTemporaryVehicles = totalTemporaryVehicles - 1 end local vehicleData = { id = save and totalSavedVehicles or totalTemporaryVehicles, fuel = 100, } self.vehicles[vehicle] = vehicleData self:toggleEngine(vehicle, 0) self:toggleLights(vehicle, 0) return self.vehicles[vehicle] end; getVehicleData = function(self, vehicle) return self.vehicles[vehicle] end; deleteVehicle = function(self, vehicle) if self.vehicles[vehicle] then if self.vehicles[vehicle].id > 0 then dbExec(db,"DELETE FROM vehicles WHERE id", self.vehicles[vehicle].id) end self.vehicles[vehicle] = nil vehicle:destroy() return true end return false end; toggleEngine = function(self, vehicle, state) if self.vehicles[vehicle] then self.vehicles[vehicle].engine = state return vehicle:setEngineState(numberToBoolean[state]) end end; toggleLights = function(self, vehicle, state) if self.vehicles[vehicle] then self.vehicles[vehicle].lights = state return vehicle:setOverrideLights(switchToOverrideLights[state]) end end; }) -- testing local testveh = vehicleCreator:newVehicle(475, Vector3(-296.25921630859,1751.9106445313,42.6875), nil) print(#vehicleCreator.vehicles) -- why do i always get 0? addEventHandler("onVehicleStartEnter", root, function() --local data = vehicleCreator:getVehicleData(source) --if data.id < 0 then --vehicleCreator:deleteVehicle(source) --end vehicleCreator:toggleEngine(source, 1) vehicleCreator:toggleLights(source, 1) end) So my questions are why does #vehicleCreator.vehicles return 0 even though there is clearly a created vehicle (I tried it with multiple vehicles as well)? how can I send the fuel variable from server to client? how can I get the fuel variable of a vehicle in a different resource? (I guess setElementData would be the easiest but I would like to avoid it as much as possible) Do I have to use exported functions and triggers from server to client to get the variables? Because that would also cause desync for sure. Lets say I have vehicleCreator and vehicleScripter resources. In vehicleScripter resource I store the scripts about gas stations, fueling up the vehicles, etc, and in vehicleCreator I create them for shops and admin purposes, etc. How can reach a variable or method stated in vehicleCreator from vehicleScripter, for example the toggleEngine. Regarding the element data, should I make a custom data system which uses only one element data (let's say vehicle.data) to store a table of information (let's say {fuel=100, engine=1, ligths=1})? Is it more efficient or basically I am at the same position because of the length of the tables? I hope my question makes sense and you can answer me. 😄
  3. I've watched every single MTA scripting tutorial from Daniel Lett, big shout outs to him btw, I learned some new things from their videos even though I am into scripting for a while now. My DB system is kinda similar to his from the videos because I want to remake my stuff in OOP, so basically kinda starting from stratch, I have an idea of the things I would like to do, I just don't know how to do some of them now that I experience with this OOP method. And I think it is more efficient in some ways, mainly just because you write less text in codes, means less data to convert into zeros and ones. I don't know this advanced stuff that much, but so far this is what I heard and learned in videos I watched about OOP. I even watched Roblox OOP tutorials, but all I found was the basic setting up of tables and changing variables. But from this there comes no answer to my question about targeting a vehicle element and returning the (fuel) variable. 🤔😟 However I might just rewatch these videos in case I missed something.
  4. So then I don't understand how should I implement custom functions in my scripts, for example setFuel([element] vehicle, [int] value) and such things. I thought I must specify them inside the first table where I create and specify every default variable. Or you mean exactly like that, to create the above mentioned function then use a custom function outside of the vehicleCreator class where I use the fuel consumption method to update the fuel variable of the vehicle? Sorry, it isn't clear for me yet. Because after that in a different gas station script, how do I use the self.fuel variable on a vehicle element? I found a script on the wiki that uses rawset for a backpack example: https://wiki.multitheftauto.com/wiki/OOP_in_Lua (bottom of the page) but it doesn't specify any real elements like vehicles, objects, peds etc. It is also not really clear to me what do you mean by re-attaching them. 😅 Should I make the base of the vehicleCreator class in a shared Lua file with variables I would like to share, I mean something like this: -- stated as "shared" in meta vehicleCreator = { lights = 0, engine = 0, fuel = 0, } -- stated as "server" in meta function vehicleCreator:newVehicle(...) self.element = createVehicle(...) self.fuel = 100 --etc etc end -- stated as "client" in meta function displayFuel() local vehicle = localPlayer:getOccupiedVehicle() -- or i guess i can use localPlayer.vehicle as well if vehicle then dxDrawText(vehicle.fuel 200, 200, 0, 0) end end addEventHandler("onClientRender", root, displayFuel) But while I was writing this, in my head other problems came up because of security and basic functioning. I would like to make a simple and efficient system where I can use elements in any server side script to modify a once given variable and easily return it on client side for displaying when I need to (for example in this case let's just talk about the fuel, but later on I would like to expand variables to create a complex vehicle system with simple readable code 🙄😄).
  5. I have one more question, can I get a custom variable like self.fuel of a vehicle [element]? So let’s say I want to display the fuel on client, so I just have to write something like this local vehicle = localPlayer:getOccupiedVehicle() dxDrawText(vehicle.fuel ... —bla blaa If it is, how can I achieve it? I really appreciate and accept every suggestions you think I might need to know about OOP and optimized easy to read code!🥰😘🤓
  6. Hello community! A few days ago I jumped into learning OOP scripting and started creating a new vehicle system with it. I stumbled into a few problems when I finally created a basic vehicle creator script. I added fuel first of all, but when I wanted to create a gas station script for it (this would be in a different Lua file because of readability and organization), I couldn't think of how to get the fuel variable of the vehicle. This problem got me thinking if I made the current system correctly at all? Regarding to this problem I got one more question. I don't know how I should return the OOP variable on client side from server side, so I can show the fuel for example with dx functions, without setting different element datas for everything (because I would like to add a lot more features to the system, not just fuel) Is there a way to simply save variables or get them later somehow? Or is this what getmetatable function is used for? Here is my current code, which is working how I wanted by the way, there is no problem right now, but I would like to make it as optimised, as simple as possible, and change it correctly regarding to my questions. Is there anything I did wrong or should be done otherwise and could be more efficient? Server: local db = exports["sa_db"]:getConnection() local VEHICLE_FUEL_CONSUMPTION = 0.006 vehicleCreator = {totalSavedVehicles = 0, totalTemporaryVehicles = 0} vehicleCreator.__index = vehicleCreator function vehicleCreator:newVehicle(model, position, save) if not tonumber(model) then return outputDebugString("[vehiclecreator] 'model' parameter is required when creating a vehicle", 2) end if not position then return outputDebugString("[vehiclecreator] 'position' parameter is required when creating a vehicle", 2) end local newPosition = {x = position.x, y = position.y} local vehicleData = { element = Vehicle(model, position), fuel = 100, dirtLevel = 0, } setmetatable(vehicleData, self) local consumeFuel = function() local vehicle = vehicleData.element local distance = getDistanceBetweenPoints2D(vehicle.position.x, vehicle.position.y, newPosition.x, newPosition.y) local engineConsumption = 0 if vehicle:getEngineState() then engineConsumption = 0.7 end if vehicleData.fuel >= 1 then vehicleData.fuel = vehicleData.fuel - (VEHICLE_FUEL_CONSUMPTION*(distance+engineConsumption)) newPosition.x, newPosition.y = vehicle.position.x, vehicle.position.y print(vehicleData.fuel) end if vehicleData.fuel < 1 then vehicleData.fuel = 0 vehicle:setEngineState(false) end end addEventHandler("onVehicleEnter", vehicleData.element, function(_, seat) if seat == 0 then local fuelTimer = setTimer(function(vehicle) consumeFuel() vehicle:setData("vehicle.datatable", vehicleData) end, 1000, 0, source) addEventHandler("onVehicleExit", source, function(_, seat) if seat == 0 then if isTimer(fuelTimer) then killTimer(fuelTimer) fuelTimer = nil end end end) end end) if save then self.totalSavedVehicles = self.totalSavedVehicles + 1 vehicleData.id = self.totalSavedVehicles dbExec(db, "INSERT INTO vehicles (id, model, position, rotation) VALUES (?, ?, ?, ?)",vehicleData.id,model,toJSON({x = position.x, y = position.y, z = position.z, int = 0, dim = 0}), toJSON({rx = 0, ry = 0, rz = 0})) else self.totalTemporaryVehicles = self.totalTemporaryVehicles + 1 vehicleData.id = -self.totalTemporaryVehicles end vehicleData.element:setData("vehicle.datatable", vehicleData) return vehicleData end function vehicleCreator:deleteVehicle() self.element:destroy() if self.id > 0 then dbExec(db,"DELETE FROM vehicles WHERE id", self.id) end self = nil end function vehicleCreator:loadSavedVehicles() local query = dbQuery(db, "SELECT * FROM vehicles") local results = dbPoll(query, -1) self.totalSavedVehicles = 0 for _, data in pairs(results) do local position = fromJSON(data.position) local vehicle = vehicleCreator:newVehicle(data.model, Vector3(position.x, position.y, position.z)) self.totalSavedVehicles = self.totalSavedVehicles + 1 vehicle.id = self.totalSavedVehicles print("id: " .. vehicle.id .. " | fuel: " .. vehicle.fuel .. " | dirt: " .. vehicle.dirtLevel) end dbFree(query) end addEventHandler("onResourceStart", resourceRoot, function() vehicleCreator:loadSavedVehicles() end) local testVehicle = vehicleCreator:newVehicle(500, Vector3(475.95861816406,-1841.2951660156,4.5377359390259)) -- creates vehicle at santa maria beach Client: local sx, sy = guiGetScreenSize() function fueldisplay() local vehicle = localPlayer:getOccupiedVehicle() if vehicle then local vehicleData = getElementData(vehicle, "vehicle.datatable") dxDrawRectangle(sx/2-50, sy/3-25, 100, 50, tocolor(0, 0, 0, 150)) dxDrawRectangle(sx/2-50, sy/3-25, (100*vehicleData.fuel)/100, 50, tocolor(100, 200, 100, 200)) end end addEventHandler("onClientRender", root, fueldisplay) I'm still learning OOP and there are some things I just couldn't understand how they work yet. Thank you for your response in advance!
  7. So no matter what, I will have to use at least 2 tables for the item positions? Btw sorry for the lots of questions, I’ve never created or worked with inventory systems by myself. Also, what should be the value of the ignoreID variable in this case?
  8. I came to the conclusion that I can basically use one table for the item list which holds the currently opened inventory’s items and the indexes of this table represent the items’ position, like this itemTable = { {name = "item1", size = {1, 1}}, -- 1 {name = "item2", size = {1, 3}}, -- 2 } ------------------ -- this should be the temporary item table which I don't save, because it is for drawing the items of an opened inventory(?) inventoryItems = { -- [x position/column] = {[y position/row] = {itemData}}, [2] = { [3] = {itemID = 1, value = 100}, }, } So in my mind I could use this for checking positions and use an utility function like isSlotFree(x, y, w, h) which would be similar to isMouseInPosition, that checks if the given variables match the item positions from the inventoryItems table, then if they are matching just return false. But then this raises another question for me, how can I change the index of a specified item, especially if there are 2 items of the same id, or what would be a way to identify items seperately? Sorry I got a little bit confused with this ”checking box” thing. Also these things are only in my head right now, but today when I get home I will start working on it based on the things and ideas in this topic and will see if this all is a good approach, but correct me please if there is something wrong with my “theories”.
  9. So based on this logic I assume that I should make utility functions like isSlotFree(x, y) and then check the indexes inside the table, then if an index is same as the given variable it should return false, am I correct? Then use this function to check movent of an item by player to a hovered slot. But when beginning the calculation and adding a new item, how do I set it’s first position if there are already items in the inventory, but lets say there is just enough space at the bottom of the inventory? What should be the criteria or logic behind checking for free positions anywhere inside an opened inventory?
  10. Hello MTA community! I would like to make an inventory system, which has different sized items (1*1, 2*1, 1*3, etc.), so the inventory space would matter based only on your space management. Here are some example photos of what I mean: I haven’t started coding yet, that is the reason I created this topic. First of all I am trying to put together a structure and I would like to hear your opinions and suggestions on how to make this type of inventory. I have some main questions but please let me know anything you think I might have to know regarding this topic. My main questions are: - How should I do the calculations for item positioning? (I would like players to be able to move the items within an inventory, that’s for sure) - Do I calculate a freshly added items’ position inside the dx drawing function? Or should I specify the new items’ position at the point when I give it to the player? - I would like to make it as simple, as efficient and as “automatic” as possible, so if it is an option, when I give an item to an element inventory I would like to only specify the element, item and item value variable. - Where or how should I store the items’ position or how can I return the position and other data of an item when clicking on a slot? Do I make a variable for each slot representing it’s space (true if free/false if taken)? Do I save the currently visible inventory’s content with item data inside a table on client side? - I would like to make inventories for vehicles peds and objects as well with a function, something like createInventory(element, slotNumber) for example. Should I make a new element for that using createElement or is there any other way to do that? As I mentioned above, right now I am putting together a plan about how I would like to start working on this inventory resource, so please let me know anything useful!
  11. These videos in this topic show a much more different system from what is currently done. Soon when I fix most of the known bugs and be ready with unfinished systems, I will be uploading a new video about it.
  12. https://community.mtasa.com/index.php?p=resources&s=details&id=15679 With this resource you are able to get/modify the position of a vehicle's cargo space. The position you get is the middle of for example a Bobcat's bed, so if you want to add lots of objects you will have to use some loops for positioning. Look at the exampleS.Lua in the resource. local function testFunction2() local vehicleObject if not isElement(vehicleObject) then local cargoPos = exports["vehiclecargo"]:getVehicleCargoPlacementPosition(source) if cargoPos then local x, y, z = getPositionFromElementOffset(source,cargoPos.x, cargoPos.y, cargoPos.z+0.285) local vehicleObject = createObject(1271, x, y, z, 0, 0, 0) setElementCollisionsEnabled(vehicleObject, false) setObjectScale(vehicleObject, 1.5) attachElements(vehicleObject, source, cargoPos.x, cargoPos.y, cargoPos.z+0.285) -- +value on Z because of the object scaling so the object doesn't collide with the vehicle addEventHandler("onVehicleExit", source, function() if isElement(vehicleObject) then destroyElement(vehicleObject) vehicleObject = nil end end ) end end end addEventHandler("onVehicleEnter", root, testFunction2)
  13. Thank you! I had to change some things up a little bit to match my needs and get it done correctly, it's working now just as I wanted to!
  14. Hello! While I was improving a resource, I came across a small problem; I would like to get the correct value based on vehicle health. I have a table similar like this: ["somekey"] = { [75] = "somevar1", -- view it as health limits, so when the health is lower or between the current and the next, more lower number, then I can add a property to my vehicle [50] = "somevar2", [25] = "somevar3", }, What I want to do is if the health of the vehicle goes under 75 then return "somevar1", when it goes under 50 then return "somevar2" and when it goes under 25 then return "somevar3" and so on. Basically I would like to check if the vehicle's health is between the given indexes/limits and return the correct table value for it. I am guessing that I will need a custom range function but I don't know how to get started and how to select between the indexes depending on a given number when calling the function. I hope I was understandable and someone can help me out, I really need to get this work, please help!
  15. I think the problem is the way you are trying to get the matching model id. In my opinion this would be a much simpler solution for this problem: local vehicleModelIDs = { [596] = true, [523] = true, } addEventHandler ("onVehicleExit", getRootElement (), function (thePlayer) if vehicleModelIDs[getElementModel(source)] then local passenger = getVehicleOccupant (source, 1) if passenger then removePedFromVehicle(passenger) end end end ) This way adding and removing vehicle ids in the future will be easier. Let me know if it works or not.
  16. I just noticed I didn't even use the given rotations at this line; setElementRotation(fx, rx-(elementRX+90)-180, elementRY-ry+90, elementRZ-rz) -- what do i actually write here? but I changed up the variables so many times, nothing seemed to work, probably I copied the wrong version of the script while I was trying to achieve what I wanted.
  17. Hello! I am asking for your help in rotation calculations, I am struggling to get done what I want. I made a script to attach effects to vehicles, but I noticed a problem with some specific effects (for example the one called "petrolcan", which is the effect you get when your character is peeing). I attached this effect to the position of the wheel_rb_dummy and wheel_lb_dummy, now the problem is that when my vehicle turns the effects do not keep their offset rotations, they turn in wrong directions. Here's my current calculations: vehicleEffectData = { ["smoke"] = { ["wheel_lb_dummy"] = { ["petrolcan"] = {x = -0.1, y = 0.3, z = 0.3, rx = -270, ry = 0, density = 1}, }, ["wheel_rb_dummy"] = { ["petrolcan"] = {x = 0.1, y = 0.3, z = 0.3, rx = 270, ry = 0, density = 1}, }, }, } local attachedEffects = {} local vehicleEffects = {} function attachEffect(effect, element, pos, rot) attachedEffects[effect] = { effect = effect, element = element, pos = pos, rot = rot } addEventHandler("onClientElementDestroy", effect, function() attachedEffects[effect] = nil end) addEventHandler("onClientElementDestroy", element, function() attachedEffects[effect] = nil end) return true end addEventHandler("onClientPreRender", root, function() for fx, info in pairs(attachedEffects) do local rx, ry, rz = info.rot.x, info.rot.y, info.rot.z local elementRX, elementRY, elementRZ = getElementRotation(info.element) local x, y, z = getPositionFromElementOffset(info.element, info.pos.x, info.pos.y, info.pos.z) setElementPosition(fx, x, y, z) setElementRotation(fx, rx-(elementRX+90)-180, elementRY-ry+90, elementRZ-rz) end end ) -- inside script: attachEffect(vehicleEffects[vehicle][effect][partName][effectName], vehicle, Vector3(partX+effectData.x, partY+effectData.y/(seatToEngineDifference*2), partZ+effectData.z), Vector3(effectData.rx or 0, effectData.ry or 0, effectData.rz or 0)) Images of the current version: This is the rotation I want to always achieve when I set the rotation inside the table, but this only happens when I am facing this or -(this) direction: When I face north (the effects rotate as well and they turn inside): Please help me out with the calculations!
  18. I think you could achieve something really similar to that single player feature by combining these functions: createProjectile setElementAlpha createObject setElementCollisionsEnabled attachElements
  19. I still got the scripts, I might continue and finish this project finally, I just have to plan what I want to do exactly. If you have any suggestions or ideas let me know!
  20. addEvent("UI.click", false) addEventHandler("UI.click", resourceRoot, function (widget) if widget == ui.playersList then local items = exports.UI:getItems(ui.playersList) local selectedItem = exports.UI:getActiveItem(ui.playersList) Panel.showPlayerInfo(items[selectedItem].player) elseif widget == ui.CanelButton then Panel.hide() elseif widget == ui.SendButton then local reason = UI:getText(ui.reasonInput) if client:getData("money") < reason then exports.UI:showMessageBox("Error", "Недостаточно средств") else triggerServerEvent("SendMoney", localPlayer, Panel.showPlayerInfo(items[selectedItem].player), reason) Panel.hide() end end end) addEvent("SendMoney",true) addEventHandler("SendMoney", root, function(selectedPlayer, reason) if not isElement(selectedPlayer) then return false end if type(reason) ~= "number" then return false end if client:getData("money") < reason then return end if not exports.Core:givePlayerMoney(client, -reason) then return false end if isElement(selectedPlayer) then exports.Core:givePlayerMoney(selectedPlayer, reason) end end) Try this one.
  21. @MrTasty helped me with the following useful function: https://wiki.multitheftauto.com/wiki/WordWrap I also needed it for a notification system. This could be useful if you want to do multiple line dx texts, this function also supports color codes going from the 1st line to the 2nd.
  22. Why don't you just use bone attach and attach a phone object to the player's hand?
  23. Very helpful, lots of beginner modellers will be grateful for your effort that you put into this video!
  24. ****Sighs**** Okay so you are trying to tell me to look up the wiki and community and basically the whole internet to create a new shader file, that - as I can see I must write it down again - can handle the replace of 4 textures at the same time. What kind of modeller are you if you couldn't find the default CJ textures in the game files bro? You are 100% right! But what does that have to do with my problem, nothing? It's a fact that peds vehicles and objects are being made in a modeling program bro, no sh#t! Have you ever checked this function on the wiki https://wiki.multitheftauto.com/wiki/EngineApplyShaderToWorldTexture ? I quote: so by that you probably already figured out that I am using the correct texture names, just because your HD downloaded CJ mod doesn't have its files named the same (let me guess they are called player_torso, player_legs, etc), it doesn't mean I am using the wrong textures, since MTA handles those texture names in a different way as we can see, with some quick semi enthusiastic research you could find the answer easy bro. Why are you linking me the MTA community site, I don't even know, so let's not talk about that. Well, about countless shader examples, I wouldn't say they are countless. But they are not examples for me in this case. Like you said, yes, those are shaders, and this is what I use them for in this case as well. REPLACE TEXTURES, which means I edit the default texture, for example the torso and REPLACE it with a shader. So what does modeling has to do with it, I still don't get it. I don't have to do any UV mapping nor any modeling, why would I? You yourself said that shaders are for applying a texture to an object ped or vehicle. Looks like you are not completely understanding how texture replacing works if you only edit the default texture(?) You can keep telling me to go on YouTube or MTA forum (well, in this case this is what I just did, and that's the reason for this topic being existent, so again, I don't understand you), but there's a reason I made this topic... Probably because I didn't find the proper help I need and I am hoping for someone to help me out, don't you think? I didn't create this topic because I was bored. So, from now on, please avoid telling me the same thing "over and over in different ways" bro. Because you are not helping me, you are just trying to prove me wrong, that I must go and learn from wiki and search up the whole internet for a solution to my problem. I just asked a simple question which is: HOW CAN I MAKE A SHADER THAT CAN HANDLE MULTIPLE TEXTURE REPLACES AT ONCE??? No modeling, no UV mapping, no Facebook or YouTube or Twitter search for help, just a simple question on MTA forum in a topic about shaders. You don't have to tell me that I am doing it wrong and must find a different way via modeling, (even if I already have my system ready, just willing to improve it) when you are the one who doesn't even know where to find the default game textures. And now, back to the main question again: HOW CAN I MAKE A SHADER THAT CAN HANDLE MULTIPLE TEXTURE REPLACES AT ONCE??? ???