Jayceon Posted January 11, 2017 Share Posted January 11, 2017 Hello everyone! I tried to make custom wheels to vehicles (like tuning element) but i have some problems with code. When the wheel camber angle is not default, the wheel get not good rotations. local createdCustomWheels = {} bindKey("f2", "down", function() local vehicle = getPedOccupiedVehicle(localPlayer) if vehicle then addCustomWheel(vehicle, 1075, "front") end end ) addEventHandler("onClientPreRender", root, function() for vehicle, value in pairs(createdCustomWheels) do if vehicle and isElement(vehicle) and isElementStreamedIn(vehicle) then local vehicleX, vehicleY, vehicleZ = getElementPosition(vehicle) if value["wheel_lf_dummy"] then local componentX, componentY, componentZ = getVehicleComponentPosition(vehicle, "wheel_lf_dummy") local componentRX, componentRY, componentRZ = getVehicleComponentRotation(vehicle, "wheel_lf_dummy") attachElements(value["wheel_lf_dummy"], vehicle, componentX, componentY, componentZ, componentRX, -15 + componentRY, componentRZ) end if value["wheel_rf_dummy"] then local componentX, componentY, componentZ = getVehicleComponentPosition(vehicle, "wheel_rf_dummy") local componentRX, componentRY, componentRZ = getVehicleComponentRotation(vehicle, "wheel_rf_dummy") attachElements(value["wheel_rf_dummy"], vehicle, componentX, componentY, componentZ, componentRX, -15 + componentRY, componentRZ) end end end end ) function addCustomWheel(vehicle, wheelId, side) if vehicle and wheelId and side then local vehicleX, vehicleY, vehicleZ = getElementPosition(vehicle) if side == "front" then local lfX, lfY, lfZ = getVehicleComponentPosition(vehicle, "wheel_lf_dummy") local rfX, rfY, rfZ = getVehicleComponentPosition(vehicle, "wheel_rf_dummy") setVehicleComponentVisible(vehicle, "wheel_lf_dummy", false) setVehicleComponentVisible(vehicle, "wheel_rf_dummy", false) createdCustomWheels[vehicle] = {} createdCustomWheels[vehicle]["wheel_lf_dummy"] = createObject(wheelId, vehicleX, vehicleY, vehicleZ) createdCustomWheels[vehicle]["wheel_rf_dummy"] = createObject(wheelId, vehicleX, vehicleY, vehicleZ) setElementCollidableWith(createdCustomWheels[vehicle]["wheel_lf_dummy"], vehicle, false) setElementCollidableWith(createdCustomWheels[vehicle]["wheel_rf_dummy"], vehicle, false) setObjectScale(createdCustomWheels[vehicle]["wheel_lf_dummy"], 0.7) setObjectScale(createdCustomWheels[vehicle]["wheel_rf_dummy"], 0.7) attachElements(createdCustomWheels[vehicle]["wheel_lf_dummy"], vehicle, lfX, lfY, lfZ, 0, 0, 0) attachElements(createdCustomWheels[vehicle]["wheel_rf_dummy"], vehicle, rfX, rfY, rfZ, 0, 0, 0) end end end Link to comment
Captain Cody Posted January 11, 2017 Share Posted January 11, 2017 You need to lock either Y or X, forgot which. One of them has lean that makes all hell breaks loose when applied. 1 Link to comment
myonlake Posted January 12, 2017 Share Posted January 12, 2017 (edited) You need to lock the Y component relative to the X component with an offset of -15 or whatever tilt looks good for you. I'll get you an example once I get to test it out. Edited January 12, 2017 by myonlake 1 Link to comment
Jayceon Posted January 12, 2017 Author Share Posted January 12, 2017 Thanks the reply, i'm waiting your example. Link to comment
myonlake Posted January 12, 2017 Share Posted January 12, 2017 (edited) Alright, I managed to figure it out for you. I also included the OOP version. So, I found out attachElements doesn't have the custom order parameter which allows you to set the order of the rotation. The expected rotation order would be ZYX, in OOP this is not the case however. I am not entirely sure why this is, it might be because of some simple rule but I just don't realize it right now... maybe it's written somewhere in the depths of the Wiki, but I cba to find it right now. I changed some of the parameters for the addVehicleCustomWheel function to allow tilt and scale upon call. I also added a command /customwheels so you can try it out by typing /customwheels [tilt] [scale] Anyway, have fun, either one works, whichever you like the best. I also cleaned up and commented the code just because people might be interested in this, so it's better if this is cleaned up for future reference. For you specifically, the fix would be to look into the calculateVehicleWheelRotation function, which shows how I've attached the custom wheel to the vehicle. Those contents should replace your attachElements, because attachElements doesn't work, you have to attach manually with position and rotation... Client-side -- Table containing vehicles that have custom wheels local createdCustomWheels = { } --[[ /customwheels [ number tilt, number scale ] Adds custom wheels to your currently occupied vehicle and optionally applies a tilt angle and wheel scale. ]] addCommandHandler( 'customwheels', function( _, tilt, scale ) -- Let's get our vehicle local vehicle = getPedOccupiedVehicle( localPlayer ) -- Oh, we have a vehicle! if ( vehicle ) then -- Let's give it a wheel now addVehicleCustomWheel( vehicle, 1075, tilt, scale ) end end ) -- Let's bind that command to F2 as requested by OP bindKey( 'f2', 'down', 'customwheels' ) --[[ void addVehicleCustomWheel ( vehicle vehicle, number model [ , number tilt, number scale ] ) Adds custom wheels to the vehicle. ]] function addVehicleCustomWheel( vehicle, model, tilt, scale ) -- If we've given the object's model number if ( tonumber( model ) ) then -- Let's delete any old ones for _, wheel in pairs( createdCustomWheels[ vehicle ] or { } ) do destroyElement( wheel.object ) end -- And let's nil it to be clear createdCustomWheels[ vehicle ] = nil -- Let's set some component names we want to customize local wheels = { 'wheel_lf_dummy', 'wheel_rf_dummy' } -- Let's iterate through those components for i = 1, #wheels do -- Let's hide the existing component setVehicleComponentVisible( vehicle, wheels[ i ], false ) -- Initialize our wheel table local wheel = { tilt = tonumber( tilt ) or 0, -- We'll default a non-number tilt angle to 0 name = wheels[ i ], -- Let's store the component name object = createObject( model, Vector3( ) ) -- Let's make a new wheel object } -- Let's set the vehicle as the wheel object's parent setElementParent( wheel.object, vehicle ) -- Let's make sure the wheel is not colliding with the vehicle setElementCollidableWith( wheel.object, vehicle, false ) -- Let's change the scale setObjectScale( wheel.object, tonumber( scale ) or 0.7 ) -- Let's update that original table wheels[ i ] = wheel end -- And let's store all of those wheels now createdCustomWheels[ vehicle ] = wheels end end --[[ void calculateVehicleWheelRotation ( vehicle vehicle, table wheel ) Let's calculate the wheel rotation for given wheel(s). ]] function calculateVehicleWheelRotation( vehicle, wheel ) -- If we have many wheels in the given argument if ( type( wheel ) == 'table' ) and ( #wheel > 0 ) then -- Let's iterate through them all for i = 1, #wheel do -- Let's call the method alone with just the iterator calculateVehicleWheelRotation( vehicle, wheel[ i ] ) end -- Let's stop here now return end -- If we have an object if ( wheel.object ) then -- Let's get the rotation vector of the original component local rotation = Vector3( getVehicleComponentRotation( vehicle, wheel.name, 'world' ) ) -- Let's set our tilt angle rotation.y = wheel.tilt -- Let's make sure the wheel is at the original component's position setElementPosition( wheel.object, Vector3( getVehicleComponentPosition( vehicle, wheel.name, 'world' ) ) ) -- Let's finally set the rotation (in ZYX order, important!) setElementRotation( wheel.object, rotation, "ZYX" ) end end -- Render-time! addEventHandler( 'onClientPreRender', root, function( ) -- Let's iterate through all the vehicles for vehicle, wheels in pairs( createdCustomWheels ) do -- If we have a vehicle, it's streamed in and it has wheels if ( vehicle ) and ( isElementStreamedIn( vehicle ) ) and ( #wheels > 0 ) then -- Let's calculate wheel rotation! calculateVehicleWheelRotation( vehicle, wheels ) end end end ) Client-side (OOP) -- Table containing vehicles that have custom wheels local createdCustomWheels = { } --[[ /customwheels [ number tilt, number scale ] Adds custom wheels to your currently occupied vehicle and optionally applies a tilt angle and wheel scale. ]] addCommandHandler( 'customwheels', function( _, tilt, scale ) -- Let's get our vehicle local vehicle = localPlayer:getOccupiedVehicle( ) -- Oh, we have a vehicle! if ( vehicle ) then -- Let's give it a wheel now vehicle:addCustomWheel( 1075, tilt, scale ) end end ) -- Let's bind that command to F2 as requested by OP bindKey( 'f2', 'down', 'customwheels' ) --[[ void Vehicle:addCustomWheel ( number model [ , number tilt, number scale ] ) Adds custom wheels to the vehicle. ]] function Vehicle:addCustomWheel( model, tilt, scale ) -- If we've given the object's model number if ( tonumber( model ) ) then -- Let's delete any old ones for _, wheel in pairs( createdCustomWheels[ self ] or { } ) do wheel.object:destroy( ) end -- And let's nil it to be clear createdCustomWheels[ self ] = nil -- Let's set some component names we want to customize local wheels = { 'wheel_lf_dummy', 'wheel_rf_dummy' } -- Let's iterate through those components for i = 1, #wheels do -- Let's hide the existing component self:setComponentVisible( wheels[ i ], false ) -- Initialize our wheel table local wheel = { tilt = tonumber( tilt ) or 0, -- We'll default a non-number tilt angle to 0 name = wheels[ i ], -- Let's store the component name object = Object( model, Vector3( ) ) -- Let's make a new wheel object } -- Let's set the vehicle as the wheel object's parent wheel.object:setParent( self ) -- Let's make sure the wheel is not colliding with the vehicle wheel.object:setCollidableWith( self, false ) -- Let's change the scale wheel.object:setScale( tonumber( scale ) or 0.7 ) -- Let's update that original table wheels[ i ] = wheel end -- And let's store all of those wheels now createdCustomWheels[ self ] = wheels end end --[[ void Vehicle:calculateWheelRotation ( table wheel ) Let's calculate the wheel rotation for given wheel(s). ]] function Vehicle:calculateWheelRotation( wheel ) -- If we have many wheels in the given argument if ( type( wheel ) == 'table' ) and ( #wheel > 0 ) then -- Let's iterate through them all for i = 1, #wheel do -- Let's call the method alone with just the iterator self:calculateWheelRotation( wheel[ i ] ) end -- Let's stop here now return end -- If we have an object if ( wheel.object ) then -- Let's get the rotation vector of the original component local rotation = Vector3( self:getComponentRotation( wheel.name, 'world' ) ) -- Let's set our tilt angle rotation.y = wheel.tilt -- Let's make sure the wheel is at the original component's position wheel.object:setPosition( self:getComponentPosition( wheel.name, 'world' ) ) -- Let's finally set the rotation wheel.object:setRotation( rotation ) end end -- Render-time! addEventHandler( 'onClientPreRender', root, function( ) -- Let's iterate through all the vehicles for vehicle, wheels in pairs( createdCustomWheels ) do -- If we have a vehicle, it's streamed in and it has wheels if ( vehicle ) and ( vehicle:isStreamedIn( ) ) and ( #wheels > 0 ) then -- Let's calculate wheel rotation! vehicle:calculateWheelRotation( wheels ) end end end ) Edited January 12, 2017 by myonlake 3 Link to comment
Jayceon Posted January 12, 2017 Author Share Posted January 12, 2017 Big thanks to you. I'm now very happy. Thank you. Link to comment
myonlake Posted January 12, 2017 Share Posted January 12, 2017 2 minutes ago, Jayceon said: Big thanks to you. I'm now very happy. Thank you. You're welcome. Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now