Jump to content

getGroundType


Salem

Recommended Posts

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

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. :D

By the way, is it possible to use 'getPedContactElement' to obtain some data from the ground?

Link to comment

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

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

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
  • 2 weeks later...

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

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

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...