Salem Posted April 23, 2012 Share Posted April 23, 2012 Hi. I'd like to ask you about a function which could return the type of ground/surface I'm using at the moment. Was searching some on wiki but cannot find any similar. It'd be useful for me in constructing handling script for cars using so much gravel/grass during race. Anyway, in stead of getGroundType it could be also something which returns sound, which is actually hearing while driving thru different types of ground. Any ideas guys? Link to comment
Salem Posted April 23, 2012 Author Share Posted April 23, 2012 mhm, thanks. This function looks so complicated and it is said: "This function is relatively expensive to call, so over use of this in scripts may have a detrimental effect on performance." It probably lower fps so critically. Anyway I going to study this and see how it will work. It would be helpful to limit the area of processing to the objects being in contact with the car only, but I'm not so strong in LUA, and don't know how to do it at the moment. Anyway, thanks. By the way, is it possible to use 'getPedContactElement' to obtain some data from the ground? Link to comment
Puma Posted April 23, 2012 Share Posted April 23, 2012 Depends on what data you want to get. It only returns the object/vehicle the ped is standing on. You can then use the returned element to request the data, such as position, alpha, dimension etcetera. As far as I know, there is no function that returns data that implicates whether you're standing on grass, sand or concrete, for example. Link to comment
Kenix Posted April 23, 2012 Share Posted April 23, 2012 material: an integer representing the GTASA material ID of the surface hit when applicable (world, objects) Link to comment
Salem Posted April 27, 2012 Author Share Posted April 27, 2012 Eh! I used these functions, but really cannot get any satisfying result. In following code: -- PLAYER COLIZION addEventHandler( 'onClientRender', getRootElement(), function( ) local px, py, pz = getElementPosition( me ); local hit, x, y, z, elementHit, nx, ny, nz, material, li, pi, worldID = processLineOfSight( px, py, 2, px, py, -1000, true, false, false, true, false, false, false, false, me, true ) if hit then if elementHit then outputChatBox( "Hit element: "..getElementType( elementHit )..", material: "..tostring( material )..", world ID: "..tostring( worldID ) ); end else --setTimer( outputChatBox, 10000, 0, "Nothing het." ); end end ); nothing happens. I was changing coordinates, parameters, using camera and screen coords, etc., but no effect. Function with getting collisions does work for vehicles and maybe some objects, but not world ones. Does anyone have an experience with this functions or have done something similar? I guess the Client must know the surface. He returns different sounds and other reactions. Also produces a bug in custom handling made by 'setVehicleHandling...' while driving on some kinds of sand, but it can be GTA problem, i don't know this so well. Link to comment
qaisjp Posted April 27, 2012 Share Posted April 27, 2012 Try this test code, may or may not work, as it is untested. local materials = { [0] = 'Default' } addCommandHandler ( 'los', function ( ) local x, y, z = getElementPosition ( localPlayer ) local gx,gy,gz = getGroundPosition ( localPlayer ) if not gx then outputChatBox ( 'No ground!' ) return end local hit, _,_,_,ele,_,_,_,material = processLineOfSight ( x,y,z, gx,gy,gz-10, true,false,false,false,false,true,true,true,localPlayer, true) if not hit then outputChatBox( ' Has not collided' ) return end if ele then outputChatBox('Collided with created object (not world object)') return end if not material then outputChatBox('Unknown material') return end if materials[material] then outputChatBox('Material found: '..materials[material]..' ('..material..')') return end outputChatBox('Material found: '..material) end) sry for spaghetti, made it from quick reply Link to comment
iChang Posted April 27, 2012 Share Posted April 27, 2012 MTA's map editor has a way to get the ID of a world object. I'd suggest: Take look in the the editor_main resource. Link to comment
qaisjp Posted April 27, 2012 Share Posted April 27, 2012 MTA's map editor has a way to get the ID of a world object.I'd suggest: Take look in the the editor_main resource. same method i used (with a few missed out components which arent needed here) Link to comment
Salem Posted May 9, 2012 Author Share Posted May 9, 2012 Thanks guys, everything works perfectly. The new real handling doesn't allow to speeding throung the sand, decreases grip on grass, etc. Great. The files are so long, but I can paste some fragments if someone wants. Now, I'm going to do some tyres events, usage and damaging options. It could be helpful to know some states of wheels, I mean, for example, if the car loses the grip or not. Link to comment
qaisjp Posted May 11, 2012 Share Posted May 11, 2012 Wow that looks nice, how do you handle it? Do you use onClientRender, because triggering server events on each user frame is extremely redundant. Link to comment
Salem Posted May 11, 2012 Author Share Posted May 11, 2012 Yes, everything is handled by client rendering, but it's not such a beast as i thought before (Pentium 4, 2x3GHz core). Script changes cars' handling only once while changing ground type, so maximaly, for example, once a second or twice. Some code: addEventHandler( "onClientPreRender", root, function ( ) --............................ -- this lower the speed if ( isVehicleOnGround( veh ) and getElementData( veh, 'handled' ) == true ) then if a_type > 0 then if ( a_type == 1 and speed > 100 ) then -- concrete setElementVelocity( veh, velX-velX/200, velY-velY/200, velZ ) elseif ( a_type == 2 and speed > 50 ) then -- gravel setElementVelocity( veh, velX-velX/75, velY-velY/75, velZ ) elseif ( a_type == 3 and speed > 25 ) then -- grass setElementVelocity( veh, velX-velX/50, velY-velY/50, velZ ) elseif ( a_type == 4 and speed > 50 ) then -- dirt setElementVelocity( veh, velX-velX/100, velY-velY/100, velZ ) elseif ( a_type == 5 and speed > 25 ) then -- sand setElementVelocity( veh, velX-velX/25, velY-velY/25, velZ ) elseif ( a_type == 7 and speed > 50 ) then -- wood setElementVelocity( veh, velX-velX/150, velY-velY/150, velZ ) elseif ( a_type == 10 and speed > 25 ) then -- vegetation setElementVelocity( veh, velX-velX/30, velY-velY/30, velZ ) elseif ( a_type == 11 and speed > 0 ) then -- water setElementVelocity( veh, velX-velX/10, velY-velY/10, velZ ) elseif ( a_type == 12 and speed > 50 ) then -- misc setElementVelocity( veh, velX-velX/125, velY-velY/125, velZ ) end; if a_change ~= a_type then local x = getSurfaceHandle( a_type ) setHandlingChanges( veh, x, true ) a_change = a_type end; else if a_change ~= a_type then setHandlingChanges( veh, _, false ) a_change = a_type; end; --setVehicleHandling( veh, "tractionMultiplier", a_traction ) -- --end; end; end; --..................................... local material = getMaterial( X0, Y0, Z0 ) if ( a_material ~= material ) then local a_text = ''; local m_type = 0; if material >= 0 then m_type = MATERIALS[material+1][2]; --outputChatBox( 'Material: '..MATERIALS[material+1][1]..', type: '..material_types[m_type+1]..' ('..m_type..'), ID: '..material ) -- output on surface change only a_text = 'TERRAIN: '..MATERIALS[material+1][1]..' [iD: '..material..'], type: '..material_types[m_type+1]..' [iD: '..m_type..']'; else if material == -1 then a_text = 'No ground!' elseif material == -2 then a_text = 'Has not collided' elseif material == -3 then a_text = 'Collided with created object (not world object)' elseif material == -4 then a_text = 'Unknown material' end; end ); end; guiSetText( guiGroundLabel, a_text ); --guiLabelSetColor( guiGroundLabel, 255 - math.ceil ( FPSCalc * FPSLimit ), math.ceil ( FPSCalc * FPSLimit ), 0 ) a_type = m_type; end; a_material = material; -- FUNCTIONS function getSurfaceHandle( type ) if type == 1 then return 1.2 -- concrete elseif type == 2 then return 1.25 -- gravel elseif type == 3 then return 2.5 -- grass elseif type == 4 then return 1.5 -- dirt elseif type == 5 then return 2 -- sand elseif type == 7 then return 1.75 -- wood elseif type == 10 then return 2.25 -- veget elseif type == 11 then return 2.75 -- water elseif type == 12 then return 1.1 -- misc else return 1 end; end; function getMaterial( x, y, z ) if x then local gz = getGroundPosition( x, y, z ) if not gz then --outputChatBox( 'No ground!' ) return -1 end local hit, _,_,_,ele,_,_,_,material = processLineOfSight( x,y,z, x,y,gz-10, true,false,false,true,false,true,true,true,localPlayer, true ) if not hit then --outputChatBox( 'Has not collided' ) return -2 end if ele then --outputChatBox( 'Collided with created object (not world object)' ) return -3 end if not material then --outputChatBox( 'Unknown material' ) return -4 else return material end else return 0 end; end; It's quite wierd, and that's not everything of course, but on the other hand it's easy. The server side is complete: ---------------------------- HANDLING TEST ---------------------------- addEventHandler( "onVehicleEnter", getRootElement(), function( player, seat ) --local hset = { }; if seat == 0 then if getElementData( source, 'handled' ) == false then local mv = getVehicleHandling( source )["maxVelocity"]; setVehicleHandling( source, "maxVelocity", mv*2 ); --local ea = getVehicleHandling( source )["engineAcceleration"]; --setVehicleHandling( source, "engineAcceleration", ea-ea*0.1 ); local ei = getVehicleHandling( source )["engineInertia"]; setVehicleHandling( source, "engineInertia", ei*5 ); local bd = getVehicleHandling( source )["brakeDeceleration"]; setVehicleHandling( source, "brakeDeceleration", bd-bd*0.25 ); local sl = getVehicleHandling( source )["steeringLock"]; setVehicleHandling( source, "steeringLock", sl-sl*0.2 ); local tl = getVehicleHandling( source )["tractionLoss"]; setVehicleHandling( source, "tractionLoss", tl-tl*0.3 ); local tr = getVehicleHandling( source )["tractionMultiplier"]; local s_tr = tr+tr*0.5; setVehicleHandling( source, "tractionMultiplier", s_tr ); -- using in dynamic handling local tm = getVehicleHandling( source )["turnMass"]; setVehicleHandling( source, "turnMass", tm*1.25 ); local m = getVehicleHandling( source )["mass"]; setVehicleHandling( source, "mass", m*1.2 ); local dc = getVehicleHandling( source )["dragCoeff"]; setVehicleHandling( source, "dragCoeff", dc*0.5 ); -- wtfs setVehicleHandling( source, "ABS", true ); setVehicleHandling( source, "headLight", 1 ); setVehicleHandling( source, "tailLight", 1 ); setElementData( source, 'handled', true ); -- send values setted setElementData( source, "s_tractionMultiplier", s_tr ); else local o_tr = getElementData( source, "s_tractionMultiplier" ); local g_tr = getVehicleHandling( source )["tractionMultiplier"]; if g_tr ~= o_tr then setVehicleHandling( source, "tractionMultiplier", o_tr ) end; end; outputChatBox( '* Handling: maxV='..string.format( '%d', getVehicleHandling( source )["maxVelocity"] )..', engAcc='..string.format( '%d', getVehicleHandling( source )["engineAcceleration"] )..', engIn='..string.format( '%d', getVehicleHandling( source )["engineInertia"] )..', brkDecc='..string.format( '%d', getVehicleHandling( source )["brakeDeceleration"] )..', steerL='..string.format( '%d', getVehicleHandling( source )["steeringLock"] ), player, 20, 200, 50 ); end; end ); addEvent( 'changeHandling', true ); addEventHandler( 'changeHandling', root, function( veh, x, state ) local y = getElementData( veh, "s_tractionMultiplier" ); if state == true then setVehicleHandling( veh, "tractionMultiplier", y/x ); --outputChatBox( '* tr = '..string.format( '%.2f', y/x ), source ); else setVehicleHandling( veh, "tractionMultiplier", y ); --outputChatBox( '* tr = '..string.format( '%.2f', y ), source ); end; end ); addCommandHandler( 'abs', function( player ) -- test - dunno if it works if isPedInVehicle( player ) then local veh = getPedOccupiedVehicle( player ); if getVehicleHandling( veh )[ "ABS" ] == true then setVehicleHandling( veh, "ABS", false ) outputChatBox( '* ABS turned off.', player, 150, 50, 50 ); else setVehicleHandling( veh, "ABS", true ) outputChatBox( '* ABS turned on.', player, 150, 50, 50 ); end; else outputChatBox( '* Be in vehicle.', player ); end; end ); And very important table (it's client side, but it can be probably server side also), just copied from wiki (materials): [materials.lua] material_types = { 'Default', 'Concrete', 'Gravel', 'Grass', 'Dirt', 'Sand', 'Glass', 'Wood', 'Metal', 'Stone', 'Vegetation', 'Water', 'Misc' }; --[0..12] MATERIALS = { --[0..178] [ 'Name', type ] { 'Default', 0 }, { 'Tarmac', 0 }, { 'Tarmac (fucked)', 0 }, { 'Tarmac (really fucked)', 0 }, { 'Pavement', 1 }, { 'Pavement (fucked)', 1 }, { 'Gravel', 2 }, { 'Concrete (fucked)', 1 }, { 'Painted Ground', 1 }, { 'Grass (short lush)', 3 }, { 'Grass (medium lush)', 3 }, { 'Grass (long lush)', 3 }, { 'Grass (short dry)', 3 }, { 'Grass (medium dry)', 3 }, { 'Grass (long dry)', 3 }, { 'Golf Grass (rough)', 3 }, { 'Golf Grass (smooth)', 3 }, { 'Steep Slidy Grass', 3 }, { 'Steep Cliff', 9 }, { 'Flower Bed', 4 }, { 'Meadow', 3 }, { 'Waste Ground', 4 }, { 'Woodland Ground', 4 }, { 'Vegetation', 10 }, { 'Mud (wet)', 4 }, { 'Mud (dry)', 4 }, { 'Dirt', 4 }, { 'Dirt Track', 4 }, { 'Sand (deep)', 5 }, { 'Sand (medium)', 5 }, { 'Sand (compact)', 5 }, { 'Sand (arid)', 5 }, { 'Sand (more)', 5 }, { 'Sand (beach)', 5 }, { 'Concrete (beach)', 1 }, { 'Rock (dry)', 9 }, { 'Rock (wet)', 9 }, { 'Rock (cliff)', 9 }, { 'Water (riverbed)', 11 }, { 'Water (shallow)', 11 }, { 'Corn Field', 4 }, { 'Hedge', 10 }, { 'Wood (crates)', 7 }, { 'Wood (solid)', 7 }, { 'Wood (thin)', 7 }, { 'Glass', 6 }, { 'Glass Windows (large)', 6 }, { 'Glass Windows (small)', 6 }, { 'Empty1', 12 }, { 'Empty2', 12 }, { 'Garage Door', 8 }, { 'Thick Metal Plate', 8 }, { 'Scaffold Pole', 8 }, { 'Lamp Post', 8 }, { 'Metal Gate', 8 }, { 'Metal Chain fence', 8 }, { 'Girder', 8 }, { 'Fire Hydrant', 8 }, { 'Container', 8 }, { 'News Vendor', 8 }, { 'Wheelbase', 12 }, { 'Cardboard Box', 12 }, { 'Ped', 12 }, { 'Car', 8 }, { 'Car (panel)', 8 }, { 'Car (moving component)', 8 }, { 'Transparent Cloth', 12 }, { 'Rubber', 12 }, { 'Plastic', 12 }, { 'Transparent Stone', 9 }, { 'Wood (bench)', 7 }, { 'Carpet', 12 }, { 'Floorboard', 7 }, { 'Stairs (wood)', 7 }, { 'Sand', 5 }, { 'Sand (dense)', 5 }, { 'Sand (arid)', 5 }, { 'Sand (compact)', 5 }, { 'Sand (rocky)', 5 }, { 'Sand (beach)', 5 }, { 'Grass (short)', 3 }, { 'Grass (meadow)', 3 }, { 'Grass (dry)', 3 }, { 'Woodland', 4 }, { 'Wood Dense', 4 }, { 'Roadside', 2 }, { 'Roadside Des', 5 }, { 'Flowerbed', 4 }, { 'Waste Ground', 4 }, { 'Concrete', 1 }, { 'Office Desk', 12 }, { '711 Shelf 1', 12 }, { '711 Shelf 2', 12 }, { '711 Shelf 3', 12 }, { 'Restuarant Table', 12 }, { 'Bar Table', 12 }, { 'Underwater (lush)', 5 }, { 'Underwater (barren)', 5 }, { 'Underwater (coral)', 5 }, { 'Underwater (deep)', 5 }, { 'Riverbed', 4 }, { 'Rubble', 2 }, { 'Bedroom Floor', 12 }, { 'Kitchen Floor', 12 }, { 'Livingroom Floor', 12 }, { 'corridor Floor', 12 }, { '711 Floor', 12 }, { 'Fast Food Floor', 12 }, { 'Skanky Floor', 12 }, { 'Mountain', 9 }, { 'Marsh', 4 }, { 'Bushy', 10 }, { 'Bushy (mix)', 10 }, { 'Bushy (dry)', 10 }, { 'Bushy (mid)', 10 }, { 'Grass (wee flowers)', 3 }, { 'Grass (dry tall)', 3 }, { 'Grass (lush tall)', 3 }, { 'Grass (green mix)', 3 }, { 'Grass (brown mix)', 3 }, { 'Grass (low)', 3 }, { 'Grass (rocky)', 3 }, { 'Grass (small trees)', 3 }, { 'Dirt (rocky)', 4 }, { 'Dirt (weeds)', 4 }, { 'Grass (weeds)', 3 }, { 'River Edge', 4 }, { 'Poolside', 1 }, { 'Forest (stumps)', 4 }, { 'Forest (sticks)', 4 }, { 'Forest (leaves)', 4 }, { 'Desert Rocks', 5 }, { 'Forest (dry)', 4 }, { 'Sparse Flowers', 4 }, { 'Building Site', 2 }, { 'Docklands', 1 }, { 'Industrial', 1 }, { 'Industrial Jetty', 1 }, { 'Concrete (litter)', 1 }, { 'Alley Rubbish', 1 }, { 'Junkyard Piles', 2 }, { 'Junkyard Ground', 4 }, { 'Dump', 4 }, { 'Cactus Dense', 5 }, { 'Airport Ground', 1 }, { 'Cornfield', 4 }, { 'Grass (light)', 3 }, { 'Grass (lighter)', 3 }, { 'Grass (lighter 2)', 3 }, { 'Grass (mid 1)', 3 }, { 'Grass (mid 2)', 3 }, { 'Grass (dark)', 3 }, { 'Grass (dark 2)', 3 }, { 'Grass (dirt mix)', 3 }, { 'Riverbed (stone)', 9 }, { 'Riverbed (shallow)', 4 }, { 'Riverbed (weeds)', 4 }, { 'Seaweed', 5 }, { 'Door', 12 }, { 'Plastic Barrier', 12 }, { 'Park Grass', 3 }, { 'Stairs (stone)', 9 }, { 'Stairs (metal)', 8 }, { 'Stairs (carpet)', 12 }, { 'Floor (metal)', 8 }, { 'Floor (concrete)', 1 }, { 'Bin Bag', 12 }, { 'Thin Metal Sheet', 8 }, { 'Metal Barrel', 8 }, { 'Plastic Cone', 12 }, { 'Plastic Dumpster', 12 }, { 'Metal Dumpster', 8 }, { 'Wood Picket Fence', 7 }, { 'Wood Slatted Fence', 7 }, { 'Wood Ranch Fence', 7 }, { 'Unbreakable Glass', 6 }, { 'Hay Bale', 12 }, { 'Gore', 12 }, { 'Rail Track', 12 } }; On the screen GUI shows actual surface (dunno if it's in this code above) and everything works fine. You can of course change these parameters which handle the preferences to get stronger or weaker forces, or add some others, and the performance is (for me) exactly the same as without this. It's nice fun, try something like this yourself Note that programming like this (a bit of chaos included) causes many bugs, and it's recomended to fight'em to have really good and deliberate results. 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