VE Lua Documentation

Press F to search!

updateGFX

Definition


-- @/lua/vehicle/sounds.lua:219

local function updateGFX(dt)
  --crash sounds
  crashSoundTimer = crashSoundTimer + dt
  if crashSoundTimer > 0.04 then
    crashSoundTimer = 0
    local impactEnergy, breakEnergy, breakNode, mat1, mat2 = obj:getImpactDeformEnergyNode()
    -- if not (scrapeAbsorbing[mat1] or scrapeAbsorbing[mat2]) then // removed because it was stopping some small impacts from happening as the system thinks it's a scrape
    -- local volImpact = impactEnergy / (impactEnergy + 6)
    impactEnergy = impactEnergy * impactSoundVolumeCoef
    local volImpact = impactEnergy / (impactEnergy + 4.5)
    -- local volBreak = breakEnergy / (breakEnergy + 1000)
    local volBreak = breakEnergy / (breakEnergy + 600)
    -- if volImpact > volBreak then
    if ((volImpact + 0.01) * 3) > volBreak then
      if volImpact > 0.004 then
        if (mat1 == 3 or mat2 == 3) then
          local nodeImpactPlasticEvent = v.data.nodes[breakNode].impactPlasticEvent or impactPlasticEvent
          if nodeImpactPlasticEvent then
            --print(string.format("%d: Impact Plastic (%.2f) -> %q", objectId, volImpact, nodeImpactPlasticEvent))
            -- print (string.format(" PLASTIC IMPACT / mat1=%.2d / mat2=%.2d / impactEnergy=%9.2f / breakEnergy=%9.2f / volImpact=%.3f  ", mat1, mat2, impactEnergy, breakEnergy, volImpact))
            sounds.playSoundOnceFollowNode(nodeImpactPlasticEvent, breakNode, volImpact)
          end
        elseif (mat1 == 2 or mat2 == 2) then
          local nodeImpactMetalEvent = v.data.nodes[breakNode].impactMetalEvent or impactMetalEvent
          if nodeImpactMetalEvent then
            --print(string.format("%d: Impact Metal (%.2f) -> %q", objectId, volImpact, nodeImpactMetalEvent))
            --print (string.format("    PART IMPACT / mat1=%.2d / mat2=%.2d / impactEnergy=%9.2f / breakEnergy=%9.2f /                 / volImpact=%.3f  ", mat1, mat2, impactEnergy, breakEnergy, volImpact))
            sounds.playSoundOnceFollowNode(nodeImpactMetalEvent, breakNode, volImpact)
          end
        else
          local nodeImpactGenericEvent = v.data.nodes[breakNode].impactGenericEvent or impactGenericEvent
          if nodeImpactGenericEvent then
            --print(string.format("%d: Impact Generic (%.2f) -> %q", objectId, volImpact, nodeImpactGenericEvent))
            -- print (string.format(" GENERIC IMPACT / mat1=%.2d / mat2=%.2d / impactEnergy=%9.2f / breakEnergy=%9.2f /                 / volImpact=%.3f  ", mat1, mat2, impactEnergy, breakEnergy, volImpact))
            sounds.playSoundOnceFollowNode(nodeImpactGenericEvent, breakNode, volImpact)
          end
        end
      end
    else
      if volBreak > 0.004 then
        if (mat1 == 3 and mat2 == 3) then
          local nodeBreakPlasticEvent = v.data.nodes[breakNode].breakPlasticEvent or breakPlasticEvent
          if nodeBreakPlasticEvent then
            --print(string.format("%d: Break Plastic (%.2f) -> %q", objectId, volBreak, nodeBreakPlasticEvent))
            sounds.playSoundOnceFollowNode(nodeBreakPlasticEvent, breakNode, volBreak)
          end
        else
          local nodeBreakGenericEvent = v.data.nodes[breakNode].breakGenericEvent or breakGenericEvent
          if nodeBreakGenericEvent then
            --print(string.format("%d: Break Generic (%.2f) -> %q", objectId, volBreak, nodeBreakGenericEvent))
            sounds.playSoundOnceFollowNode(nodeBreakGenericEvent, breakNode, volBreak)
          end
        end
      -- print (string.format("     PART BREAK / mat1=%.2d / mat2=%.2d / impactEnergy=%9.2f / breakEnergy=%9.2f /                 /                 / volBreak=%.3f ", mat1, mat2, impactEnergy, breakEnergy, volBreak))
      end
    end
  -- end
  end

  -- sound bank
  for _, snd in pairs(soundBank.sounds) do
    if snd.active then
      local val = getSourceValue(snd.source) or 0
      val = snd.factor * (val + snd.offset)
      snd.lastVal = val

      local sndVol = 0

      --check volume conditions
      if val < snd.volumeBlendInStartValue or val > snd.volumeBlendOutEndValue then
        sndVol = snd.minVolume
      end
      if val > snd.volumeBlendInStartValue and val < snd.volumeBlendInEndValue then
        --blend in volume
        sndVol = lerp(snd.minVolume, snd.maxVolume, (val - snd.volumeBlendInStartValue) / (snd.volumeBlendInEndValue - snd.volumeBlendInStartValue))
      elseif val > snd.volumeBlendInEndValue and val < snd.volumeBlendOutStartValue then
        sndVol = snd.maxVolume
      elseif val > snd.volumeBlendOutStartValue and val < snd.volumeBlendOutEndValue then
        --blend out volume
        sndVol = lerp(snd.minVolume, snd.maxVolume, (((val - snd.volumeBlendOutStartValue) / (snd.volumeBlendOutEndValue - snd.volumeBlendOutStartValue)) - 1) * -1)
      end

      --apply modifiers if applicable
      for _, s in pairs(snd.volumeModifiers) do
        sndVol = sndVol * getSoundModifier(s)
      end

      --blend pitch
      local sndPitch = lerp(snd.minPitch, snd.maxPitch, clamp((val - snd.pitchBlendInStartValue) / (snd.pitchBlendInEndValue - snd.pitchBlendInStartValue), 0, 1))

      for _, s in pairs(snd.pitchModifiers) do
        sndPitch = sndPitch * getSoundModifier(s)
      end

      snd.clip:setVolumePitch(sndVol, sndPitch)
    end
  end

  beamResetTimer = min(beamResetTimer + dt, 1)

  -- beam sounds, suspension
  local maxStressVolume = 0
  for bi, snd in ipairs(beamSounds) do
    local beamVel = obj:getBeamVelocity(snd.beam)

    -- noise filter
    snd.noiseTrail = snd.noiseTrail + beamVel * dt
    if abs(snd.noiseTrail) < snd.noiseFactor then
      beamVel = 0
    else
      snd.noiseTrail = signApply(snd.noiseTrail, snd.noiseFactor)
    end

    beamVel = min(1, abs(beamVel))
    local currentStress = clamp(obj:getBeamStress(snd.beam) / snd.maxStress, -1, 1) * beamVel * beamVel -- find the stress on the current sound beam (unsmoothed)
    -- local currentStress = clamp(obj:getBeamStress(snd.beam), -1, 1) * beamVel * beamVel -- find the stress on the current sound beam (unsmoothed)
    local smoothStress = snd.smoothing:get(currentStress, dt)
    local impulse = min(abs(smoothStress - currentStress), abs(smoothStress)) -- beam stress difference between instananeous stress and smooth stress
    -- local impulse = abs(currentStress)
    local volume = snd.volumeFactor * impulse -- normalize volume (cancel out maxStress factor)
    local pitch = (snd.pitchFactor * snd.volumeFactor) * impulse -- loud suspension sounds also gain a higher pitch

    snd.clip:setVolumePitch(volume * beamResetTimer, pitch, snd.colorFactor)
    maxStressVolume = max(maxStressVolume, volume)

    -- store the outputs so we can view with vehicle editor
    snd.impulse = impulse
    snd.pitch = pitch
    snd.volume = volume

    -- Audio Debug. DON'T FORGET THERE IS SMOOTHING ON THE VOLUME RTPC WHICH ALTERS FINAL RESULT - VOLUME SMOOTHING IS NOW TURNED OFF
    -- streams.drawGraph('susp VOL w'..bi..' '..snd.volumeFactor, {value = volume, min = 0, max = 1})
    -- streams.drawGraph('w'..bi, {value = -smoothStress, min = 0, max = 1})
    -- if volume >= 0.01 then print (string.format(" Suspension%.0f   currentStress %.2f x smoothStress %.2f x volumeFactor %.2f = Volume=%.2f  Impulse=%.2f  Pitch=%.2f  colorFactor=%.2f  beamResetTimer=%.2f", bi, currentStress, smoothStress, snd.volumeFactor, volume, impulse, pitch, snd.colorFactor, beamResetTimer)); end

    -- -- one shot cabin rattles
    -- -- Teri - things required please - the event needs to be set per vehicle, potentially in x_interior.jbeam - also, should the emitters be on different nodes (they are currently set as suspension.
    -- rattleSoundTimer = rattleSoundTimer + dt
    -- if rattleSoundTimer > 0.08 then
    -- rattleSoundTimer = 0
    -- if volume > 0.25 then
    -- volume = linearScale(volume,0.25,0.95,0,1)
    -- sounds.playSoundOnceAtNode("event:>Vehicle>Interior>Rattles>car>multi_test", 0, volume)
    -- print (volume)
    -- end
    -- end
  end

  local aeroSpeed = obj:getAirflowSpeed() -- speed against wind

  -- wind
  if aeroSpeed > 3 and windSoundEvent then
    -- TODO: Find a better place to emit wind sounds. Maybe at the windows?
    if ai.mode ~= 'traffic' then
      windSound = windSound or createSoundObj(windSoundEvent, "AudioDefaultLoop3D", "WindTestSound", windSoundEventNode)
    end

    if windSound then
      --local vol = clamp(aeroSpeed * 0.015, 0, 1)
      local vol = aeroSpeed * 0.02
      --local pitch = clamp(aeroSpeed * 0.012, 0, 1) -- controls pitch of large buffet so goes up at a slower rate
      local pitch = aeroSpeed * 0.012
      windSound:setVolumePitch(vol, pitch)
    end
  -- print (string.format("WINDSPEED KPH=%.0f MPH=%.0f  Wind vol=%.2f  pitch=%.2f", (speed*3.657), (speed*2.285), vol, pitch))
  end

  -- wheels
  local groundSpeed = obj:getGroundSpeed()

  for wi, wd in pairs(wheels.wheels) do
    local wheelSound = wheelsSounds[wi]

    local rigidSurfaceType = 0 -- textureRTPC - asphalt=0.05, cobble=15, metal=0.25, wood=0.45
    local rigidRollVolume = 0
    local rigidRollPitch = 0
    local rigidRollColor = 0 -- unused
    local rigidSkidVolume = 0
    local rigidSkidPitch = 0
    local rigidSkidSlip = 0 -- colorRTPC

    local looseSurfaceType = 0 -- textureRTPC - dirt=0.05, grass=0.15, gravel=0.25
    local looseRollVolume = 0
    local looseRollPitch = 0
    local looseRollDepth = 0
    local looseSkidVolume = 0
    local looseSkidPitch = 0
    local looseSkidDepth = 0

    --shared calculations for most surfaces
    local absWheelSpeed = abs(wd.angularVelocity * wd.radius)
    local slip = wd.lastSlip * min(wd.downForce * 0.1, 1)
    local sideSlip = abs(wd.lastSideSlip)
    local tirePressure = sqrt(wd.downForce * 0.00002) --replacing tirePatchPressure so the tireGoem from tirePatchPressure can become a static RTPC. Was using a linear range of 0 - 30,000
    -- local vehicleWheelSpeedDiff = sign(absWheelSpeed - groundSpeed) * wd.lastSlip * 0.7
    local vehicleWheelSpeedDiff = absWheelSpeed - groundSpeed

    -- if wd.name == "RR" then print(string.format("RR skids = slip %6.3f / slipEnergy %6.3f / sideSlip %6.3f / lastSlip %0.3f", slip, wd.slipEnergy * 0.000005, sideSlip, wd.lastSlip * 0.0125)); end

    -- if wd.name == "RR" or wd.name == "RL" then streams.drawGraph(wd.name.." sideSlip", {value = sideSlip * 0.0125, min = 0, max = 0.3}); end

    --Release settings
    local vehicleWheelSpeedDiffSlip
    if vehicleWheelSpeedDiff > 0 then
      --vehicleWheelSpeedDiffSlip = (vehicleWheelSpeedDiff * 0.01 + sideSlip * 0.0125) * 0.5
      vehicleWheelSpeedDiffSlip = sideSlip * 0.0125
    else
      vehicleWheelSpeedDiffSlip = vehicleWheelSpeedDiff * 0.01
    end

    local mat, mat2 = wd.contactMaterialID1, wd.contactMaterialID2
    if mat == 4 then
      mat, mat2 = mat2, mat
    end
    local isRubberTire = mat2 == 4 and wd.hasTire -- if the tire is rubber
    local maxContactBase = obj:inWater(wd.node1) and math.huge or 0
    local maxContact = maxContactBase

    -- print (string.format(" wd.downf=%6.3d : tirePressure=%5.2f : wd.lastSlip*0.01=%7.3f : slip=%7.3f ; absWhlSpd=%6.1f/MPH%3.0f : c_tirePropVol=%6.3f, c_tirePropPit=%6.3f", wd.downForce, tirePressure, wd.lastSlip * 0.01, slip, absWheelSpeed, (absWheelSpeed*2.285), wheelSound.tirePropertiesVolRoll, wheelSound.tirePropertiesPitch).." "..wd.name)
    -- print (string.format("tireVolumePitch=%7.3f : wd.tireVolume=%7.3f : material=%2.0f : wd.contactDepth=%0.2f", wheelSound.tireVolumePitch, wd.tireVolume, mat, wd.contactDepth).." "..wd.name)

    -- streams.drawGraph(wd.name.." vehicleWheelSpeedDiffSlip", {value = vehicleWheelSpeedDiffSlip + 0.5, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." tirePressure", {value = tirePressure, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." slip", {value = slip, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." wd.downForce * 0.00002", {value = sqrt(wd.downForce * 0.00002), min = 0, max = 1})
    -- streams.drawGraph(wd.name.." lastSlip", {value = wd.lastSlip * 0.0125, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." slipEnergy", {value = wd.slipEnergy * 0.000005, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." sideSlip", {value = sideSlip * 0.0125, min = 0, max = 1})

    -- shows the differences between slip and spin/lock
    -- if wd.name == "RR" then
    -- streams.drawGraph(wd.name.." lastSlip", {value = wd.lastSlip * 0.0125, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." vehicleWheelSpeedDiff", {value = (vehicleWheelSpeedDiff * 0.01) + 0.5, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." tirePressure", {value = tirePressure, min = 0, max = 1})
    -- end

    -- RIGID asphalt
    local asphaltContactSmooth = wheelSound.asphaltContactSmoother:getUncapped(boolToNum[(mat == 10 or mat == 29) and wd.contactDepth == 0 and isRubberTire], dt)
    if asphaltContactSmooth > maxContact then
      maxContact = asphaltContactSmooth
      rigidSurfaceType = 0.025
      -- rigidRollVolume = min(10, absWheelSpeed * 0.015) * asphaltContactSmooth
      rigidRollVolume = min(1, max(abs(absWheelSpeed - slip), sideSlip) * 0.015) * asphaltContactSmooth
      rigidRollPitch = tirePressure
      rigidSkidVolume = slip * wheelSound.tirePropertiesSlip * 0.015 * asphaltContactSmooth
      -- rigidSkidVolume = slip * wheelSound.tirePropertiesSlip * asphaltContactSmooth
      -- rigidSkidVolume = sideSlip * wheelSound.tirePropertiesSlip * asphaltContactSmooth * 0.0125
      rigidSkidPitch = tirePressure
      rigidSkidSlip = vehicleWheelSpeedDiffSlip * wheelSound.tirePropertiesSlip

      --Mark Test lock spin on color, slide on something else skid asphalt v6a
      -- rigidSkidVolume = (sideSlip * 0.05) * wheelSound.tirePropertiesSlip * asphaltContactSmooth
      -- rigidSkidPitch = tirePressure
      -- rigidSkidSlip = vehicleWheelSpeedDiffSlip * wheelSound.tirePropertiesSlip * asphaltContactSmooth
      -- DON'T DELETE
      -- if wd.name == "RR" then
      -- if rigidRollVolume > 0.01  then print (string.format("ASPHAT KPH=%3.0f MPH=%3.0f / absWhlSpeed %5.1f / rollVolume %4.2f / RollPitch %4.2f / tirePressure%6.2f / Contact %.1f", (absWheelSpeed*3.656), (absWheelSpeed*2.285), absWheelSpeed, rigidRollVolume, rigidRollPitch, tirePressure, asphaltContactSmooth).." "..wd.name); end
      -- if rigidSkidVolume > 0.01 then print (string.format(" "..wd.name.." ".."Skid Volume %.2f : Pitch %.2f : Color(+0.5) %.2f : tirePressure %.2f : Slip %6.2f : wd.lastSlip %6.2f : wd.slipEnergy %6.0f", rigidSkidVolume, rigidSkidPitch, rigidSkidSlip + 0.5, tirePressure, slip, wd.lastSlip, wd.slipEnergy)); end
      -- end

      -- RIGID asphalt kickup
      local wheelPeripherySpeedKickup = max(slip * wheelSound.tirePropertiesKickup * 10, absWheelSpeed * wheelSound.tirePropertiesKickup * 1)
      wheelSound.looseSurfaceKickupLimit = wheelSound.looseSurfaceKickupLimit - dt * wheelPeripherySpeedKickup
      if wheelSound.looseSurfaceKickupLimit <= 0 and wheelPeripherySpeedKickup > 2 and wd.tireSoundVolumeCoef > 0 then
        local kickupVolume = min(1, wheelPeripherySpeedKickup * 0.01 * wheelSound.tirePropertiesKickup)
        playSoundOnceAtNode("event:>Surfaces>kickup_asphalt", wd.node1, kickupVolume * wd.tireSoundVolumeCoef, wheelSound.tirePropertiesVolRoll, wheelSound.tirePropertiesPitch, 1)
        wheelSound.looseSurfaceKickupLimit = randomGauss3() * 8 / wheelSound.tirePropertiesKickup
      -- print(string.format("KICKUP ASPHALT Vol=%.2f : Pitch=%.2f : Color=%.2f : tirePropertiesKickup=%.2f", kickupVolume, wheelSound.tirePropertiesVolRoll, wheelSound.tirePropertiesPitch, wheelSound.tirePropertiesKickup) .. " " .. wd.name)
      -- streams.drawGraph(wd.name.." kickupVolume", {value = kickupVolume, min = 0, max = 1})
      end
    end

    -- RIGID asphalt wet
    local asphaltwetContactSmooth = wheelSound.asphaltwetContactSmoother:getUncapped(boolToNum[mat == 11 and wd.contactDepth == 0 and isRubberTire], dt)
    if asphaltwetContactSmooth > maxContact then
      maxContact = asphaltwetContactSmooth
      rigidSurfaceType = 0.125
      -- rigidRollVolume = min(10, absWheelSpeed * 0.015) * asphaltwetContactSmooth
      rigidRollVolume = min(1, max(abs(absWheelSpeed - slip), sideSlip) * 0.015) * asphaltwetContactSmooth
      rigidRollPitch = tirePressure
      rigidSkidVolume = slip * wheelSound.tirePropertiesSlip * 0.025 * asphaltwetContactSmooth
      rigidSkidPitch = tirePressure
      rigidSkidSlip = vehicleWheelSpeedDiffSlip * wheelSound.tirePropertiesSlip
    -- if rigidSkidVolume > 0.01 then print (string.format(" ASPHALT WET SKID / rigidSkidVolume %.2f / rigidSkidPitch %.2f / rigidSkidColor(+0.5) %.2f", rigidSkidVolume, rigidSkidPitch, rigidSkidColor + 0.5).." "..wd.name); end
    end

    -- RIGID cobble stone
    local cobbleStoneContactSmooth = wheelSound.cobbleStoneContactSmoother:getUncapped(boolToNum[mat == 30 and wd.contactDepth == 0 and isRubberTire], dt)
    if cobbleStoneContactSmooth > maxContact then
      maxContact = cobbleStoneContactSmooth
      rigidSurfaceType = 0.175
      -- rigidRollVolume = min(1, max(absWheelSpeed, min(slip, groundSpeed)) * 0.025) * (randomGauss3() * 0.33 + 0.5) * cobbleStoneContactSmooth
      rigidRollVolume = min(1, max(abs(absWheelSpeed - slip), sideSlip) * 0.02) * cobbleStoneContactSmooth
      rigidRollPitch = tirePressure
      rigidSkidVolume = slip * wheelSound.tirePropertiesSlip * 0.025 * cobbleStoneContactSmooth
      rigidSkidPitch = tirePressure
      rigidSkidSlip = vehicleWheelSpeedDiffSlip * wheelSound.tirePropertiesSlip
    -- this should really do slip + sideSlip and keep the roll playing, and then slip on its own to mute the roll (for wheelspin)

    -- if slip > 1 and sideSlip < 0.05 then rigidRollVolume = rigidRollVolume * (aeroSpeed * 0.01) else
    -- if sideSlip > 0.05 then rigidRollVolume = rigidRollVolume * 0.25 else
    -- rigidRollVolume = rigidRollVolume
    -- end
    -- end

    -- if rigidSkidVolume > 0.01 then print (string.format(" COBBLE SKID / rigidSkidVolume %.2f / rigidSkidPitch %.2f / rigidSkidSlip(+0.5) %.2f", rigidSkidVolume, rigidSkidPitch, rigidSkidSlip + 0.5).." "..wd.name); end
    -- if rigidSkidVolume > 0.01 then print (string.format(" COBBLE SKID / slip %.2f / sideSlip %.2f / absWheelSpeed %.2f / aeroSpeed %.2f", slip, sideSlip * 0.0125, absWheelSpeed, aeroSpeed).." "..wd.name); end
    end

    -- RIGID ice
    local iceContactSmooth = wheelSound.iceContactSmoother:getUncapped(boolToNum[mat == 21 and wd.contactDepth == 0 and isRubberTire], dt)
    if iceContactSmooth > maxContact then
      maxContact = iceContactSmooth
      rigidSurfaceType = 0.225
      -- rigidRollVolume = min(1, absWheelSpeed * 0.015) * iceContactSmooth
      rigidRollVolume = min(1, max(abs(absWheelSpeed - slip), sideSlip) * 0.015) * iceContactSmooth
      rigidRollPitch = tirePressure
      rigidSkidVolume = slip * wheelSound.tirePropertiesSlip * 0.025 * iceContactSmooth
      rigidSkidPitch = tirePressure
      rigidSkidSlip = vehicleWheelSpeedDiffSlip * wheelSound.tirePropertiesSlip
    -- if rigidSkidVolume > 0.01 then print (string.format(" ICE SKID / rigidSkidVolume %.2f / rigidSkidPitch %.2f / rigidSkidSlip(+0.5) %.2f", rigidSkidVolume, rigidSkidPitch, rigidSkidSlip + 0.5).." "..wd.name); end
    end

    -- RIGID metal
    local metalContactSmooth = wheelSound.metalContactSmoother:getUncapped(boolToNum[mat == 2 and wd.contactDepth == 0 and isRubberTire], dt)
    if metalContactSmooth > maxContact then
      maxContact = metalContactSmooth
      rigidSurfaceType = 0.275
      -- rigidRollVolume = min(1, absWheelSpeed * 0.03) * metalContactSmooth
      rigidRollVolume = min(1, max(abs(absWheelSpeed - slip), sideSlip) * 0.02) * metalContactSmooth
      rigidRollPitch = tirePressure
      rigidSkidVolume = slip * wheelSound.tirePropertiesSlip * 0.025 * metalContactSmooth
      rigidSkidPitch = tirePressure
      rigidSkidSlip = vehicleWheelSpeedDiffSlip * wheelSound.tirePropertiesSlip
    -- if rigidSkidVolume > 0.01 then print (string.format(" METAL SKID / rigidSkidVolume %.2f / rigidSkidPitch %.2f / rigidSkidSlip(+0.5) %.2f", rigidSkidVolume, rigidSkidPitch, rigidSkidSlip + 0.5).." "..wd.name); end
    end

    -- RIGID wood
    local woodContactSmooth = wheelSound.woodContactSmoother:getUncapped(boolToNum[mat == 6 and wd.contactDepth == 0 and isRubberTire], dt)
    if woodContactSmooth > maxContact then
      maxContact = woodContactSmooth
      rigidSurfaceType = 0.375
      -- rigidRollVolume = min(1, max(absWheelSpeed, slip) * 0.025) * randomGauss3() * 0.66 * woodContactSmooth
      rigidRollVolume = min(1, max(abs(absWheelSpeed - slip), sideSlip) * 0.025) * woodContactSmooth
      rigidRollPitch = tirePressure
      rigidSkidVolume = slip * wheelSound.tirePropertiesSlip * 0.025 * woodContactSmooth
      rigidSkidPitch = tirePressure
      rigidSkidSlip = vehicleWheelSpeedDiffSlip * wheelSound.tirePropertiesSlip
    -- if rigidSkidVolume > 0.01 then print (string.format(" WOOD SKID / rigidSkidVolume %.2f / rigidSkidPitch %.2f / rigidSkidSlip(+0.5) %.2f", rigidSkidVolume, rigidSkidPitch, rigidSkidSlip + 0.5).." "..wd.name); end
    end

    -- Audio Debug - prints for roll/skid RTPC's for all wheels
    -- streams.drawGraph(wd.name.." rigidRollVolume", {value = rigidRollVolume, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." rigidRollPitch", {value = rigidRollPtich, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." rigidSkidVolume", {value = rigidSkidVolume, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." rigidSkidPitch", {value = rigidSkidPitch, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." rigidSkidSlip + 0.5", {value = rigidSkidSlip + 0.5, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." slip * 0.01", {value = slip * 0.01, min = 0, max = 1})

    -- prints for roll/skid RTPC's for an individual wheel
    -- if wd.name == "RR" then
    -- streams.drawGraph(wd.name.." rigidSkidVolume (slip)", {value = rigidSkidVolume, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." rigidSkidPitch (pressure on surface)", {value = rigidSkidPitch, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." rigidSkidSlip + 0.5 (Slip difference)", {value = rigidSkidSlip + 0.5, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." sideSlip", {value = sideSlip * 0.0125, min = 0, max = 1})
    -- end

    if wd.tireSoundVolumeCoef > 0 then
      wheelSound.rigidRoll:setVolumePitch(rigidRollVolume * wd.tireSoundVolumeCoef, rigidRollPitch, rigidRollColor, rigidSurfaceType)
      wheelSound.rigidSkid:setVolumePitch(rigidSkidVolume * wd.tireSoundVolumeCoef, rigidSkidPitch, rigidSkidSlip + 0.5, rigidSurfaceType)
    end

    maxContact = maxContactBase --I don't think this is required twuce

    -- LOOSE dirt
    local dirtContactSmooth = wheelSound.dirtContactSmoother:getUncapped(boolToNum[mat == 15 and isRubberTire], dt)
    if dirtContactSmooth > maxContact then
      -- if wd.name == "RL" and wd.contactDepth > 0 then print (string.format("  DIRT depth=%.2f", wd.contactDepth).." "..wd.name);end
      maxContact = dirtContactSmooth
      looseSurfaceType = 0.025
      looseRollVolume = min(1, absWheelSpeed * 0.015) * dirtContactSmooth
      looseRollPitch = tirePressure
      looseRollDepth = wd.contactDepth + 0.1
      looseSkidVolume = slip * wheelSound.tirePropertiesSlip * 0.030 * dirtContactSmooth
      looseSkidPitch = tirePressure
      looseSkidDepth = wd.contactDepth
      -- if looseRollVolume > 0.001 then print (string.format("  DIRT ROLL Vol=%.2f : Pitch=%.2f : Depth=%.2f : Texture=%.2f", looseRollVolume, looseRollPitch, looseRollDepth, looseSurfaceType).." "..wd.name); end
      -- if looseSkidVolume > 0.001 then print (string.format("  DIRT SKID Vol=%.2f : Pitch=%.2f : Depth=%.2f : Texture=%.2f", looseSkidVolume, looseSkidPitch, looseSkidDepth, looseSurfaceType).." "..wd.name); end
      -- streams.drawGraph(wd.name.." looseSkidVolume", {value = looseSkidVolume, min = 0, max = 1})

      -- LOOSE dirt kickup
      local wheelPeripherySpeedKickup = max(slip * wheelSound.tirePropertiesKickup * 10, absWheelSpeed * wheelSound.tirePropertiesKickup * 4)
      wheelSound.looseSurfaceKickupLimit = wheelSound.looseSurfaceKickupLimit - dt * wheelPeripherySpeedKickup
      if wheelSound.looseSurfaceKickupLimit <= 0 and wheelPeripherySpeedKickup > 2 and wd.tireSoundVolumeCoef > 0 then
        local kickupVolume = min(1, wheelPeripherySpeedKickup * 0.002 * wheelSound.tirePropertiesKickup)
        playSoundOnceAtNode("event:>Surfaces>kickup_dirt", wd.node1, kickupVolume * wd.tireSoundVolumeCoef, wheelSound.tirePropertiesVolRoll, wheelSound.tirePropertiesPitch, 1)
        wheelSound.looseSurfaceKickupLimit = randomGauss3() * 8 / wheelSound.tirePropertiesKickup
      -- print(string.format("KICKUP DIRT Vol=%.2f : Pitch=%.2f : Color=%.2f : tirePropertiesKickup=%.2f", kickupVolume, wheelSound.tirePropertiesVolRoll, wheelSound.tirePropertiesPitch, wheelSound.tirePropertiesKickup) .. " " .. wd.name)
      -- streams.drawGraph(wd.name.." kickupVolume", {value = kickupVolume, min = 0, max = 1})
      end
    end

    -- LOOSE dirtDusty
    local dirtdustyContactSmooth = wheelSound.dirtDustyContactSmoother:getUncapped(boolToNum[mat == 14 and isRubberTire], dt)
    if dirtdustyContactSmooth > maxContact then
      -- if wd.name == "RL" and wd.contactDepth > 0 then print (string.format("  DIRT depth=%.2f", wd.contactDepth).." "..wd.name);end
      maxContact = dirtdustyContactSmooth
      looseSurfaceType = 0.075
      looseRollVolume = min(1, absWheelSpeed * 0.015) * dirtdustyContactSmooth
      looseRollPitch = tirePressure
      looseRollDepth = wd.contactDepth
      looseSkidVolume = slip * wheelSound.tirePropertiesSlip * 0.030 * dirtdustyContactSmooth
      looseSkidPitch = tirePressure
      looseSkidDepth = wd.contactDepth
      -- if looseRollVolume > 0.001 then print (string.format(" DUSTY ROLL Vol=%.2f : Pitch=%.2f : Depth=%.2f : Texture=%.2f", looseRollVolume, looseRollPitch, looseRollDepth, looseSurfaceType).." "..wd.name); end
      -- if looseSkidVolume > 0.001 then print (string.format(" DUSTY SKID Vol=%.2f : Pitch=%.2f : Depth=%.2f : Texture=%.2f", looseSkidVolume, looseSkidPitch, looseSkidDepth, looseSurfaceType).." "..wd.name); end
      -- streams.drawGraph(wd.name.." looseSkidVolume", {value = looseSkidVolume, min = 0, max = 1})

      -- LOOSE dirt kickup
      local wheelPeripherySpeedKickup = max(slip * wheelSound.tirePropertiesKickup * 10, absWheelSpeed * wheelSound.tirePropertiesKickup * 4)
      wheelSound.looseSurfaceKickupLimit = wheelSound.looseSurfaceKickupLimit - dt * wheelPeripherySpeedKickup
      if wheelSound.looseSurfaceKickupLimit <= 0 and wheelPeripherySpeedKickup > 2 and wd.tireSoundVolumeCoef > 0 then
        local kickupVolume = min(1, wheelPeripherySpeedKickup * 0.002 * wheelSound.tirePropertiesKickup)
        playSoundOnceAtNode("event:>Surfaces>kickup_dirtDusty", wd.node1, kickupVolume * wd.tireSoundVolumeCoef, wheelSound.tirePropertiesVolRoll, wheelSound.tirePropertiesPitch, 1)
        wheelSound.looseSurfaceKickupLimit = wheelSound.looseSurfaceKickupLimit + randomGauss3() * 20 / wheelSound.tirePropertiesKickup
      -- print(string.format("KICKUP DUST Vol=%.2f : Pitch=%.2f : Color=%.2f : tirePropertiesKickup=%.2f", kickupVolume, wheelSound.tirePropertiesVolRoll, wheelSound.tirePropertiesPitch, wheelSound.tirePropertiesKickup) .. " " .. wd.name)
      -- streams.drawGraph(wd.name.." kickupVolume", {value = kickupVolume, min = 0, max = 1})
      end
    end

    -- LOOSE grass
    local grassContactSmooth = wheelSound.grassContactSmoother:getUncapped(boolToNum[mat == 20 and isRubberTire], dt)
    if grassContactSmooth > maxContact then
      -- if wd.name == "RL" and wd.contactDepth > 0 then print (string.format(" GRASS depth=%.2f", wd.contactDepth).." "..wd.name);end
      maxContact = grassContactSmooth
      looseSurfaceType = 0.125
      looseRollVolume = min(1, absWheelSpeed * 0.015) * grassContactSmooth
      looseRollPitch = tirePressure
      looseRollDepth = wd.contactDepth
      looseSkidVolume = slip * wheelSound.tirePropertiesSlip * 0.030 * grassContactSmooth
      looseSkidPitch = tirePressure
      looseSkidDepth = wd.contactDepth
      -- if looseRollVolume > 0.001 then print (string.format(" GRASS ROLL Vol=%.2f : Pitch=%.2f : Depth=%.2f : Texture=%.2f", looseRollVolume, looseRollPitch, looseRollDepth, looseSurfaceType).." "..wd.name); end
      -- if looseSkidVolume > 0.001 then print (string.format(" GRASS SKID Vol=%.2f : Pitch=%.2f : Depth=%.2f : Texture=%.2f", looseSkidVolume, looseSkidPitch, looseSkidDepth, looseSurfaceType).." "..wd.name); end
      -- streams.drawGraph(wd.name.." looseSkidVolume", {value = looseSkidVolume, min = 0, max = 1})

      -- LOOSE grass kickup
      local wheelPeripherySpeedKickup = max(slip * wheelSound.tirePropertiesKickup * 12, absWheelSpeed * wheelSound.tirePropertiesKickup * 8)
      wheelSound.looseSurfaceKickupLimit = wheelSound.looseSurfaceKickupLimit - dt * wheelPeripherySpeedKickup
      if wheelSound.looseSurfaceKickupLimit <= 0 and wheelPeripherySpeedKickup > 2 and wd.tireSoundVolumeCoef > 0 then
        local kickupVolume = min(1, wheelPeripherySpeedKickup * 0.0024 * wheelSound.tirePropertiesKickup)
        playSoundOnceAtNode("event:>Surfaces>kickup_grass", wd.node1, kickupVolume * wd.tireSoundVolumeCoef, wheelSound.tirePropertiesVolRoll, wheelSound.tirePropertiesPitch, 1)
        wheelSound.looseSurfaceKickupLimit = randomGauss3() * 12 / wheelSound.tirePropertiesKickup
      -- print (string.format("KICKUP GRASS Vol=%.2f : Pitch=%.2f : Color=%.2f : tirePropertiesKickup=%.2f", kickupVolume, wheelSound.tirePropertiesVolRoll, wheelSound.tirePropertiesPitch, wheelSound.tirePropertiesKickup).." "..wd.name)
      -- streams.drawGraph(wd.name.." kickupVolume", {value = kickupVolume, min = 0, max = 1})
      end
    end

    -- LOOSE gravel
    local gravelContactSmooth = wheelSound.gravelContactSmoother:getUncapped(boolToNum[mat == 19 and isRubberTire], dt)
    if gravelContactSmooth > maxContact then
      -- if wd.name == "RL" and wd.contactDepth > 0 then print (string.format("GRAVEL depth=%.2f", wd.contactDepth).." "..wd.name);end
      maxContact = gravelContactSmooth
      looseSurfaceType = 0.175
      looseRollVolume = min(1, absWheelSpeed * 0.015) * gravelContactSmooth
      looseRollPitch = tirePressure
      looseRollDepth = wd.contactDepth + 0.4
      looseSkidVolume = slip * wheelSound.tirePropertiesSlip * 0.030 * gravelContactSmooth
      looseSkidPitch = tirePressure
      looseSkidDepth = wd.contactDepth
      -- if looseRollVolume > 0.001 then print (string.format("GRAVEL ROLL Vol=%.2f : Pitch=%.2f : Depth=%.2f : Texture=%.2f", looseRollVolume, looseRollPitch, looseRollDepth, looseSurfaceType).." "..wd.name); end
      -- if looseSkidVolume > 0.001 then print (string.format("GRAVEL SKID Vol=%.2f : Pitch=%.2f : Depth=%.2f : Texture=%.2f : tirePropertiesSlip=%.2f", looseSkidVolume, looseSkidPitch, looseSkidDepth, looseSurfaceType, wheelSound.tirePropertiesSlip).." "..wd.name); end
      -- streams.drawGraph(wd.name.." looseSkidVolume", {value = looseSkidVolume, min = 0, max = 1})

      local wheelPeripherySpeedKickup = max(slip * wheelSound.tirePropertiesKickup * 60, absWheelSpeed * wheelSound.tirePropertiesKickup * 20)
      wheelSound.looseSurfaceKickupLimit = wheelSound.looseSurfaceKickupLimit - dt * wheelPeripherySpeedKickup
      if wheelSound.looseSurfaceKickupLimit <= 0 and wheelPeripherySpeedKickup > 2 and wd.tireSoundVolumeCoef > 0 then
        local kickupVolume = min(1, wheelPeripherySpeedKickup * 0.0003 * wheelSound.tirePropertiesKickup)
        playSoundOnceAtNode("event:>Surfaces>kickup_gravel", wd.node1, kickupVolume * wd.tireSoundVolumeCoef, wheelSound.tirePropertiesVolRoll, wheelSound.tirePropertiesPitch, 1)
        wheelSound.looseSurfaceKickupLimit = wheelSound.looseSurfaceKickupLimit + randomGauss3() * 16 / wheelSound.tirePropertiesKickup
      -- print (string.format("KICKUP Slip=%.2f : Slip*Properties=%.2f", slip * 12, slip * wheelSound.tirePropertiesKickup * 12).." "..wd.name)
      -- print (string.format("KICKUP GRAVEL Vol=%.2f : Pitch=%.2f : Color=%.2f : tirePropertiesKickup=%.2f", kickupVolume, wheelSound.tirePropertiesVolRoll, wheelSound.tirePropertiesPitch, wheelSound.tirePropertiesKickup).." "..wd.name)
      -- streams.drawGraph(wd.name.." kickupVolume", {value = kickupVolume, min = 0, max = 1})
      end
    end

    -- LOOSE mud
    local mudContactSmooth = wheelSound.mudContactSmoother:getUncapped(boolToNum[mat == 18 and isRubberTire], dt)
    if mudContactSmooth > maxContact then
      -- if wd.name == "RL" and wd.contactDepth > 0 then print (string.format("  MUD depth=%.2f", wd.contactDepth).." "..wd.name);end
      maxContact = mudContactSmooth
      looseSurfaceType = 0.225
      looseRollVolume = min(1, absWheelSpeed * 0.015) * mudContactSmooth
      looseRollPitch = tirePressure
      looseRollDepth = wd.contactDepth * 2
      looseSkidVolume = slip * wheelSound.tirePropertiesSlip * 0.030 * mudContactSmooth
      looseSkidPitch = tirePressure
      looseSkidDepth = wd.contactDepth
      -- if looseRollVolume > 0.001 then print (string.format("   MUD ROLL Vol=%.2f : Pitch=%.2f : Depth=%.2f : Texture=%.2f", looseRollVolume, looseRollPitch, looseRollDepth, looseSurfaceType).." "..wd.name); end
      -- if looseSkidVolume > 0.001 then print (string.format("   MUD SKID Vol=%.2f : Pitch=%.2f : Depth=%.2f : Texture=%.2f", looseSkidVolume, looseSkidPitch, looseSkidDepth, looseSurfaceType).." "..wd.name); end
      -- streams.drawGraph(wd.name.." looseSkidVolume", {value = looseSkidVolume, min = 0, max = 1})
      -- streams.drawGraph(wd.name.."  mud looseRollDepth", {value = looseRollDepth, min = 0, max = 0.5})

      local wheelPeripherySpeedKickup = max(slip * wheelSound.tirePropertiesKickup * 20, absWheelSpeed * wheelSound.tirePropertiesKickup * 4)
      wheelSound.looseSurfaceKickupLimit = wheelSound.looseSurfaceKickupLimit - dt * wheelPeripherySpeedKickup
      if wheelSound.looseSurfaceKickupLimit <= 0 and wheelPeripherySpeedKickup > 2 and wd.tireSoundVolumeCoef > 0 then
        local kickupVolume = min(1, wheelPeripherySpeedKickup * 0.0024 * wheelSound.tirePropertiesKickup)
        playSoundOnceAtNode("event:>Surfaces>kickup_mud", wd.node1, kickupVolume * wd.tireSoundVolumeCoef, wheelSound.tirePropertiesVolRoll, wheelSound.tirePropertiesPitch, 1)
        wheelSound.looseSurfaceKickupLimit = randomGauss3() * 8 / wheelSound.tirePropertiesKickup
      -- print (string.format("KICKUP MUD Vol=%.2f : Pitch=%.2f : Color=%.2f : tirePropertiesKickup=%.2f", kickupVolume, wheelSound.tirePropertiesVolRoll, wheelSound.tirePropertiesPitch, wheelSound.tirePropertiesKickup).." "..wd.name)
      -- streams.drawGraph(wd.name.." kickupVolume", {value = kickupVolume, min = 0, max = 1})
      end
    end

    -- LOOSE rock
    local rockContactSmooth = wheelSound.rockContactSmoother:getUncapped(boolToNum[mat == 13 and isRubberTire], dt)
    if rockContactSmooth > maxContact then
      maxContact = rockContactSmooth
      looseSurfaceType = 0.275
      looseRollVolume = min(1, absWheelSpeed * 0.015) * rockContactSmooth
      looseRollPitch = tirePressure
      looseRollDepth = wd.contactDepth
      looseSkidVolume = slip * wheelSound.tirePropertiesSlip * 0.030 * rockContactSmooth
      looseSkidPitch = tirePressure
      looseSkidDepth = wd.contactDepth
      -- if looseRollVolume > 0.001 then print (string.format("  ROCK ROLL Vol=%.2f : Pitch=%.2f : Depth=%.2f : Texture=%.2f", looseRollVolume, looseRollPitch, looseRollDepth, looseSurfaceType).." "..wd.name); end
      -- if looseSkidVolume > 0.001 then print (string.format("  ROCK SKID Vol=%.2f : Pitch=%.2f : Depth=%.2f : Texture=%.2f", looseSkidVolume, looseSkidPitch, looseSkidDepth, looseSurfaceType).." "..wd.name); end
      -- streams.drawGraph(wd.name.." looseSkidVolume", {value = looseSkidVolume, min = 0, max = 1})

      local wheelPeripherySpeedKickup = max(slip * wheelSound.tirePropertiesKickup * 20, absWheelSpeed * wheelSound.tirePropertiesKickup * 5)
      wheelSound.looseSurfaceKickupLimit = wheelSound.looseSurfaceKickupLimit - dt * wheelPeripherySpeedKickup
      if wheelSound.looseSurfaceKickupLimit <= 0 and wheelPeripherySpeedKickup > 2 and wd.tireSoundVolumeCoef > 0 then
        local kickupVolume = min(1, wheelPeripherySpeedKickup * 0.0024 * wheelSound.tirePropertiesKickup)
        playSoundOnceAtNode("event:>Surfaces>kickup_rock", wd.node1, kickupVolume * wd.tireSoundVolumeCoef, wheelSound.tirePropertiesVolRoll, wheelSound.tirePropertiesPitch, 1)
        wheelSound.looseSurfaceKickupLimit = randomGauss3() * 8 / wheelSound.tirePropertiesKickup
      -- print (string.format("KICKUP ROCK Vol=%.2f : Pitch=%.2f : Color=%.2f : tirePropertiesKickup=%.2f", kickupVolume, wheelSound.tirePropertiesVolRoll, wheelSound.tirePropertiesPitch, wheelSound.tirePropertiesKickup).." "..wd.name)
      -- streams.drawGraph(wd.name.." kickupVolume", {value = kickupVolume, min = 0, max = 1})
      end
    end

    -- LOOSE sand
    local sandContactSmooth = wheelSound.sandContactSmoother:getUncapped(boolToNum[mat == 16 and isRubberTire], dt)
    if sandContactSmooth > maxContact then
      -- if wd.name == "RL" and wd.contactDepth > 0 then print (string.format(" SAND depth=%.2f", wd.contactDepth).." "..wd.name);end
      maxContact = sandContactSmooth
      looseSurfaceType = 0.325
      looseRollVolume = min(1, absWheelSpeed * 0.015) * sandContactSmooth
      looseRollPitch = tirePressure
      looseRollDepth = wd.contactDepth * 1
      looseSkidVolume = slip * wheelSound.tirePropertiesSlip * 0.020 * sandContactSmooth
      looseSkidPitch = tirePressure
      looseSkidDepth = wd.contactDepth
      -- if looseRollVolume > 0.001 then print (string.format("  SAND ROLL Vol=%.2f : Pitch=%.2f : Depth=%.2f : Texture=%.2f", looseRollVolume, looseRollPitch, looseRollDepth, looseSurfaceType).." "..wd.name); end
      -- if looseSkidVolume > 0.001 then print (string.format("  SAND SKID Vol=%.2f : Pitch=%.2f : Depth=%.2f : Texture=%.2f", looseSkidVolume, looseSkidPitch, looseSkidDepth, looseSurfaceType).." "..wd.name); end
      -- if wd.name == "FL" then streams.drawGraph(wd.name.." looseSkidVolume", {value = looseSkidVolume}); end
      -- streams.drawGraph(wd.name.." sand looseRollDepth", {value = looseRollDepth, min = 0, max = 0.5})

      local wheelPeripherySpeedKickup = max(slip * wheelSound.tirePropertiesKickup * 20, absWheelSpeed * wheelSound.tirePropertiesKickup * 4)
      wheelSound.looseSurfaceKickupLimit = wheelSound.looseSurfaceKickupLimit - dt * wheelPeripherySpeedKickup
      if wheelSound.looseSurfaceKickupLimit <= 0 and wheelPeripherySpeedKickup > 2 and wd.tireSoundVolumeCoef > 0 then
        local kickupVolume = min(1, wheelPeripherySpeedKickup * 0.0010 * wheelSound.tirePropertiesKickup)
        playSoundOnceAtNode("event:>Surfaces>kickup_sand", wd.node1, kickupVolume * wd.tireSoundVolumeCoef, wheelSound.tirePropertiesVolRoll, wheelSound.tirePropertiesPitch, 1)
        wheelSound.looseSurfaceKickupLimit = randomGauss3() * 4 / wheelSound.tirePropertiesKickup
      -- print (string.format("KICKUP SAND Vol=%.2f : Pitch=%.2f : Color=%.2f : tirePropertiesKickup=%.2f", kickupVolume, wheelSound.tirePropertiesVolRoll, wheelSound.tirePropertiesPitch, wheelSound.tirePropertiesKickup).." "..wd.name)
      -- streams.drawGraph(wd.name.." kickupVolume", {value = kickupVolume, min = 0, max = 1})
      end
    end

    looseSurfaceType = wheelSound.loosenessSmoother:getUncapped(looseSurfaceType, dt)

    -- streams.drawGraph(wd.name.." looseRollVolume", {value = looseRollVolume, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." looseRollPitch", {value = looseRollPitch, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." looseRollDepth", {value = looseRollDepth, min = 0, max = 0.3})
    -- streams.drawGraph(wd.name.." looseSkidVolume", {value = looseSkidVolume, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." looseSkidPitch", {value = looseSkidPitch, min = 0, max = 1})
    -- streams.drawGraph(wd.name.." looseSkidDepth", {value = looseSkidDepth, min = 0, max = 0.3})
    -- if looseRollDepth > 0 then print (string.format("looseSurfaceType = %0.3f / looseRollDepth = %0.2f", looseSurfaceType, looseRollDepth)); end

    if wd.tireSoundVolumeCoef > 0 then
      wheelSound.looseRoll:setVolumePitch(looseRollVolume * wd.tireSoundVolumeCoef, looseRollPitch, looseRollDepth, looseSurfaceType)
      wheelSound.looseSkid:setVolumePitch(looseSkidVolume * wd.tireSoundVolumeCoef, looseSkidPitch, looseSkidDepth, looseSurfaceType)
    end

    -- MISC flat tire
    if wd.isTireDeflated and not wd.isBroken and mat >= 0 then
      wd.deflatedTireAngle = wd.deflatedTireAngle + clamp(wd.angularVelocity, -100, 100) * dt
      if abs(wd.deflatedTireAngle) >= twoPi then
        local downForceVolume = clamp(wd.downForce / 5000, 0, 1)
        local speedPitch = clamp(abs(wd.angularVelocity) / 200, 0, 1)
        obj:playSFXOnceCT(wd.flatTireSound, wd.node1, downForceVolume, speedPitch, wd.tireVolume * 5, max(M.scrapeLoosenessMap[mat] or 0, M.scrapeLoosenessMap[mat2] or 0))
        wd.deflatedTireAngle = wd.deflatedTireAngle - twoPi * sign(wd.deflatedTireAngle)
      end
    end

    -- MISC rumblestrip
    local rumbleStripContactSmooth = wheelSound.rumbleStripContactSmoother:getUncapped(boolToNum[mat == 29 and isRubberTire], dt)
    if rumbleStripContactSmooth > 0 then
      local vehicleSpeed = groundSpeed
      local peakForce = wd.peakForce
      -- if vehicleSpeed < 15 then
      if peakForce > 0 and wd.obj:getPeakPeriod() * vehicleSpeed > 0.0 and wd.tireSoundVolumeCoef > 0 then
        rigidSurfaceType = 0.35
        -- if wd.name == "FL" then print (string.format("peakForce=%6.0f / wd.obj:getPeakPeriod()=%0.2f / vehicleSpeed=%0.3f", peakForce, wd.obj:getPeakPeriod(), vehicleSpeed)); end
        local volume = min(1, peakForce * vehicleSpeed * 0.000002 / wheelSound.tireContactPatchCoef - 0.01)
        local pitch = vehicleSpeed * 0.0175
        playSoundOnceAtNode("event:>Surfaces>roll_rumblestrip", wd.node1, volume * wd.tireSoundVolumeCoef, pitch, wheelSound.tirePropertiesVolRoll)
      -- if wd.name == "FL" then playSoundOnceAtNode("event:>Surfaces>roll_rumblestrip", wd.node1, volume, pitch, wheelSound.tirePropertiesVolRoll);end
      end
    -- end
    end
  end

  if M.uiDebugging and playerInfo.firstPlayerSeated then
    guihooks.trigger("AudioDebug", soundBank)
  end
end

Callers

@/lua/vehicle/controller/propAnimation/singleAxisLever.lua

local function updateGFX(dt)
  local gearModeIndex = electrics.values.gearModeIndex or 0
@/lua/vehicle/controller/sound/airbrakes.lua

local function updateGFX(dt)
  local brake = electrics.values[electricsBrakeName] or 0
@/lua/vehicle/extensions/api.lua

local function updateGFX()
    httpJsonServer.update()
@/lua/vehicle/thrusters.lua
local invalidThrusterControlWarned
local function updateGFX()
  table.clear(thrusterState)
@/lua/vehicle/controller/vivaceGauges.lua

local function updateGFX(dt)
  updateTimer = updateTimer + dt
@/lua/ge/map.lua

local function updateGFX(dtReal, dtSim)
  if dtSim > 0 then
@/lua/vehicle/controller/gauges/customModules/dynamicRedlineData.lua

local function updateGFX(dt)
end
@/lua/vehicle/controller/propAnimation/hPattern.lua

local function updateGFX(dt)
  if not relevantGearbox and not demoMode then
@/lua/vehicle/extensions/dynamicVehicleData.lua

local function updateGFX(dt)
  timer = timer + dt
@/lua/vehicle/powertrain/hydraulicAccumulator.lua

local function updateGFX(device, dt)
  for _, consumer in ipairs(device.connectedConsumers) do
  for _, consumer in ipairs(device.connectedConsumers) do
    consumer:updateGFX(device.accumulatorPressure, dt)
  end
@/lua/vehicle/controller/pneumatics.lua

local function updateGFX(dt)
  for _, g in pairs(beamGroups) do
@/lua/vehicle/extensions/dynoClient.lua

local function updateGFX(dt)
    if not dynoObjectID then return end
@/lua/vehicle/material.lua

local function updateGFX()
  -- check for changes
@/lua/vehicle/powertrain/genericTorqueProvider.lua

local function updateGFX(device, dt)
  device.outputRPM = device.outputAV1 * avToRPM
@/lua/vehicle/controller/propAnimation/dualAxisLever.lua

local function updateGFX(dt)
  updateTargetQueue(dt)
@/lua/vehicle/energyStorage/electricBattery.lua

local function updateGFX(storage, dt)
  storage:setStoredEnergy(storage.storedEnergy)
@/lua/vehicle/fire.lua

local function updateGFX(dt)
  local rand = random(1) --use the same random value for all effects in this frame
@/lua/vehicle/controller/shiftLights.lua

local function updateGFX(dt)
  local rpm = electrics.values[inputElectricsName]
@/lua/vehicle/controller/gauges/customModules/navigationData.lua

local function updateGFX(dt)
end
@/lua/vehicle/input.lua
local lockTypeWarned
local function updateGFX(dt)
  gxSmoothMax = gx_Smoother:getUncapped(0, dt)
@/lua/vehicle/extensions/tech/CANBus/ProjectBavariaShifter.lua

local function updateGFX(dt)
  if playerInfo.firstPlayerSeated then
@/lua/vehicle/controller/pyrotechnicCharge.lua

local function updateGFX(dt)
  if not hasTriggered then
@/lua/vehicle/controller/sbrGauges.lua

local function updateGFX(dt)
  updateTimer = updateTimer + dt
@/lua/vehicle/controller/playerController.lua

local function updateGFX(dt)
  ballGroundContactNodesPast, ballGroundContactNodesNew = ballGroundContactNodesNew, ballGroundContactNodesPast
@/lua/vehicle/controller/hydraulics/electricHydraulics.lua

local function updateGFX(dt)
  local motorThrottle = 0
@/lua/vehicle/extensions/inputAnalyzer.lua

local function updateGFX(dt)
  inputCheckTimer = inputCheckTimer + dt
@/lua/vehicle/extensions/tech/ACC.lua

local function updateGFX(dtSim)
@/gameplay/missionTypes/hypermiling/fluidConsumptionToGraph.lua

local function updateGFX(dtSim)
  updateTimer = updateTimer + dtSim
@/lua/vehicle/powertrain/hydraulicCylinder.lua

local function updateGFX(cylinder, dt)
  local valvePosition = electrics.values[cylinder.directionElectricsName] or 0
@/lua/vehicle/controller/dragTimer.lua

local function updateGFX(dt)
end
@/lua/vehicle/extensions/tech/CANBus/CANBusPeak.lua

local function updateGFX(dt)
  if M.isConnected and next(canMessageCallbacks) ~= nil then
@/lua/vehicle/controller/drivingDynamics/supervisors/components/brakeControl.lua

local function updateGFX(dt)
  electrics.values.isYCBrakeActive = isYCBrakeActive and 1 or 0
local function updateGFXDebug(dt)
  updateGFX(dt)
@/lua/vehicle/powertrain/manualGearbox.lua

local function updateGFX(device, dt)
  --local gearIndex = device.grindingShiftTargetIndex or device.gearIndex
@/lua/vehicle/controller/beaconSpin.lua

local function updateGFX(dt)
  electrics.values[electricsName] = electrics.values.lightbar > 0 and ((electrics.values[electricsName] + (dt * beaconSpeed)) % 360) or 0 --this needs to be 0 as otherwise the spotlights stay turned on :|
@/lua/vehicle/extensions/tech/wheelForces.lua

local function updateGFX()
end
@/lua/vehicle/controller/braking/hydraulicPumpBrake.lua

local function updateGFX(dt)
  --the engine technically runs the hydraulic pump for the brakes, so no spinning engine means no brake pressure
@/lua/vehicle/controller/braking/compressionBrake.lua

local function updateGFX(dt)
  local compressionBrakeCoefActual = compressionBrakeCoef * (1 - sign(controlledEngine.requestedThrottle))
@/lua/vehicle/extensions/straightLine.lua

local function updateGFX(dt)
  if baseTargetPos then
@/lua/vehicle/electrics.lua

local function updateGFX(dt)
  updateIgnitionStarterHandler(dt)

  customValueParser.updateGFX(dt)
@/lua/vehicle/powertrain/supercharger.lua

local function updateGFX(dt)
  -- Some verification stuff
@/lua/vehicle/powertrain/turbocharger.lua

local function updateGFX(dt)
  --Some verification stuff
@/lua/vehicle/controller/lineLock.lua

local function updateGFX(dt)
  electrics.values[electricsName] = lineLockActive
@/lua/vehicle/main.lua
  lastDt = dtSim
  sensors.updateGFX(dtSim) -- must be before input and ai
  mapmgr.sendTracking() -- must be before ai
  mapmgr.sendTracking() -- must be before ai
  wheels.updateGFX(dtSim)
  ai.updateGFX(dtSim) -- must be before input and after wheels
  wheels.updateGFX(dtSim)
  ai.updateGFX(dtSim) -- must be before input and after wheels
  input.updateGFX(dtSim) -- must be as early as possible
  ai.updateGFX(dtSim) -- must be before input and after wheels
  input.updateGFX(dtSim) -- must be as early as possible
  electrics.updateGFX(dtSim)
  input.updateGFX(dtSim) -- must be as early as possible
  electrics.updateGFX(dtSim)
  controller.updateGFX(dtSim)
  electrics.updateGFX(dtSim)
  controller.updateGFX(dtSim)
  electrics.updateGFXSecondStep(dtSim)
  extensions.hook("updateGFX", dtSim) -- must be before drivetrain, hydros and after electrics
  hydros.updateGFX(dtSim) -- must be early for FFB, but after (input, electrics) and before props
  powertrain.updateGFX(dtSim)
  hydros.updateGFX(dtSim) -- must be early for FFB, but after (input, electrics) and before props
  powertrain.updateGFX(dtSim)
  energyStorage.updateGFX(dtSim)
  powertrain.updateGFX(dtSim)
  energyStorage.updateGFX(dtSim)
  drivetrain.updateGFX(dtSim)
  energyStorage.updateGFX(dtSim)
  drivetrain.updateGFX(dtSim)
  beamstate.updateGFX(dtSim) -- must be after drivetrain
  drivetrain.updateGFX(dtSim)
  beamstate.updateGFX(dtSim) -- must be after drivetrain
  protocols.updateGFX(dtSim)
  beamstate.updateGFX(dtSim) -- must be after drivetrain
  protocols.updateGFX(dtSim)
  sounds.updateGFX(dtSim)
  protocols.updateGFX(dtSim)
  sounds.updateGFX(dtSim)
  thrusters.updateGFX() -- should be after extensions.hook
  sounds.updateGFX(dtSim)
  thrusters.updateGFX() -- should be after extensions.hook
  if playerInfo.firstPlayerSeated then
    damageTracker.updateGFX(dtSim)
  end

  props.updateGFX() -- must be after hydros
  material.updateGFX()
  props.updateGFX() -- must be after hydros
  material.updateGFX()
  fire.updateGFX(dtSim)
  material.updateGFX()
  fire.updateGFX(dtSim)
  recovery.updateGFX(dtSim)
  fire.updateGFX(dtSim)
  recovery.updateGFX(dtSim)
  powertrain.updateGFXLastStage(dtSim)
@/lua/vehicle/extensions/dragAi.lua

local function updateGFX(dt)
  if state == "ready" then
@/lua/vehicle/controller/drivingDynamics/supervisors/components/motorTorqueControl.lua

local function updateGFX(dt)
end
local function updateGFXDebug(dt)
  updateGFX(dt)
@/lua/vehicle/extensions/odometer.lua

local function updateGFX(dt)
  relativeOdometer = relativeOdometer + abs(electrics.values.wheelspeed or 0) * dt
@/lua/vehicle/controller/couplings/fifthwheel.lua

local function updateGFX(dt)
  --print(state)
@/lua/vehicle/extensions/tech/LINBus/LINBusPeak.lua

local function updateGFX(dt)
  if M.isConnected then
@/lua/vehicle/extensions/tech/CANBus/ProjectBavariaKombi.lua

local function updateGFX(dt)
  if playerInfo.firstPlayerSeated then
@/lua/vehicle/energyStorage/n2oTank.lua

local function updateGFX(storage, dt)
  storage.remainingMass = storage.storedEnergy / storage.energyDensity
@/lua/vehicle/powertrain/electricServo.lua

local function updateGFX(device, dt)
  --note: this method is only executed if any electrics name for the target angle is set
@/lua/vehicle/controller/drivingDynamics/supervisors/tractionControl.lua

local function updateGFX(dt)
  isActiveSmoothed = isActiveSmoother:getUncapped(tractionControlActive and 1 or 0, dt)
local function updateGFXDebug(dt)
  updateGFX(dt)
@/lua/vehicle/controller/sound/AVAS.lua

local function updateGFX(dt)
  local gear = electrics.values.gear
@/lua/vehicle/powertrain/compressor.lua

local function updateGFX(device, dt)
  if streams.willSend("pneumaticsData") then
@/lua/vehicle/controller/tirePressureControl.lua

local function updateGFX(dt)
  pEnv = obj:getEnvPressure()
@/lua/vehicle/extensions/cruiseControl.lua

local function updateGFX(dt)
  if not isEnabled then
@/lua/vehicle/extensions/escMeasurement.lua

local function updateGFX(dt)
  if workerCoroutine ~= nil then
@/lua/vehicle/hydros.lua

local function updateGFX(dt) -- dt in seconds
  local invPhysSteps = physicsDt / dt
@/lua/vehicle/controller/gauges/customModules/accelerationData.lua

local function updateGFX(dt)
end
@/lua/vehicle/controller/gauges/analogOdometer.lua

local function updateGFX(dt)
  updateTimer = updateTimer + dt
@/lua/vehicle/extensions/tech/GPS.lua

local function updateGFX(dtSim)
  for sensorId, _ in pairs(GPSs) do
@/lua/vehicle/controller/drivingDynamics/CMU.lua

local function updateGFX(dt)
  checkForRollOverAndCrash(dt)
local function updateGFXDebugNotEnabled(dt)
  updateGFX(dt)
local function updateGFXDebugEnabled(dt)
  updateGFX(dt)
@/lua/vehicle/controller/linearActuators/linearActuatorTrailerFeet.lua

local function updateGFX(dt)
  local currentPosition = actuator.currentExtendPercent
@/lua/vehicle/controller/pneumatics/liftAxleControl.lua

local function updateGFX(dt)
  if currentMode == modes.drop then
@/lua/vehicle/sensors.lua

local function updateGFX(dt)
  local ffisensors = M.ffiSensors
@/lua/vehicle/extensions/telemetryLogger.lua

local function updateGFX(dt)
  if not isRecording then
@/lua/vehicle/controller/nitrousOxideInjection.lua

local function updateGFX(dt)
  local tankRatio = engine.nitrousOxideInjection.getTankRatio()
@/lua/vehicle/controller/drivingDynamics/supervisors/slipProviders/virtualSpeedSlip.lua

local function updateGFX(dt)
end
local function updateGFXDebug(dt)
  updateGFX(dt)
@/lua/vehicle/powertrain/hydraulicPump.lua

local function updateGFX(device, dt)
  for _, consumer in ipairs(device.connectedConsumers) do
  for _, consumer in ipairs(device.connectedConsumers) do
    consumer:updateGFX(device.accumulatorPressure, dt)
  end
@/lua/vehicle/extensions/tech/tyreBarrier.lua

local function updateGFX(dtSim)
  if IMUcontroller ~= nil then
@/lua/vehicle/extensions/mqttGrafanaDemo.lua

local function updateGFX(dt)
  if not client then return end
@/lua/vehicle/extensions/tech/powertrainSensor.lua

local function updateGFX(dtSim)
  for sensorId, _ in pairs(powertrains) do
@/lua/vehicle/extensions/scenario/shiftBooster.lua

local function updateGFX(dt)
  if boostTime > 0.01 then
@/lua/vehicle/extensions/vehiclePerformanceData.lua

local function updateGFX(dt)
  --iterate active recordings and execute the update method
@/lua/vehicle/controller/etkGauges.lua

local function updateGFX(dt)
  if not uiIsReady then
@/lua/vehicle/controller/drivingDynamics/sensors/virtualSensors.lua

local function updateGFX(dt)
end
local function updateGFXDebug(dt)
  updateGFX(dt)
  local virtual = M.virtual
@/lua/vehicle/extensions/vehicleStatsLogger.lua

local function updateGFX(dt)
  if not doLogging then
@/lua/vehicle/controller/drivingDynamics/sensors/sensorHub.lua

local function updateGFX(dt)
  --print(M.accNoiseX + M.accNoiseY + M.accNoiseZ)
local function updateGFXDebug(dt)
  updateGFX(dt)
@/lua/vehicle/extensions/tech/CANBus/ButtonBox.lua

local function updateGFX(dt)
  if playerInfo.firstPlayerSeated then
@/lua/vehicle/powertrain/nitrousOxideInjection.lua

local function updateGFX(dt)
  if assignedEngine.engineDisabled then
@/lua/vehicle/props.lua

local function updateGFX()
  local evals = electrics.values
@/lua/vehicle/extensions/tech/OBDEmulator.lua

local function updateGFX(dt)
  if playerInfo.firstPlayerSeated then
@/lua/vehicle/beamstate.lua

local function updateGFX(dt)
  -- Planet timers
@/lua/vehicle/extensions/perfectLaunch.lua

local function updateGFX(dt)
  if state == "idle" then

  straightLine.updateGFX(dt)
end
@/lua/vehicle/controller/hydraulicSuspension.lua

local function updateGFX(dt)
  if currentPumpFlow > 0 then
@/lua/vehicle/powertrain/centrifugalClutch.lua

local function updateGFX(device, dt)
  local kClutchToHousing = 20
@/lua/vehicle/controller/airplaneSurfaces.lua

local function updateGFX(dt)
  local rudder = input.rudder or 0
@/lua/vehicle/controller/powertrainControl/rimPullControl.lua

local function updateGFX(dt)
  --read the rim pull input from the relevant axis action
@/lua/vehicle/controller/axleLift.lua

local function updateGFX(dt)
  local frontPos = frontRaisedPosition
@/lua/vehicle/controller/twoStepLaunch.lua

local function updateGFX(dt)
  if twoStepState == "idle" then
@/lua/vehicle/powertrain/electricMotor.lua

local function updateGFX(device, dt)
  device:updateEnergyUsage()
@/lua/vehicle/controller/driveModes.lua

local function updateGFX(dt)
  for _, buttonData in pairs(simpleControlButtons) do
@/lua/ge/main.lua
  if geluaProfiler then geluaProfiler:start() end
  map.updateGFX(dtReal, dtSim)
  if geluaProfiler then geluaProfiler:add("luaPreRender map update") end

  extensions.core_input_bindings.updateGFX(dtRaw)
  simTimeAuthority.update(dtReal)
@/lua/vehicle/extensions/core/booster.lua

local function updateGFX(dtSim)
  local planets = {}
@/lua/vehicle/controller/drivingDynamics/sensors/vehicleData.lua

local function updateGFX(dt)
end
local function updateGFXDebug(dt)
  updateGFX(dt)
@/lua/vehicle/controller.lua

local function updateGFX(dt)
  for i = 1, gfxUpdateCount, 1 do
      if controller.updateGFX ~= nil then
        print("  sortedControllers[" .. i .. "].updateGFX(dt) -- " .. tostring(controller.typeName))
      end
@/lua/vehicle/controller/gauges/genericGauges.lua

local function updateGFX(dt)
  updateTimer = updateTimer + dt
@/lua/vehicle/controller/braking/brakedDifferentialSteering.lua

local function updateGFX(dt)
  local steering = electrics.values.steering_input or 0
@/lua/vehicle/controller/drivingDynamics/actuators/activeDiffBias.lua

local function updateGFX(dt)
  if not controlParameters.isEnabled then
local function updateGFXDebug(dt)
  updateGFX(dt)
@/lua/vehicle/controller/beamNavigator.lua

local function updateGFX(dt)
  updateTimer = updateTimer + dt
@/lua/vehicle/extensions/debug/advancedExternalDebug.lua

local function updateGFX(dt)
  mainDebugPacket.isActiveVehicle = playerInfo.firstPlayerSeated
@/lua/vehicle/protocols.lua

local function updateGFX(dtSim)
  if not playerInfo.firstPlayerSeated then return end
@/lua/vehicle/energyStorage/pressureTank.lua

local function updateGFX(storage, dt)
  -- calculate pressure from stored energy and capacity: PV = nRT, e = nRT, therefore PV = e and P = e / V
@/lua/vehicle/energyStorage/fuelTank.lua

local function updateGFX(storage, dt)
  storage.remainingVolume = storage.storedEnergy / (storage.fuelLiquidDensity * storage.energyDensity)
@/lua/vehicle/controller/gauges/customModules/combustionEngineData.lua

local function updateGFX(dt)
end
@/lua/vehicle/controller/drivingDynamics/supervisors/yawProviders/STMEstimate.lua

local function updateGFX(dt)
end
local function updateGFXDebug(dt)
  updateGFX(dt)
@/lua/vehicle/controller/drivingDynamics/supervisors/components/awdControl.lua

local function updateGFX(dt)
end
local function updateGFXDebug(dt)
  updateGFX(dt)
@/lua/vehicle/controller/vehicleController/vehicleController.lua

  --drivingStrategy.core.updateGFX(dt)
@/lua/vehicle/electricsCustomValueParser.lua

local function updateGFX(dt)
  --copy our main electrics into the sandboxed environment
@/lua/vehicle/controller/drivingDynamics/actuators/activeCenterDiffLock.lua

local function updateGFX(dt)
  if not controlParameters.isEnabled then
local function updateGFXDebug(dt)
  updateGFX(dt)
@/lua/vehicle/controller/propAnimation/googlyEyes.lua

local function updateGFX(dt)
  local sizeCoef = linearScale(sensors.gz, 0, defaultGravity * gravityMaxSizeCoef, maxSizeCoef, minSizeCoef)
@/lua/vehicle/controller/controlModes.lua

local function updateGFX(dt)
  inputs.steering = input.steering
@/lua/vehicle/controller/drivingDynamics/actuators/activeDiffLock.lua

local function updateGFX(dt)
  if not controlParameters.isEnabled then
local function updateGFXDebug(dt)
  updateGFX(dt)
@/lua/vehicle/extensions/tech/platooning.lua

local function updateGFX(dtSim)
@/lua/vehicle/controller/drivingDynamics/actuators/electronicSplitShaftLock.lua

local function updateGFX(dt)
  if not controlParameters.isEnabled then
local function updateGFXDebug(dt)
  updateGFX(dt)
@/lua/vehicle/extensions/tech/roadsSensor.lua

local function updateGFX(dtSim)
  for sensorId, _ in pairs(roadsSensors) do
@/lua/vehicle/extensions/tech/advancedIMU.lua

local function updateGFX(dtSim)
  for sensorId, _ in pairs(advancedIMUs) do
@/lua/vehicle/controller/advancedCouplerControl.lua

local function updateGFX(dt)
  if couplerGroup.spawnSoundDelayTimer > 0 then
@/lua/vehicle/controller/tech/screens.lua

local function updateGFX(dt)
end
@/lua/vehicle/extensions/advancedwheeldebug.lua

local function updateGFX(dt)
  if not isDebugEnabled then
@/lua/vehicle/extensions/aeroDebug.lua

local function updateGFX(dt)
  if not isEnabled then
@/lua/vehicle/controller/loggerTemplate.lua
-- If you overload this method performance wise, fps will drop gracefully, so disk IO and other heavily unpredictable things are done/triggered from here (or user input)
local function updateGFX(dt)
  logInterestingData()
@/lua/vehicle/extensions/gameplayInterfaceModules/interactCargoContainers.lua
local anyContainerNeedsUpdate = false
local function updateGFX(dtSim)
  anyContainerNeedsUpdate = false
@/lua/vehicle/controller/powertrainControl/activeCenterDiff.lua

local function updateGFX(dt)
end
@/lua/vehicle/wheels.lua

local function updateGFX(dt)
  updateThermalsGFXMethod(dt)
@/lua/vehicle/controller/drivingDynamics/actuators/electronicDiffLock.lua

local function updateGFX(dt)
  if not controlParameters.isEnabled then
local function updateGFXDebug(dt)
  updateGFX(dt)
@/lua/ge/extensions/core/input/bindings.lua
local wasWalking
local function updateGFX(dtRaw)
  if filechangeTimeout then
@/lua/vehicle/controller/wendoverGauges.lua

local function updateGFX(dt)
  updateTimer = updateTimer + dt
@/lua/vehicle/controller/propAnimation/sequentialLever.lua

local function updateGFX(dt)
  if not relevantGearbox then
@/lua/vehicle/controller/drivingDynamics/supervisors/components/diffControl.lua

local function updateGFX(dt)
end
local function updateGFXDebug(dt)
  updateGFX(dt)
@/lua/vehicle/controller/braking/transbrake.lua

local function updateGFX(dt)
  electrics.values[electricsName] = gearbox.lockCoef == 0
@/lua/vehicle/controller/pneumatics/airbrakes.lua

local function updateGFX(dt)
  updateSounds(dt)
@/lua/vehicle/controller/gauges/customModules/tireData.lua

local function updateGFX(dt)
end
@/lua/vehicle/controller/pneumatics/lowAirPressureWarning.lua

local function updateGFX(dt)
  local pressure = relevantPressureTank and relevantPressureTank.currentPressure or 0
@/lua/vehicle/controller/pneumatics/actuators.lua

local function updateGFX(dt)
  for _, g in pairs(crossFlowGroups) do
@/lua/vehicle/controller/drivingDynamics/supervisors/yawControl.lua

local function updateGFX(dt)
  isActiveSmoothed = isActiveSmoother:getUncapped(yawControlActive and 1 or 0, dt)
local function updateGFXDebug(dt)
  updateGFX(dt)
@/lua/vehicle/extensions/escCalibration.lua

local function updateGFX(dt)
  if skewStiffnessTestState == idleState then
@/lua/vehicle/controller/controllerTemplate.lua

local function updateGFX(dt)
end
@/lua/vehicle/extensions/utRecorder.lua

local function updateGFX(dt)
  local pos = obj:getPosition()
@/lua/vehicle/extensions/gameplayInterface.lua

local function updateGFX(dt)
  checkValueChangeNotificationMethod(dt)
@/lua/vehicle/controller/gauges/customModules/environmentData.lua

local function updateGFX(dt)
end
@/lua/vehicle/powertrain/frictionClutch.lua

local function updateGFX(device, dt)
  local kClutchToBellHousing = 30
@/lua/ge/extensions/util/export.lua

local function updateGFX(dt)
  if lastMeshInfo and lastMeshInfo.dataIsReady then
@/lua/vehicle/controller/esc.lua

local function updateGFX(dt)
  warningLightsTimer = warningLightsTimer + dt
@/lua/vehicle/extensions/simpleTripApp.lua

local function updateGFX(dtSim)
  local dtReal = obj:getRealdt()
@/lua/vehicle/extensions/tech/CANBus/RacingDisplay.lua

local function updateGFX(dt)
  if playerInfo.firstPlayerSeated then
@/lua/vehicle/extensions/core/quickAccess.lua

local function updateGFX(dt)
  if actionCallbackCountdown then
@/lua/vehicle/controller/powertrainControl/antiLag.lua

local function updateGFX(dt)
  local throttle = electrics.values.throttle
@/lua/vehicle/controller/lightbar.lua
-- @param dt: Delta time since last frame in seconds
local function updateGFX(dt)
  -- Skip if lightbar system isn't active
@/lua/vehicle/powertrain/combustionEngine.lua

local function updateGFX(device, dt)
  device:updateFuelUsage()

  device.turbocharger.updateGFX(dt)
  device.supercharger.updateGFX(dt)
  device.turbocharger.updateGFX(dt)
  device.supercharger.updateGFX(dt)
  device.nitrousOxideInjection.updateGFX(dt)
  device.supercharger.updateGFX(dt)
  device.nitrousOxideInjection.updateGFX(dt)

  device.thermals.updateGFX(dt)
@/lua/vehicle/powertrain/combustionEngineThermals.lua

local function updateGFX(dt)
  updateCoolingGFXMethod(dt)
@/lua/vehicle/powertrain/automaticGearbox.lua

local function updateGFX(device, dt)
  --interpolate gear ratio to simulate the opening/closing clutches of the auto gearbox
@/lua/vehicle/extensions/tech/mesh.lua

local function updateGFX(dtSim)
  for sensorId, _ in pairs(meshes) do
@/lua/vehicle/powertrain.lua

local function updateGFX(dt)
  M.currentGravity = obj:getGravity()
    if device.updateGFX then
      device:updateGFX(dt)
    end
@/lua/vehicle/ai.lua
M.updateGFX = nop
local function updateGFX(dtGFX)
  dt = dtGFX
@/lua/vehicle/powertrain/sequentialGearbox.lua

local function updateGFX(device, dt)
  if device.targetGearIndex then
@/lua/vehicle/extensions/gameplayStatistic.lua

local function updateGFX(dt)
  if lenstatSchedule > 0 then
@/lua/vehicle/energyStorage.lua

local function updateGFX(dt)
  for i = 1, storageCount, 1 do
    if storage.updateGFX then
      storage:updateGFX(dt)
    end
@/lua/vehicle/controller/braking/postCrashBrake.lua

local function updateGFX(dt)
  if state == "idle" then
@/lua/vehicle/controller/dummy.lua

local function updateGFX(dt)
  electrics.values.throttle = math.min(math.max(input.throttle or 0, 0), 1)
@/lua/vehicle/controller/sound/linearMovement.lua

local function updateGFX(dt)
  --get the current length of our sensor beam
@/lua/vehicle/controller/drivingDynamics/supervisors/components/aeroControl.lua

local function updateGFX(dt)
end
local function updateGFXDebug(dt)
  updateGFX(dt)
@/lua/vehicle/controller/gauges/customModules/electricMotorData.lua

local function updateGFX(dt)
end
@/lua/vehicle/extensions/tech/idealRADARSensor.lua

local function updateGFX(dtSim)
  for sensorId, _ in pairs(idealRADARs) do
@/lua/vehicle/extensions/tech/CANBus/ProjectBavariaController.lua

local function updateGFX(dt)
  if playerInfo.firstPlayerSeated then
@/lua/vehicle/controller/sound/reverseWarn.lua

local function updateGFX(dt)
  tick = tick + dt
@/lua/vehicle/controller/braking/adaptiveBrakeLights.lua

local function updateGFX(dt)
  local brakeValue = electrics.values.brake or 0
@/lua/vehicle/extensions/tech/dumpPlayerInput.lua
-- this is called every frame
local function updateGFX(dt)
  if not f then return end
@/lua/vehicle/controller/tech/MQTToutput.lua

local function updateGFX(dt)
  updateData(dt)
@/lua/vehicle/controller/hydraulics/hydraulicTrailerFeet.lua

local function updateGFX(dt)
  local currentPosition = feetCylinder.currentExtendPercent
@/lua/vehicle/controller/inputOutputDemo.lua
--If you overload this method performance wise, fps will drop gracefully, so disk IO and other heavily unpredictable things are done/triggered from here (or user input)
local function updateGFX(dt)
  LogInterestingData()
@/lua/vehicle/controller/4wd.lua

local function updateGFX(dt)
  electrics.values.modeRangeBox = rangeBox and (rangeBox.mode == "low" and 1 or 0) or 0
@/lua/vehicle/controller/jato.lua

local function updateGFX(dt)
  local jatoInput = min(electrics.values.jatoInput or 0, 1)