GE Lua Documentation

Press F to search!

linearScale

Definition


-- @/lua/common/mathlib.lua:1185

-- Note: linearScale clamps
function linearScale(v, minValue, maxValue, minOutput, maxOutput)
  return minOutput + min(max((v - minValue) / (maxValue - minValue), 0), 1) * (maxOutput - minOutput)
end

Callers

@/lua/vehicle/powertrain/automaticGearbox.lua
local function applyDeformGroupDamage(device, damageAmount)
  device.damageFrictionCoef = device.damageFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 0.1)
  device.damageGearRatioChangeRateCoef = max(device.damageGearRatioChangeRateCoef - linearScale(damageAmount, 0, 0.01, 0, 0.1), 0.2)
  device.damageFrictionCoef = device.damageFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 0.1)
  device.damageGearRatioChangeRateCoef = max(device.damageGearRatioChangeRateCoef - linearScale(damageAmount, 0, 0.01, 0, 0.1), 0.2)
end
local function setPartCondition(device, subSystem, odometer, integrity, visual)
  device.wearFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 2)
  device.wearGearRatioChangeRateCoef = linearScale(odometer, 30000000, 500000000, 1, 0.2)
  device.wearFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 2)
  device.wearGearRatioChangeRateCoef = linearScale(odometer, 30000000, 500000000, 1, 0.2)
    integrityState = {
      damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 50),
      damageGearRatioChangeRateCoef = linearScale(integrityValue, 1, 0, 1, 0.2),
      damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 50),
      damageGearRatioChangeRateCoef = linearScale(integrityValue, 1, 0, 1, 0.2),
      isBroken = false
  }
  local integrityValueFriction = linearScale(device.damageFrictionCoef, 1, 50, 1, 0)
  local integrityValueGearRatioChange = linearScale(device.damageGearRatioChangeRateCoef, 1, 0.2, 1, 0)
  local integrityValueFriction = linearScale(device.damageFrictionCoef, 1, 50, 1, 0)
  local integrityValueGearRatioChange = linearScale(device.damageGearRatioChangeRateCoef, 1, 0.2, 1, 0)
@/lua/vehicle/wheels.lua

      wd.brakeThermalEfficiency = thermalEfficiency * linearScale(wd.padGlazingFactor, 0, 1.0, 1, 0.8)

      electrics.values[wd.brakeGlowElectricsName] = linearScale(wd.brakeSurfaceTemperature, wd.brakeGlowTempStart, wd.brakeGlowTempEnd, 0, 1)
      local actualBrakeTorque = abs(wd.coreData.brakeTorqueApplied) - wd.frictionTorque
      brakeSquealPitch = linearScale(wd.brakeMass, 1, 20, 1, 0)
      brakeSquealColor = 0.5 + linearScale(actualBrakeTorque, 0, wd.initialBrakeTorque * 0.5, -0.5, 0.5)
      brakeSquealPitch = linearScale(wd.brakeMass, 1, 20, 1, 0)
      brakeSquealColor = 0.5 + linearScale(actualBrakeTorque, 0, wd.initialBrakeTorque * 0.5, -0.5, 0.5)
      local lowSpeedSquealVolume = wd.squealCoefLowSpeed * (1 - clamp(actualBrakeTorque / 1000, 0, 1)) * (1 - clamp(absAVBrakeCouple / 10, 0, 1))
      local glazingSquealVolume = wd.squealCoefGlazing * linearScale(wd.padGlazingFactor, 0, 0.1, 0, 1)
      --this is required to be gradual as otherwise the final "deflate" from beamstate has way too much effect
      local beamCoef = linearScale(currentPressure, minPressure, wd.startingPressure, 0.1, 1)

      local punctureVolume = linearScale(currentPressure, minPressure, wd.startingPressure, 0, 1) --volume is based on pressure
      local puncturePitch = linearScale(abs(wd.punctureAngle), 0, twoPi, 0, 1) --pitch is tracking the wheel angle so that fmod can apply some volume difference along the rotation
      local punctureVolume = linearScale(currentPressure, minPressure, wd.startingPressure, 0, 1) --volume is based on pressure
      local puncturePitch = linearScale(abs(wd.punctureAngle), 0, twoPi, 0, 1) --pitch is tracking the wheel angle so that fmod can apply some volume difference along the rotation
      local punctureColor = linearScale(wd.tireVolume, 0, 1, 0, 5) or 0
      local puncturePitch = linearScale(abs(wd.punctureAngle), 0, twoPi, 0, 1) --pitch is tracking the wheel angle so that fmod can apply some volume difference along the rotation
      local punctureColor = linearScale(wd.tireVolume, 0, 1, 0, 5) or 0
@/lua/ge/extensions/gameplay/markers/inspectVehicleMarker.lua
local function distanceToHeight(dist)
  return linearScale(dist, nearDist, 700, iconHeightBottom, 500)
end
      self.iconOff:normalize()
      self.iconOff:setScaled(bounce((os.clockhp() * 0.9)%1) * 0.4 * linearScale(distance, nearDist, nearDist +3, 1, 0))
      self.iconPos:setAdd(self.iconOff)
      self.iconPos:setAdd(self.iconOff)
      customSize = linearScale(distance, bigScaleDist, smallScaleDist, 1, 0.65)
    end
@/lua/vehicle/material.lua
        --scale our input value with the expected max
        local emissiveScaleValue = linearScale(localVal, 0, emissiveMax, 0, 255)
        obj:setMaterialEmissiveFactor(va.msc, color(emissiveScaleValue, emissiveScaleValue, emissiveScaleValue))
@/lua/vehicle/powertrain/hydraulicAccumulator.lua

  local reliefPressureScale = linearScale(device.accumulatorPressure, device.reliefOpeningPressure, device.reliefFullyOpenPressure, 0, 1)
  device.reliefFlow = 0.6 * device.reliefValveArea * reliefPressureScale * sqrt(2 * abs(device.accumulatorPressure) * 0.0012) -- 0.6: efficiency, 0.0012: oil density
@/lua/ge/extensions/flowgraph/nodes/mission/ARunForLife.lua
function C:doScore()
  score = score + linearScale(diffPos.y, bottom, top, 1, 3) * currCamSpeed * self.mgr.dtSim * 0.1
  self.pinOut.score.value = score
@/lua/vehicle/powertrain/dctGearbox.lua
local function applyDeformGroupDamage(device, damageAmount)
  device.damageLockTorqueCoef = max(device.damageLockTorqueCoef - linearScale(damageAmount, 0, 0.01, 0, 0.1), 0.2)
end
local function setPartCondition(device, subSystem, odometer, integrity, visual)
  device.wearLockTorqueCoef = linearScale(odometer, 30000000, 500000000, 1, 0.7)
  local integrityState = integrity
    integrityState = {
      damageLockTorqueCoef = linearScale(integrityValue, 1, 0, 1, 0.5)
    }
  }
  local integrityValueLockTorque = linearScale(device.damageLockTorqueCoef, 1, 0.5, 1, 0)
  local integrityValue = min(integrityValueLockTorque)
@/lua/vehicle/powertrain/centrifugalClutch.lua
local function updateTorque(device, dt)
  local clutchRatio = linearScale(device.inputAV, device.engageAVStart, device.engageAVEnd, 0, 1)
local function applyDeformGroupDamage(device, damageAmount)
  device.damageClutchFreePlayCoef = device.damageClutchFreePlayCoef + linearScale(damageAmount, 0, 0.01, 0, 0.01)
  device.damageLockTorqueCoef = max(device.damageLockTorqueCoef - linearScale(damageAmount, 0, 0.01, 0, 0.1), 0.2)
  device.damageClutchFreePlayCoef = device.damageClutchFreePlayCoef + linearScale(damageAmount, 0, 0.01, 0, 0.01)
  device.damageLockTorqueCoef = max(device.damageLockTorqueCoef - linearScale(damageAmount, 0, 0.01, 0, 0.1), 0.2)
  device:calculateInertia()
local function setPartCondition(device, subSystem, odometer, integrity, visual)
  device.wearLockTorqueCoef = linearScale(odometer, 30000000, 500000000, 1, 0.7)
  device.wearClutchFreePlayCoef = linearScale(odometer, 30000000, 500000000, 1, 10)
  device.wearLockTorqueCoef = linearScale(odometer, 30000000, 500000000, 1, 0.7)
  device.wearClutchFreePlayCoef = linearScale(odometer, 30000000, 500000000, 1, 10)
  local integrityState = integrity
    integrityState = {
      damageClutchFreePlayCoef = linearScale(integrityValue, 1, 0, 1, 20),
      damageLockTorqueCoef = linearScale(integrityValue, 1, 0, 1, 0.5),
      damageClutchFreePlayCoef = linearScale(integrityValue, 1, 0, 1, 20),
      damageLockTorqueCoef = linearScale(integrityValue, 1, 0, 1, 0.5),
      clutchPermanentlyDamaged = false
  }
  local integrityValueFreePlay = linearScale(device.damageClutchFreePlayCoef, 1, 20, 1, 0)
  local integrityValueLockTorque = linearScale(device.damageLockTorqueCoef, 1, 0.5, 1, 0)
  local integrityValueFreePlay = linearScale(device.damageClutchFreePlayCoef, 1, 20, 1, 0)
  local integrityValueLockTorque = linearScale(device.damageLockTorqueCoef, 1, 0.5, 1, 0)
  local integrityValue = min(integrityValueFreePlay, integrityValueLockTorque)
@/lua/vehicle/controller/couplings/fifthwheel.lua
    currentKingpinNodeCid = obj2nodeId
    local aggressionCoef = linearScale(attachForce, 0.1, 1, 0, 1)
    if fithwheelAttachSoundEvent then
@/lua/vehicle/energyStorage/pressureTank.lua
    local currentTankDeformDamage = beamstate.deformGroupDamage[storage.damageDeformGroup] and beamstate.deformGroupDamage[storage.damageDeformGroup].damage or 0
    storage.currentLeakRate = clamp(linearScale(currentTankDeformDamage, 0, 1, 0, storage.maxLeakRate), storage.currentLeakRate, storage.maxLeakRate)
  end
@/lua/vehicle/controller/braking/brakedDifferentialSteering.lua
  local steering = electrics.values.steering_input or 0
  local brakedSteeringSpeedCoef = linearScale(electrics.values.wheelspeed or 1, 0, 0.2, 0, 1)

  leftBrake = linearScale(-clamp(steering, -1, 0), steeringPlay, 1, 0, 1) * brakedSteeringSpeedCoef
  rightBrake = linearScale(clamp(steering, 0, 1), steeringPlay, 1, 0, 1) * brakedSteeringSpeedCoef
  leftBrake = linearScale(-clamp(steering, -1, 0), steeringPlay, 1, 0, 1) * brakedSteeringSpeedCoef
  rightBrake = linearScale(clamp(steering, 0, 1), steeringPlay, 1, 0, 1) * brakedSteeringSpeedCoef
end
@/lua/vehicle/controller/advancedCouplerControl.lua
    if isCorrectPastState and isCorrectCurrentState and couplerGroup.canPlaySounds then
      local aggressionCoef = linearScale(attachForce, 0.1, 1, 0, 1)
      obj:playSFXOnceCT(couplerGroup.attachSoundEvent, couplerGroup.soundNode, couplerGroup.attachSoundVolume, 0.5, aggressionCoef, 0)
@/lua/vehicle/extensions/tech/CANBus/ProjectBavariaController.lua

  hardwareState.axes.touchX1 = linearScale(x1, -255, 255, 0, 1)
  hardwareState.axes.touchY1 = linearScale(y1, -15, 15, 0, 1)
  hardwareState.axes.touchX1 = linearScale(x1, -255, 255, 0, 1)
  hardwareState.axes.touchY1 = linearScale(y1, -15, 15, 0, 1)
@/lua/vehicle/controller/drivingDynamics/supervisors/components/diffControl.lua
  local rearOverrideMin = 0 --not used with this diff type
  local rearOverrideMax = linearScale(bsa, controlParameters.yawControl.openRearDiffOversteerThresholdMax, controlParameters.yawControl.openRearDiffOversteerThresholdMin, 0, 1)
local function yawControlLockableFrontDiff(measuredYaw, expectedYaw, yawDifference, bsa)
  local frontOverrideMin = linearScale(bsa, controlParameters.yawControl.lockableFrontDiffOversteerThresholdMax, controlParameters.yawControl.lockableFrontDiffOversteerThresholdMin, 1, 0)
  local frontOverrideMax = 1 --todo add when reliable understeer prediction exists
  local rearOverrideMin = 0 --todo add when reliable understeer prediction exists
  local rearOverrideMax = linearScale(bsa, controlParameters.yawControl.lockableRearDiffOversteerThresholdMax, controlParameters.yawControl.lockableRearDiffOversteerThresholdMin, 0, 1)
  --TODO
  local rearOverrideMagnitude = linearScale(bsa, -0.2, -0.1, 0.2, 0)
  local rearOverrideSign = wheelSideIndex
@/lua/vehicle/controller/playerController.lua
  local frozenCoef = isFrozen and 0 or 1
  local desiredMovementSpeed = linearScale(movementSpeedCoef, 0, 1, movementSpeedNormal, movementSpeedSprint) * frozenCoef --0 movement speed when locked
  local guardedWalkVector = walkVector:z0() * frozenCoef --set this to zero if frozen to keep the ball locked

  local maxBallAVAdjusted = linearScale(movementSpeedCoef, 0, 1, maxAllowedBallAVNormal, maxAllowedBallAVSprint)
  local ballAVTorqueCoef = linearScale(abs(ballAV), maxBallAVAdjusted, maxBallAVAdjusted + 1, 1, 0)
  local maxBallAVAdjusted = linearScale(movementSpeedCoef, 0, 1, maxAllowedBallAVNormal, maxAllowedBallAVSprint)
  local ballAVTorqueCoef = linearScale(abs(ballAV), maxBallAVAdjusted, maxBallAVAdjusted + 1, 1, 0)
  ballDesiredTorque = ballDesiredTorque * ballAVTorqueCoef
  local yawForceMultiplier = yawMaxForce * enableStabilizationCoef
  yawLeftForce = (yawLeftForceCoef + linearScale(yawRightForceCoef, 0, 0.01, 0.1, 0)) * yawForceMultiplier
  yawRightForce = (yawRightForceCoef + linearScale(yawLeftForceCoef, 0, 0.01, 0.1, 0)) * yawForceMultiplier
  yawLeftForce = (yawLeftForceCoef + linearScale(yawRightForceCoef, 0, 0.01, 0.1, 0)) * yawForceMultiplier
  yawRightForce = (yawRightForceCoef + linearScale(yawLeftForceCoef, 0, 0.01, 0.1, 0)) * yawForceMultiplier
@/lua/vehicle/powertrain/manualGearbox.lua
    local avDifference = (device.outputAV1 * device.gearRatios[gearIndex]) - device.inputAV
    device.grindingTorque = linearScale(avDifference, 1, 1000, device.maxGrindingTorque, device.maxGrindingTorque * 0.1)
    device.grindingTorqueSign = sign(avDifference)
  --   if device.gearPopOutTimer <= 0 then
  --     local gearPopOutChance = linearScale(device.synchroWear[device.gearIndex], 0.75, 1, 0.99, 0.95) --1% chance at 75% damage, 5% chance at 100% damage
  --     if math.random() > gearPopOutChance then
    --print(string.format("AV difference: %.2f", avDifference))
    local synchroWearCoef = linearScale(device.synchroWear[newDesiredIndex], 0.1, 1, 1, 0.4)
local function applyDeformGroupDamage(device, damageAmount)
  device.damageFrictionCoef = device.damageFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 0.1)
end
local function setPartCondition(device, subSystem, odometer, integrity, visual)
  device.wearFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 2)
  local integrityState = integrity
    integrityState = {
      damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 50),
      synchroWear = {},
  }
  local integrityValue = linearScale(device.damageFrictionCoef, 1, 50, 1, 0)
  if device.isBroken then
@/lua/ge/extensions/gameplay/drift/drift.lua
local function updateDriftCompleteTime()
  currDriftCompleteTime = linearScale(score.combo, 5, 20, driftOptions.baseDriftCompleteTime, 2.25)
end
@/lua/ge/extensions/gameplay/crashTest/crashTestScoring.lua
  elseif timeElapsed > timeGoal and timeElapsed <= timeGoal + timeGoal / 100 * 30 then
    score = linearScale(timeElapsed, timeGoal, timeGoal + timeGoal / 100 * 30, scoreParameters.maxTimeScore, scoreParameters.minTimeScore)
  end
  local speedDiff = math.abs(roundedSpeed - trSpeedGoal)
  local score = linearScale(speedDiff, 0, trSpeedOffset, scoreParameters.maxSpeedScore, 0)
  return {score = math.ceil(score), scoreName = "Impact Speed Score", maxScore = scoreParameters.maxSpeedScore, targetSpeed = {text = "Required impact speed", value = trSpeedGoal, unit = unit} , actualSpeed = {text = "Registered impact speed", value = roundedSpeed, unit = unit}, diff = {text = "Speed difference", value = speedDiff, unit = unit}}
@/lua/vehicle/controller/sound/linearMovement.lua
  --calculate the desird pitch based on the beam length velocity
  local pitch = linearScale(movementVelocity, movementSoundPitchMinVelocity, movementSoundPitchMaxVelocity, movementSoundMinPitch, movementSoundMaxPitch)
  --calculate our volume based on the base volume from jbeam and a little fade coef based on the beam length velocity
  --calculate our volume based on the base volume from jbeam and a little fade coef based on the beam length velocity
  local volume = movementSoundVolume * linearScale(movementVelocity, movementSoundVolumeCoefMinVelocity, movementSoundVolumeCoefMaxVelocity, 0, 1)
@/lua/vehicle/controller/propAnimation/hPattern.lua
  local shiftAggression = controller.mainController.shiftingAggression or 0
  local shiftAnimationSpeedCoef = linearScale(shiftAggression, 0, 1, 0.3, 1)
@/lua/vehicle/controller/drivingDynamics/sensors/vehicleData.lua

  turningCircle.centerFinal = linearScale(speed, 3, 5, turningCircle.centerSTM, turningCircle.centerAcc)
@/lua/vehicle/powertrain/hydraulicCylinder.lua
  cylinder.currentExtend = currentExtend * invBeamCount
  cylinder.currentExtendPercent = linearScale(cylinder.currentExtend, cylinder.minExtend, cylinder.maxExtend, 0, 1)
  cylinder.velocity = currentBeamVelocity * invBeamCount
  cylinder.currentExtend = currentExtend * invBeamCount
  cylinder.currentExtendPercent = linearScale(cylinder.currentExtend, cylinder.minExtend, cylinder.maxExtend, 0, 1)
  cylinder.velocity = currentBeamVelocity * invBeamCount
  if cylinder.valvePosition < cylinder.dropInputThreshold then
    local dropInput = linearScale(abs(cylinder.valvePosition), abs(cylinder.dropInputThreshold), 1, 0, 1)
    slipForce = linearScale(dropInput, 0, 1, slipForce, 0)
    local dropInput = linearScale(abs(cylinder.valvePosition), abs(cylinder.dropInputThreshold), 1, 0, 1)
    slipForce = linearScale(dropInput, 0, 1, slipForce, 0)
    slipSpeedLimit = linearScale(dropInput * dropInput, 0, 1, 0, cylinder.cylinderReliefSlipSpeedLimit)
    slipForce = linearScale(dropInput, 0, 1, slipForce, 0)
    slipSpeedLimit = linearScale(dropInput * dropInput, 0, 1, 0, cylinder.cylinderReliefSlipSpeedLimit)
    inputPressure = 0
  cylinder.currentExtend = currentExtend * invBeamCount
  cylinder.currentExtendPercent = linearScale(cylinder.currentExtend, cylinder.minExtend, cylinder.maxExtend, 0, 1)
  cylinder.velocity = currentBeamVelocity * invBeamCount
  flowDragCoef = flowDragCoef * (1 - bypassOpenSmooth * abs(cylinder.valvePosition))
  speedLimit = linearScale(bypassOpenSmooth, 0, 1, speedLimit, bypassSpeedLimit)
  cylinder.currentExtend = currentExtend * invBeamCount
  cylinder.currentExtendPercent = linearScale(cylinder.currentExtend, cylinder.minExtend, cylinder.maxExtend, 0, 1)
  cylinder.velocity = currentBeamVelocity * invBeamCount
    if valvePosition < cylinder.dropInputThreshold then
      local dropInput = linearScale(abs(valvePosition), abs(cylinder.dropInputThreshold), 1, 0, 1)
      slipForce = 0
      slipForce = 0
      slipSpeedLimit = linearScale(dropInput * dropInput, 0, 1, 0, cylinder.cylinderReliefSlipSpeedLimit)
      inputPressure = 0
  cylinder.currentExtend = currentExtend * invBeamCount
  cylinder.currentExtendPercent = linearScale(cylinder.currentExtend, cylinder.minExtend, cylinder.maxExtend, 0, 1)
  cylinder.velocity = currentBeamVelocity * invBeamCount
  --cylinder.flowDragCoef = cylinder.minimumDragCoef + (1 - abs(valvePosition)) * cylinder.dragCoefRange
  cylinder.flowDragCoef = linearScale(abs(valvePosition), 0, 1, cylinder.maximumDragCoef, cylinder.minimumDragCoef)
end
    local absVelocitySmooth = cylinder.movementVelocitySmoothing:get(abs(cylinder.velocity), dt)
    local volume = linearScale(absVelocitySmooth, cylinder.movementLoopVolumeMinVelocity, cylinder.movementLoopVolumeMaxVelocity, cylinder.movementLoopVolumeMin, cylinder.movementLoopVolumeMax)
    obj:setVolumePitchCT(cylinder.movementSound, volume, 1, 0, 0)
  cylinder.currentExtend = cylinder.currentExtend * cylinder.invBeamCount
  cylinder.currentExtendPercent = linearScale(cylinder.currentExtend, cylinder.minExtend, cylinder.maxExtend, 0, 1)
@/lua/vehicle/powertrain/turbocharger.lua
local function applyDeformGroupDamage(damageAmount)
  damageFrictionCoef = damageFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 1)
  damageExhaustPowerCoef = max(damageExhaustPowerCoef - linearScale(damageAmount, 0, 0.01, 0, 0.1), 0)
  damageFrictionCoef = damageFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 1)
  damageExhaustPowerCoef = max(damageExhaustPowerCoef - linearScale(damageAmount, 0, 0.01, 0, 0.1), 0)
  damageTracker.setDamage("engine", "inductionSystemDamaged", true, true)
local function setPartCondition(odometer, integrity, visual)
  wearFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 2)
  local integrityState = integrity
    integrityState = {
      damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 20),
      damageExhaustPowerCoef = linearScale(integrityValue, 1, 0, 1, 0.2)
      damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 20),
      damageExhaustPowerCoef = linearScale(integrityValue, 1, 0, 1, 0.2)
    }

  local frictionIntegrityValue = linearScale(damageFrictionCoef, 1, 20, 1, 0)
  local exhaustPowerIntegrityValue = linearScale(damageExhaustPowerCoef, 1, 0.2, 1, 0)
  local frictionIntegrityValue = linearScale(damageFrictionCoef, 1, 20, 1, 0)
  local exhaustPowerIntegrityValue = linearScale(damageExhaustPowerCoef, 1, 0.2, 1, 0)
@/lua/vehicle/sounds.lua
    -- 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)

  local tireContactPatchCoef = linearScale((wd.radius * wd.tireWidth), 0, 0.17, 0, 1) -- max contact patch so far is 0.165
  local tireContactPatchReverseNormalCoef = linearScale((wd.radius * wd.tireWidth), 0, 0.17, 1.5, 0.5) -- max contact patch so far is 0.165
  local tireContactPatchCoef = linearScale((wd.radius * wd.tireWidth), 0, 0.17, 0, 1) -- max contact patch so far is 0.165
  local tireContactPatchReverseNormalCoef = linearScale((wd.radius * wd.tireWidth), 0, 0.17, 1.5, 0.5) -- max contact patch so far is 0.165
  --local tireLinearScaleRadius = linearScale(wd.radius, 0, 0.5, 0, 1) -- used to help bring in the tread noise of large rugged tires
  local tireContactPatchReverseNormalCoef = linearScale((wd.radius * wd.tireWidth), 0, 0.17, 1.5, 0.5) -- max contact patch so far is 0.165
  --local tireLinearScaleRadius = linearScale(wd.radius, 0, 0.5, 0, 1) -- used to help bring in the tread noise of large rugged tires
  --local tireVolWidthCoef = linearScale(wd.tireWidth, 0.05, 0.35, 0, 1)
  --local tireLinearScaleRadius = linearScale(wd.radius, 0, 0.5, 0, 1) -- used to help bring in the tread noise of large rugged tires
  --local tireVolWidthCoef = linearScale(wd.tireWidth, 0.05, 0.35, 0, 1)
  local tireVolProfileCoef = linearScale(wd.radius - wd.hubRadius, 0, 0.3, 1.4, 0.6)
  --local tireVolWidthCoef = linearScale(wd.tireWidth, 0.05, 0.35, 0, 1)
  local tireVolProfileCoef = linearScale(wd.radius - wd.hubRadius, 0, 0.3, 1.4, 0.6)
  local tireVolTreadCoef = linearScale(wd.treadCoef, 0, 1, 0.75, 1.25)
  local tireVolProfileCoef = linearScale(wd.radius - wd.hubRadius, 0, 0.3, 1.4, 0.6)
  local tireVolTreadCoef = linearScale(wd.treadCoef, 0, 1, 0.75, 1.25)
  --local tireVolRollSoftCoef = linearScale(wd.softnessCoef, 0, 1, 1.4, 0.6) -- changes the THRESHOLD of when the squeal starts....
  local tireVolTreadCoef = linearScale(wd.treadCoef, 0, 1, 0.75, 1.25)
  --local tireVolRollSoftCoef = linearScale(wd.softnessCoef, 0, 1, 1.4, 0.6) -- changes the THRESHOLD of when the squeal starts....
  local tireVolSkidSoftCoef = linearScale(wd.softnessCoef, 0, 1, 1.5, 1) -- changes the THRESHOLD of when the squeal starts....
  --local tireVolRollSoftCoef = linearScale(wd.softnessCoef, 0, 1, 1.4, 0.6) -- changes the THRESHOLD of when the squeal starts....
  local tireVolSkidSoftCoef = linearScale(wd.softnessCoef, 0, 1, 1.5, 1) -- changes the THRESHOLD of when the squeal starts....
  --local tireVolAirCoefOld = linearScale(wd.tireVolume, 0, 0.2, 0.7, 1.3) -- the larger the volume of air, the higher the volume
  local tireVolSkidSoftCoef = linearScale(wd.softnessCoef, 0, 1, 1.5, 1) -- changes the THRESHOLD of when the squeal starts....
  --local tireVolAirCoefOld = linearScale(wd.tireVolume, 0, 0.2, 0.7, 1.3) -- the larger the volume of air, the higher the volume
  local tireVolAirCoef = linearScale(wd.tireVolume, 0, 0.2, 0.8, 1.2) -- the larger the volume of air, the higher the volume
  --local tireVolAirCoefOld = linearScale(wd.tireVolume, 0, 0.2, 0.7, 1.3) -- the larger the volume of air, the higher the volume
  local tireVolAirCoef = linearScale(wd.tireVolume, 0, 0.2, 0.8, 1.2) -- the larger the volume of air, the higher the volume
  local tirePitchWidthCoef = linearScale(wd.tireWidth, 0.05, 0.35, 0, 1)
  local tireVolAirCoef = linearScale(wd.tireVolume, 0, 0.2, 0.8, 1.2) -- the larger the volume of air, the higher the volume
  local tirePitchWidthCoef = linearScale(wd.tireWidth, 0.05, 0.35, 0, 1)
  local tirePitchRadiusCoef = linearScale(wd.radius - wd.hubRadius, 0, 0.3, 0, 1)
  local tirePitchWidthCoef = linearScale(wd.tireWidth, 0.05, 0.35, 0, 1)
  local tirePitchRadiusCoef = linearScale(wd.radius - wd.hubRadius, 0, 0.3, 0, 1)
  local tirePitchTreadCoef = linearScale(wd.treadCoef, 0, 1, 0.8, 1.2)
  local tirePitchRadiusCoef = linearScale(wd.radius - wd.hubRadius, 0, 0.3, 0, 1)
  local tirePitchTreadCoef = linearScale(wd.treadCoef, 0, 1, 0.8, 1.2)
  local tirePitchSoftCoef = linearScale(wd.softnessCoef, 0, 1, 1.3, 0.7) -- changes the THRESHOLD of when the squeal starts....
  local tirePitchTreadCoef = linearScale(wd.treadCoef, 0, 1, 0.8, 1.2)
  local tirePitchSoftCoef = linearScale(wd.softnessCoef, 0, 1, 1.3, 0.7) -- changes the THRESHOLD of when the squeal starts....
  local tirePitchSoftCoef2 = linearScale(wd.softnessCoef, 0, 1, 0.7, 1.3) -- changes the THRESHOLD of when the squeal starts....
  local tirePitchSoftCoef = linearScale(wd.softnessCoef, 0, 1, 1.3, 0.7) -- changes the THRESHOLD of when the squeal starts....
  local tirePitchSoftCoef2 = linearScale(wd.softnessCoef, 0, 1, 0.7, 1.3) -- changes the THRESHOLD of when the squeal starts....
  local tirePitchAirCoef = linearScale(wd.tireVolume, 0.01, 0.25, 0, 1) -- the larger volume of air, the lower the pitch
  local tirePitchSoftCoef2 = linearScale(wd.softnessCoef, 0, 1, 0.7, 1.3) -- changes the THRESHOLD of when the squeal starts....
  local tirePitchAirCoef = linearScale(wd.tireVolume, 0.01, 0.25, 0, 1) -- the larger volume of air, the lower the pitch
  local tireSlipTreadCoef = linearScale(wd.treadCoef, 0, 1, 0.8, 1.2) -- changed from 0.75/1.25 just to help race tyres get a bit more slip
  local tirePitchAirCoef = linearScale(wd.tireVolume, 0.01, 0.25, 0, 1) -- the larger volume of air, the lower the pitch
  local tireSlipTreadCoef = linearScale(wd.treadCoef, 0, 1, 0.8, 1.2) -- changed from 0.75/1.25 just to help race tyres get a bit more slip
  local tireSlipSoftCoef = linearScale(wd.softnessCoef, 0, 1, 1.25, 0.75)
  local tireSlipTreadCoef = linearScale(wd.treadCoef, 0, 1, 0.8, 1.2) -- changed from 0.75/1.25 just to help race tyres get a bit more slip
  local tireSlipSoftCoef = linearScale(wd.softnessCoef, 0, 1, 1.25, 0.75)
  local tireKickSoftCoef = linearScale(wd.softnessCoef, 0, 1, 0.75, 1.25)
  local tireSlipSoftCoef = linearScale(wd.softnessCoef, 0, 1, 1.25, 0.75)
  local tireKickSoftCoef = linearScale(wd.softnessCoef, 0, 1, 0.75, 1.25)
  local wh = {
@/lua/vehicle/controller/gauges/customModules/dynamicRedlineData.lua
local function updateGaugeData(moduleData, dt)
  local currentTempRedlineCoef = linearScale(electrics.values.oiltemp or 0, minOilTemp, maxOilTemp, coldOilRPMCoef, 1)
  local maxRedline = electrics.values.maxrpm or 0
  local adjustedRedline = maxRedline * currentTempRedlineCoef
  local redlineOutput = floor(linearScale(adjustedRedline, minOutputRPM, maxOutputRPM, minOutput, maxOutput))
  local maxGearReached = (electrics.values.gearIndex or 0) >= (electrics.values.maxGearIndex or 0)
@/lua/vehicle/controller/hydraulics/orbitrolSteering.lua
  currentSteering = currentSteering * invSteeringCylinderCount
  currentSteering = linearScale(currentSteering, steeringPositionMin, steeringPositionMax, -1, 1)
@/lua/vehicle/controller/vehicleController/shiftLogic/dctGearbox.lua
  local gearRatioDifference = abs(gearbox.gearRatios[previousGearIndex] - gearbox.gearRatios[newDesiredGearIndex])
  local inertiaCoef = linearScale(engine.inertia, 0.1, 0.5, 0.1, 1)
  local gearRatioCoef = linearScale(gearRatioDifference * inertiaCoef, 0.5, 1, 1, 0.5)
  local inertiaCoef = linearScale(engine.inertia, 0.1, 0.5, 0.1, 1)
  local gearRatioCoef = linearScale(gearRatioDifference * inertiaCoef, 0.5, 1, 1, 0.5)
  local aggressionCoef = linearScale(M.smoothedValues.drivingAggression, 0.5, 1, 0.1, 1)
  local gearRatioCoef = linearScale(gearRatioDifference * inertiaCoef, 0.5, 1, 1, 0.5)
  local aggressionCoef = linearScale(M.smoothedValues.drivingAggression, 0.5, 1, 0.1, 1)
@/lua/vehicle/controller/powertrainControl/rimPullControl.lua
  --calculate how much torque reduction we want
  local rimPullOutput = linearScale(rimPullInput, 0, 0.5, 1, 0.2)
  --calculate how much brake we want to apply, only apply brake past 50% input
  --calculate how much brake we want to apply, only apply brake past 50% input
  local brakeOutput = linearScale(rimPullInput, 0.5, 1, 0, 1)
@/lua/vehicle/extensions/tech/CANBus/ProjectBavariaKombi.lua

  local fuel = linearScale(electrics.values.fuel, 0, 1, 9500, 750) --750 -> full, 9500  -> empty
  local fuel1, fuel2 = canBus.twoBytes(fuel)
@/lua/vehicle/powertrain/frictionClutch.lua
local function applyDeformGroupDamage(device, damageAmount)
  device.damageClutchFreePlayCoef = device.damageClutchFreePlayCoef + linearScale(damageAmount, 0, 0.01, 0, 0.01)
  device.damageLockTorqueCoef = max(device.damageLockTorqueCoef - linearScale(damageAmount, 0, 0.01, 0, 0.1), 0.2)
  device.damageClutchFreePlayCoef = device.damageClutchFreePlayCoef + linearScale(damageAmount, 0, 0.01, 0, 0.01)
  device.damageLockTorqueCoef = max(device.damageLockTorqueCoef - linearScale(damageAmount, 0, 0.01, 0, 0.1), 0.2)
  device:calculateInertia()
local function setPartCondition(device, subSystem, odometer, integrity, visual)
  device.wearLockTorqueCoef = linearScale(odometer, 30000000, 500000000, 1, 0.7)
  device.wearClutchFreePlayCoef = linearScale(odometer, 30000000, 500000000, 1, 10)
  device.wearLockTorqueCoef = linearScale(odometer, 30000000, 500000000, 1, 0.7)
  device.wearClutchFreePlayCoef = linearScale(odometer, 30000000, 500000000, 1, 10)
  local integrityState = integrity
    integrityState = {
      damageClutchFreePlayCoef = linearScale(integrityValue, 1, 0, 1, 20),
      damageLockTorqueCoef = linearScale(integrityValue, 1, 0, 1, 0.5),
      damageClutchFreePlayCoef = linearScale(integrityValue, 1, 0, 1, 20),
      damageLockTorqueCoef = linearScale(integrityValue, 1, 0, 1, 0.5),
      clutchPermanentlyDamaged = false
  }
  local integrityValueFreePlay = linearScale(device.damageClutchFreePlayCoef, 1, 20, 1, 0)
  local integrityValueLockTorque = linearScale(device.damageLockTorqueCoef, 1, 0.5, 1, 0)
  local integrityValueFreePlay = linearScale(device.damageClutchFreePlayCoef, 1, 20, 1, 0)
  local integrityValueLockTorque = linearScale(device.damageLockTorqueCoef, 1, 0.5, 1, 0)
  local integrityValue = min(integrityValueFreePlay, integrityValueLockTorque)
@/lua/vehicle/powertrain/linearActuator.lua
  device.currentExtend = currentExtend * invCidCount
  device.currentExtendPercent = linearScale(device.currentExtend, device.minExtend, device.maxExtend, 0, 1)
local function applyDeformGroupDamage(device, damageAmount)
  device.damageFrictionCoef = device.damageFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 0.1)
end
local function setPartCondition(device, subSystem, odometer, integrity, visual)
  device.wearFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 1.5)
  local integrityState = integrity
    local integrityValue = integrity
    integrityState = {damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 50), isBroken = false}
  end
  local integrityState = {damageFrictionCoef = device.damageFrictionCoef, isBroken = device.isBroken}
  local integrityValue = linearScale(device.damageFrictionCoef, 1, 50, 1, 0)
  if device.isBroken then
@/lua/vehicle/controller/pneumatics/autoLevelSuspension.lua
        if abs(lengthError) > actuationStartDistance then
          actuationCoef = linearScale(abs(lengthError), actuationStartDistance, actuationEndDistance, minValveOpenAmount, 1) * sign(lengthError)
          controlGroup.timeOutsideTarget = controlGroup.timeOutsideTarget + dt
@/lua/vehicle/controller/drivingDynamics/actuators/activeDiffBias.lua
      avDiffBiasCoef = biasPID:get(avDiffCorrected, 0, dt)
      local gForceCoef = linearScale(abs(CMU.sensorHub.accelerationXSmooth), 7, 10, 0, 1)
      local throttleCoef = linearScale(electrics.values.throttle or 0, 0, 0.5, 0, 1)
      local gForceCoef = linearScale(abs(CMU.sensorHub.accelerationXSmooth), 7, 10, 0, 1)
      local throttleCoef = linearScale(electrics.values.throttle or 0, 0, 0.5, 0, 1)
      steeringBiasCoef = linearScale(abs(electrics.values.steering), 0.1, 0.3, 0, 1) * sign(electrics.values.steering) * gForceCoef * throttleCoef
      local throttleCoef = linearScale(electrics.values.throttle or 0, 0, 0.5, 0, 1)
      steeringBiasCoef = linearScale(abs(electrics.values.steering), 0.1, 0.3, 0, 1) * sign(electrics.values.steering) * gForceCoef * throttleCoef
    else

  biasOffset = linearScale(avDiffBiasCoef + steeringBiasCoef, -1, 1, -controlParameters.maxBiasOffset, controlParameters.maxBiasOffset)
  biasOffset = clamp(biasOffset, M.overrideMin, M.overrideMax)
@/lua/vehicle/controller/drivingDynamics/supervisors/slipProviders/virtualSpeedSlip.lua
  --we only want to record slip when we are actually powering the wheels
  local torqueCoef = linearScale(wheelGroup.motor.throttle, 0, 0.01, 0, 1)
  local speedTrustCoef = linearScale(CMU.virtualSensors.trustWorthiness.virtualSpeed, 0.5, 0.8, 0, 1)
  local torqueCoef = linearScale(wheelGroup.motor.throttle, 0, 0.01, 0, 1)
  local speedTrustCoef = linearScale(CMU.virtualSensors.trustWorthiness.virtualSpeed, 0.5, 0.8, 0, 1)
  local slipCoef = min(torqueCoef, steeringCoef, speedTrustCoef)
  local vehicleVelocity = CMU.virtualSensors.virtual.speed
  local speedTrustCoef = linearScale(CMU.virtualSensors.trustWorthiness.virtualSpeed, 0.5, 0.8, 0, 1)
  local slipCoef = min(speedTrustCoef, 1)
@/lua/vehicle/controller/drivingDynamics/supervisors/components/brakeControl.lua

  local maximumSpeedCoef = linearScale(CMU.virtualSensors.virtual.speed, groupControlData.maxVelocity, groupControlData.maxVelocity + 1, 1, 0)
  local slipRangeCoef = linearScale(wheelGroup.slipRange, groupControlData.slipRangeThreshold, groupControlData.slipRangeThreshold * 2, 0, 1)
  local maximumSpeedCoef = linearScale(CMU.virtualSensors.virtual.speed, groupControlData.maxVelocity, groupControlData.maxVelocity + 1, 1, 0)
  local slipRangeCoef = linearScale(wheelGroup.slipRange, groupControlData.slipRangeThreshold, groupControlData.slipRangeThreshold * 2, 0, 1)
  local finalBrakeFactor = max(avBrakeFactor, slipAngleBrakeFactor)
  local antiLockUpFactor = linearScale(abs(wheelToBrake.angularVelocityBrakeCouple), 2, 5, 0, 1)
  wheelData.brakeFactorYawControl = finalBrakeFactor * antiLockUpFactor
      local absCoef = 1 - absData.absBrakingPID:get(-wheelData.slip, -absData.slipThreshold, absDT)
      local steeringCoef = linearScale(abs(CMU.sensorHub.yawAVSmooth), 0, absData.steeringCoefYawRate, 1, absData.minSteeringCoef)
      absCoef = absCoef * steeringCoef
@/lua/vehicle/powertrain/torqueConverter.lua
local function applyDeformGroupDamage(device, damageAmount)
  device.damageLockupClutchTorqueCoef = device.damageLockupClutchTorqueCoef - linearScale(damageAmount, 0, 0.01, 0, 0.05)
local function setPartCondition(device, subSystem, odometer, integrity, visual)
  device.wearLockupClutchTorqueCoef = linearScale(odometer, 30000000, 500000000, 1, 0.2)
  local integrityState = integrity
    integrityState = {
      damageLockupClutchTorqueCoef = linearScale(integrityValue, 1, 0, 1, 0)
    }
  local integrityState = {damageLockupClutchTorqueCoef = device.damageLockupClutchTorqueCoef}
  local integrityValue = linearScale(device.damageLockupClutchTorqueCoef, 1, 0, 1, 0)
@/lua/vehicle/powertrain/compressor.lua
  local inputAV = device.inputAV
  local volumeCoef = linearScale(inputAV, 10, 20, 0, 1)
  local volume = device.compressorSoundVolume * volumeCoef
@/lua/ge/extensions/gameplay/sites/zone.lua
    if dist > fullAlphaDistance and nearCam then
      clrI.a = shapeAlpha * 255 * clamp(linearScale(dist, fullAlphaDistance, drawDistance, 1, 0), 0,1)
    else
@/lua/vehicle/controller/drivingDynamics/supervisors/components/awdControl.lua
local function yawControlRearMain(bsa)
  local overrideMin = linearScale(bsa, 0, controlParameters.yawControl.slipAngleThreshold, 0, 1)
  local overrideMax = 1 --todo change once understeer can be detected reliably
  local overrideMin = 0 --todo change once understeer can be detected reliably
  local overrideMax = linearScale(bsa, 0, controlParameters.yawControl.slipAngleThreshold, 1, 0)
  return overrideMin, overrideMax
@/lua/vehicle/powertrain/supercharger.lua
local function applyDeformGroupDamage(damageAmount)
  damagePressureCoef = clamp(damagePressureCoef - linearScale(damageAmount, 0, 0.01, 0, 1), -0.1, 1)
  damageTracker.setDamage("engine", "inductionSystemDamaged", true, true)
local function setPartCondition(odometer, integrity, visual)
  wearPressureCoef = linearScale(odometer, 30000000, 1000000000, 1, 0.5)
  local integrityState = integrity
    integrityState = {
      damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 0.5),
      damageExhaustPowerCoef = linearScale(integrityValue, 1, 0, 1, 0.2)
      damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 0.5),
      damageExhaustPowerCoef = linearScale(integrityValue, 1, 0, 1, 0.2)
    }

  local pressureIntegrityValue = linearScale(damagePressureCoef, 1, 0.5, 1, 0)
@/lua/vehicle/ai.lua
  local roadHalfWidth = planNode.halfWidth
  planNode.laneLimLeft = linearScale(planNode.rangeLeft, 0, 1, -roadHalfWidth, roadHalfWidth)
  planNode.laneLimRight = linearScale(planNode.rangeRight, 0, 1, -roadHalfWidth, roadHalfWidth)
  planNode.laneLimLeft = linearScale(planNode.rangeLeft, 0, 1, -roadHalfWidth, roadHalfWidth)
  planNode.laneLimRight = linearScale(planNode.rangeRight, 0, 1, -roadHalfWidth, roadHalfWidth)
  planNode.lanesOpen = true
  if not planNode.rangeLeft then planNode.rangeLeft, planNode.rangeRight = laneRange(newNode.inEdgeLanes) end
  local rangeLeft = linearScale(planNode.rangeLeft or 0, 0, 1, -halfWidth, halfWidth)
  local rangeRight = linearScale(planNode.rangeRight or 1, 0, 1, -halfWidth, halfWidth)
  local rangeLeft = linearScale(planNode.rangeLeft or 0, 0, 1, -halfWidth, halfWidth)
  local rangeRight = linearScale(planNode.rangeRight or 1, 0, 1, -halfWidth, halfWidth)

    local planNodeLatPosNrmd = linearScale(planNodeLatPos, planNodeRangeLeft, planNodeRangeRight, newNode.rangeLeft, newNode.rangeRight) -- TODO: lateralXnorm might be outside [inRangeLeft, inRangeRight]
    local planNodeLaneLimLeftNrmd = linearScale(planNodelaneLimLeft, planNodeRangeLeft, planNodeRangeRight, newNode.rangeLeft, newNode.rangeRight)
    local planNodeLatPosNrmd = linearScale(planNodeLatPos, planNodeRangeLeft, planNodeRangeRight, newNode.rangeLeft, newNode.rangeRight) -- TODO: lateralXnorm might be outside [inRangeLeft, inRangeRight]
    local planNodeLaneLimLeftNrmd = linearScale(planNodelaneLimLeft, planNodeRangeLeft, planNodeRangeRight, newNode.rangeLeft, newNode.rangeRight)
    local planNodeLaneLimRightNrmd = linearScale(planNodelaneLimRight, planNodeRangeLeft, planNodeRangeRight, newNode.rangeLeft, newNode.rangeRight)
    local planNodeLaneLimLeftNrmd = linearScale(planNodelaneLimLeft, planNodeRangeLeft, planNodeRangeRight, newNode.rangeLeft, newNode.rangeRight)
    local planNodeLaneLimRightNrmd = linearScale(planNodelaneLimRight, planNodeRangeLeft, planNodeRangeRight, newNode.rangeLeft, newNode.rangeRight)
    -- Calculate the most appropriate lane out of newNodeLaneConfig. This will be where to position the new node lateraly along the normal of newNode.
    local rangeLeftOrig, rangeRightOrig = laneRange(newNodeLaneConfigOrig) -- Will this work when the lane config is not monotonic?
    newNode.rangeLeft = linearScale(newNode.rangeLeft, rangeLeft, rangeRight, rangeLeftOrig, rangeRightOrig)
    newNode.rangeRight = linearScale(newNode.rangeRight, rangeLeft, rangeRight, rangeLeftOrig, rangeRightOrig)
    newNode.rangeLeft = linearScale(newNode.rangeLeft, rangeLeft, rangeRight, rangeLeftOrig, rangeRightOrig)
    newNode.rangeRight = linearScale(newNode.rangeRight, rangeLeft, rangeRight, rangeLeftOrig, rangeRightOrig)
    --newNode.laneLimLeft = linearScale(newNodeRangeLeft + (bestLane - newNodeRangeLeftIdx) * laneWidth, 0, 1, -roadHalfWidth, roadHalfWidth)
    newNode.rangeRight = linearScale(newNode.rangeRight, rangeLeft, rangeRight, rangeLeftOrig, rangeRightOrig)
    --newNode.laneLimLeft = linearScale(newNodeRangeLeft + (bestLane - newNodeRangeLeftIdx) * laneWidth, 0, 1, -roadHalfWidth, roadHalfWidth)
    --newNodeLaneLimRight = linearScale(newNodeRangeLeft + (bestLane - newNodeRangeLeftIdx) + 1) * laneWidth, 0, 1, -roadHalfWidth, roadHalfWidth)
    --newNode.laneLimLeft = linearScale(newNodeRangeLeft + (bestLane - newNodeRangeLeftIdx) * laneWidth, 0, 1, -roadHalfWidth, roadHalfWidth)
    --newNodeLaneLimRight = linearScale(newNodeRangeLeft + (bestLane - newNodeRangeLeftIdx) + 1) * laneWidth, 0, 1, -roadHalfWidth, roadHalfWidth)
    newNode.laneLimLeft = linearScale(newNode.laneLimLeft, rangeLeft, rangeRight, rangeLeftOrig, rangeRightOrig)
    --newNodeLaneLimRight = linearScale(newNodeRangeLeft + (bestLane - newNodeRangeLeftIdx) + 1) * laneWidth, 0, 1, -roadHalfWidth, roadHalfWidth)
    newNode.laneLimLeft = linearScale(newNode.laneLimLeft, rangeLeft, rangeRight, rangeLeftOrig, rangeRightOrig)
    newNode.laneLimRight = linearScale(newNode.laneLimRight, rangeLeft, rangeRight, rangeLeftOrig, rangeRightOrig)
    newNode.laneLimLeft = linearScale(newNode.laneLimLeft, rangeLeft, rangeRight, rangeLeftOrig, rangeRightOrig)
    newNode.laneLimRight = linearScale(newNode.laneLimRight, rangeLeft, rangeRight, rangeLeftOrig, rangeRightOrig)
    if (push3(mapData.positions[newNode.nextNodeInPath]) - newNode.posOrig + mapData.positions[newNode.prevNodeInPath] - newNode.posOrig):dot(newNode.normal) < 0 then -- = turnDir * normal
      newNode.laneLimLeft = linearScale(newNode.rangeLeft, 0, 1, -newNode.halfWidth, newNode.halfWidth) + (bestLane - newNodeRangeLeftIdx) * laneWidth
      --[[ tighter outside left turns
      newNode.laneLimLeft = -newNodeHalfWidth + (bestLane - 1) * laneWidth
      newNode.rangeLeft = min(newNodeRangeLeft, linearScale(-newNodeHalfWidth + (newNodeRangeLeftIdx - 1) * laneWidth, -newNodeHalfWidth, newNodeHalfWidth, 0, 1))
      --]]
    else
      newNode.laneLimRight = linearScale(newNode.rangeRight, 0, 1, -newNode.halfWidth, newNode.halfWidth) - (newNodeRangeRightIdx - bestLane) * laneWidth
      newNode.laneLimLeft = newNode.laneLimRight - laneWidth
    -- Transform newNode lateral position and lane limits from [0, 1] to [-r, r] using the recalculated newNodeHalfWidth
    newNode.laneLimLeft = linearScale(newNode.laneLimLeft, 0, 1, -newNode.halfWidth, newNode.halfWidth)
    newNode.laneLimRight = linearScale(newNode.laneLimRight, 0, 1, -newNode.halfWidth, newNode.halfWidth)
    newNode.laneLimLeft = linearScale(newNode.laneLimLeft, 0, 1, -newNode.halfWidth, newNode.halfWidth)
    newNode.laneLimRight = linearScale(newNode.laneLimRight, 0, 1, -newNode.halfWidth, newNode.halfWidth)
    newNode.lateralXnorm = (newNode.laneLimLeft + newNode.laneLimRight) * 0.5
  --  -- catching distance: distance from vehicle ahead up to which I can increase my trafficTargetSpeed in order to catch him
  --  ego.race.d = linearScale(dv, 0, 20, 0.5 * ego.length, 2 * ego.length)
  --  --ego.race.d = (square(ego.speed) - square(plan.trafficMinProjSpeed))/(min(aggression, ego.staticFrictionCoef) * 2 * g)

      local laneLimLeft = linearScale(rangeLeft + rangeBestLane * laneWidth, 0, 1, -roadHalfWidth, roadHalfWidth) -- lateral coordinate of left boundary of lane rescaled to the road half width
      local laneLimRight = linearScale(rangeLeft + (rangeBestLane + 1) * laneWidth, 0, 1, -roadHalfWidth, roadHalfWidth) -- lateral coordinate of right boundary of lane rescaled to the road half width
      local laneLimLeft = linearScale(rangeLeft + rangeBestLane * laneWidth, 0, 1, -roadHalfWidth, roadHalfWidth) -- lateral coordinate of left boundary of lane rescaled to the road half width
      local laneLimRight = linearScale(rangeLeft + (rangeBestLane + 1) * laneWidth, 0, 1, -roadHalfWidth, roadHalfWidth) -- lateral coordinate of right boundary of lane rescaled to the road half width
          local current_throttle = clamp((mainPlan.targetSpeed - ego.speed) * parameters.throttleKp, 0, 1)
          local delta_throttle = linearScale(mainPlan.distances, ego.length, 3 * ego.length, ego.race.dT_min, ego.race.dT_max)
          local cost_time = mainPlan.planLen/max(mainPlan.targetSpeed, 0.1)
          if n.rangeLeft and n.rangeRight then
            local rangeLeft = linearScale(n.rangeLeft, 0, 1, -roadHalfWidth, roadHalfWidth)
            local rangeRight = linearScale(n.rangeRight, 0, 1, -roadHalfWidth, roadHalfWidth)
            local rangeLeft = linearScale(n.rangeLeft, 0, 1, -roadHalfWidth, roadHalfWidth)
            local rangeRight = linearScale(n.rangeRight, 0, 1, -roadHalfWidth, roadHalfWidth)
            debugDrawer:drawSquarePrism(n.posOrig + rangeLeft * n.normal, n.posOrig + rangeRight * n.normal, tmpVec1, tmpVec1, color(255,0,0,120))
@/lua/vehicle/controller/powertrainControl/combustionEngineGovenor.lua
  local throttle = electrics.values[throttleInputElectricsName] or 0
  local targetAV = linearScale(throttle, 0, 1, avTarget0, avTarget1)
  local currentAV = controlledEngine.outputAV1
@/lua/vehicle/controller/drivingDynamics/sensors/virtualSensors.lua
  local invSpeed = 1 / max(virtual.speed, 0.0000001)
  local lowSpeedCoef = linearScale(abs(virtual.speed), 0.1, 1, 0, 1)

  virtual.bodySlipAngle = linearScale(abs(virtual.speed), 0, 2, virtual.bodySlipAngleLowSpeed, virtual.bodySlipAngleIntegrated)

  trustWorthiness.pitch = linearScale(abs(sensorHub.pitch), 1.4, halfPi, 1, 0)
  trustWorthiness.roll = linearScale(abs(sensorHub.roll), 1.4, halfPi, 1, 0)
  trustWorthiness.pitch = linearScale(abs(sensorHub.pitch), 1.4, halfPi, 1, 0)
  trustWorthiness.roll = linearScale(abs(sensorHub.roll), 1.4, halfPi, 1, 0)
  trustWorthiness.bodySlipAngle = linearScale(abs(virtual.bodySlipAngle), 0.8, 1.0, 1, 0)
  trustWorthiness.roll = linearScale(abs(sensorHub.roll), 1.4, halfPi, 1, 0)
  trustWorthiness.bodySlipAngle = linearScale(abs(virtual.bodySlipAngle), 0.8, 1.0, 1, 0)
  trustWorthiness.virtualSpeed = min(trustWorthiness.pitch, trustWorthiness.roll, linearScale(abs(virtual.bodySlipAngle), 0.2, 0.5, 1, 0))
  trustWorthiness.bodySlipAngle = linearScale(abs(virtual.bodySlipAngle), 0.8, 1.0, 1, 0)
  trustWorthiness.virtualSpeed = min(trustWorthiness.pitch, trustWorthiness.roll, linearScale(abs(virtual.bodySlipAngle), 0.2, 0.5, 1, 0))
@/lua/ge/extensions/gameplay/drift/scoring.lua

  wallMulti = 1 + linearScale(driftData.closestWallDistanceFront, driftOptions.wallDetectionLength, 0, 0, scoreOptions.maxWallMulti) + linearScale(driftData.closestWallDistanceRear, driftOptions.wallDetectionLength, 0, 0, scoreOptions.maxWallMulti)
  angleMulti = linearScale(driftData.currDegAngle, driftOptions.minAngle, driftOptions.maxAngle, scoreOptions.minDriftAngleMulti, scoreOptions.maxDriftAngleMulti)

  wallMulti = 1 + linearScale(driftData.closestWallDistanceFront, driftOptions.wallDetectionLength, 0, 0, scoreOptions.maxWallMulti) + linearScale(driftData.closestWallDistanceRear, driftOptions.wallDetectionLength, 0, 0, scoreOptions.maxWallMulti)
  angleMulti = linearScale(driftData.currDegAngle, driftOptions.minAngle, driftOptions.maxAngle, scoreOptions.minDriftAngleMulti, scoreOptions.maxDriftAngleMulti)
  wallMulti = 1 + linearScale(driftData.closestWallDistanceFront, driftOptions.wallDetectionLength, 0, 0, scoreOptions.maxWallMulti) + linearScale(driftData.closestWallDistanceRear, driftOptions.wallDetectionLength, 0, 0, scoreOptions.maxWallMulti)
  angleMulti = linearScale(driftData.currDegAngle, driftOptions.minAngle, driftOptions.maxAngle, scoreOptions.minDriftAngleMulti, scoreOptions.maxDriftAngleMulti)
  speedMulti = math.min(math.max(1, linearScale(driftData.airSpeed, minSpeed, maxSpeed, 1, scoreOptions.maxSpeedMulti) ), scoreOptions.maxSpeedMulti)
  angleMulti = linearScale(driftData.currDegAngle, driftOptions.minAngle, driftOptions.maxAngle, scoreOptions.minDriftAngleMulti, scoreOptions.maxDriftAngleMulti)
  speedMulti = math.min(math.max(1, linearScale(driftData.airSpeed, minSpeed, maxSpeed, 1, scoreOptions.maxSpeedMulti) ), scoreOptions.maxSpeedMulti)
local function onDriftThroughAccomplished(data)
  local score = math.floor(linearScale(data.currDegAngle, 0, 90, 0, data.zoneData.points))
  score = addCachedScore(score, true)
local function onHitPoleAccomplished(data)
  local score = math.floor(linearScale(data.currDegAngle + data.currAirSpeed, 0, 250, 0, data.zoneData.points))
  score = addCachedScore(score, true)
@/lua/vehicle/controller/drivingDynamics/supervisors/tractionControl.lua

  local steeringCoef = linearScale(abs(CMU.sensorHub.steeringInput), 0.3, 0.5, 1, 0.5)
@/lua/ge/extensions/gameplay/util/crashDetection.lua
    local peakAccel, peakAccelVerticallyUnweighted, jerk = calculateAccels(crashData)
    local crashDamageThreshold = linearScale(jerk, crashData.crashSettings.minAccel, crashData.crashSettings.maxAccel, crashData.crashSettings.maxDamage, crashData.crashSettings.minDamage)
@/lua/vehicle/controller/propAnimation/googlyEyes.lua
local function updateGFX(dt)
  local sizeCoef = linearScale(sensors.gz, 0, defaultGravity * gravityMaxSizeCoef, maxSizeCoef, minSizeCoef)
  --local sizeCoef = linearScale(electrics.values.throttle - electrics.values.brake, -1, 1, maxSizeCoef, minSizeCoef)
  local sizeCoef = linearScale(sensors.gz, 0, defaultGravity * gravityMaxSizeCoef, maxSizeCoef, minSizeCoef)
  --local sizeCoef = linearScale(electrics.values.throttle - electrics.values.brake, -1, 1, maxSizeCoef, minSizeCoef)

  local boundCoef = linearScale(sizeCoef, maxSizeCoef, minSizeCoef, maxSizeBoundCoef, minSizeBoundCoef)
  for cid, data in pairs(eyeLimiterData) do

  local attachmentCoef = linearScale(sizeCoef, minSizeCoef, maxSizeCoef, attachmentMinSizeCoef, attachmentMaxSizeCoef)
  for cid, data in pairs(eyeAttachmentData) do
@/lua/ge/extensions/gameplay/markers/parkingMarker.lua
local function distanceToHeight(dist)
  return linearScale(distance, nearDist, 700, iconHeightBottom, 500)
end
      self.iconOff:normalize()
      self.iconOff:setScaled(bounce((os.clockhp() * 0.9)%1) * 0.4 * linearScale(distance, nearDist, nearDist +3, 1, 0))
      self.iconPos:setAdd(self.iconOff)
      self.iconPos:setAdd(self.iconOff)
      customSize = linearScale(distance, bigScaleDist, smallScaleDist, 1, 0.65)
    end
@/lua/vehicle/controller/drivingDynamics/supervisors/yawControl.lua
  local measuredYaw = cmu.sensorHub.yawAVSmooth
  local bodySlipAngleTrustCoef = linearScale(virtualSensors.trustWorthiness.bodySlipAngle, 0.5, 0.8, 0, 1)
  local bodySlipAngleRaw = virtualSensors.virtual.bodySlipAngle * bodySlipAngleTrustCoef

  local lowSpeedCoef = 1 - linearScale(speed, 8, 10, 1, 0)
  bodySlipAngleAdjusted = bodySlipAngleRaw * lowSpeedCoef
@/lua/vehicle/powertrain/hydraulicPump.lua
    --investigate if we need this here or if we can move to the actual hydraulic control logic
    local stallProtection = linearScale(device.inputAV, device.stallProtectionAV * 0.75, device.stallProtectionAV, 0, 1)
    --baseline pressure for dynamic displacement scale
    local baselinePressure = device.pumpWorkingPressure - device.pumpRegulationRange
    device.currentDisplacement = device.pumpMaxDisplacement * device.pumpSmoother:get(linearScale(device.accumulatorPressure, baselinePressure, device.pumpWorkingPressure, 1, 0)) * stallProtection
  elseif device.pumpType == "fixedDisplacement" then
  --gradually open relief flow as pressure builds, otherwise we get unstable pressure limit
  local reliefPressureScale = linearScale(device.accumulatorPressure, device.reliefOpeningPressure, device.reliefFullyOpenPressure, 0, 1)
  device.reliefFlow = 0.6 * device.reliefValveArea * reliefPressureScale * sqrt(2 * abs(device.accumulatorPressure) * 0.0012) -- 0.6: efficiency, 0.0012: oil density
local function updateSounds(device, dt)
  local volumeFlowCoef = linearScale(abs(device.pumpFlowRate), device.pumpLoopVolumeFlowCoefMinFlow, device.pumpLoopVolumeFlowCoefMaxFlow, 0, 1)
  local volumeRaw = linearScale(device.accumulatorPressure, device.pumpLoopVolumeMinPressure, device.pumpLoopVolumeMaxPressure, device.pumpLoopVolumeMin, device.pumpLoopVolumeMax) * volumeFlowCoef
  local volumeFlowCoef = linearScale(abs(device.pumpFlowRate), device.pumpLoopVolumeFlowCoefMinFlow, device.pumpLoopVolumeFlowCoefMaxFlow, 0, 1)
  local volumeRaw = linearScale(device.accumulatorPressure, device.pumpLoopVolumeMinPressure, device.pumpLoopVolumeMaxPressure, device.pumpLoopVolumeMin, device.pumpLoopVolumeMax) * volumeFlowCoef
  local volume = device.volumeSmoothing:get(volumeRaw, dt)
  local volume = device.volumeSmoothing:get(volumeRaw, dt)
  local pitchRaw = linearScale(device.pumpFlowRate, device.pumpLoopPitchMinFlow, device.pumpLoopPitchMaxFlow, 0, 1)
  local pitch = device.pitchSmoothing:get(pitchRaw, dt)
  local pitch = device.pitchSmoothing:get(pitchRaw, dt)
  local normalizedPressure = linearScale(device.accumulatorPressure, 0, device.pumpWorkingPressure, 0, 1)
  device.pumpLoopStartStopEnabled = device.pumpLoopStartStopEnabled or device.pumpFlowRate >= 0.000005
@/lua/vehicle/controller/bypassDampers.lua
    if abs(smoothDirection) >= 1 and smoothDirection ~= damper.previousDirection then
      local volume = linearScale(abs(velocity), soundSettings.minVelocity, soundSettings.maxValocity, 0, 1) -- input value, min input value, max input value, output value at min input, output value at max input
      -- if M.name == "frontBypass" and _ == 1 then
@/lua/vehicle/beamstate.lua

    local tireBurstVolume = linearScale(pressureGroupPressure, 0, 1000000, 0, 1)
    local tireBurstColor = wheels.wheels[wheelid] and linearScale(wheels.wheels[wheelid].tireVolume, 0, 1, 0, 5) or 0
    local tireBurstVolume = linearScale(pressureGroupPressure, 0, 1000000, 0, 1)
    local tireBurstColor = wheels.wheels[wheelid] and linearScale(wheels.wheels[wheelid].tireVolume, 0, 1, 0, 5) or 0
    obj:playSFXOnceCT("event:>Vehicle>Failures>tire_burst", wheel.node1, tireBurstVolume, 1, tireBurstColor, 0)
@/lua/vehicle/powertrain/sequentialGearbox.lua
local function applyDeformGroupDamage(device, damageAmount)
  device.damageFrictionCoef = device.damageFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 0.1)
end
local function setPartCondition(device, subSystem, odometer, integrity, visual)
  device.wearFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 2)
  local integrityState = integrity
    local integrityValue = integrity
    integrityState = {damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 50), isBroken = false}
  end
  local integrityState = {damageFrictionCoef = device.damageFrictionCoef, isBroken = device.isBroken}
  local integrityValue = linearScale(device.damageFrictionCoef, 1, 50, 1, 0)
  if device.isBroken then
@/lua/vehicle/powertrain/combustionEngineThermals.lua
    integrityState = {
      radiatorDamage = linearScale(integrityValue, 1, 0, 0, 0.1),
      coolantMass = linearScale(integrityValue, 1, 0, fluidReservoirs.coolant.initialMass, fluidReservoirs.coolant.initialMass * 0.1)
      radiatorDamage = linearScale(integrityValue, 1, 0, 0, 0.1),
      coolantMass = linearScale(integrityValue, 1, 0, fluidReservoirs.coolant.initialMass, fluidReservoirs.coolant.initialMass * 0.1)
    }

  local radiatorIntegrityValue = linearScale(radiatorDamage, 0, 0.1, 1, 0)
  local coolantIntegrityValue = linearScale(fluidReservoirs.coolant.currentMass, fluidReservoirs.coolant.initialMass, fluidReservoirs.coolant.initialMass * 0.1, 1, 0)
  local radiatorIntegrityValue = linearScale(radiatorDamage, 0, 0.1, 1, 0)
  local coolantIntegrityValue = linearScale(fluidReservoirs.coolant.currentMass, fluidReservoirs.coolant.initialMass, fluidReservoirs.coolant.initialMass * 0.1, 1, 0)
  if oilStarvingTimer >= oilStarvingTimerThreshold * 0.5 then
    oilLubricationCoef = min(oilLubricationCoef, linearScale(oilStarvingSevernessXY, 0, 1, 1, 0)) --handle XY starvation
    oilLubricationCoef = min(oilLubricationCoef, linearScale(oilStarvingSevernessZ, 0, 10, 1, 0)) --handle Z starvation (scales are different, that's why it's two calls)
    oilLubricationCoef = min(oilLubricationCoef, linearScale(oilStarvingSevernessXY, 0, 1, 1, 0)) --handle XY starvation
    oilLubricationCoef = min(oilLubricationCoef, linearScale(oilStarvingSevernessZ, 0, 10, 1, 0)) --handle Z starvation (scales are different, that's why it's two calls)
  end
  if fluidReservoirs.oil.currentMass > fluidReservoirs.oil.maximumSafeMass and fluidReservoirs.oil.maximumSafeMass > 0 then
    oilLubricationCoef = min(oilLubricationCoef, linearScale(fluidReservoirs.oil.currentMass, fluidReservoirs.oil.maximumSafeMass, fluidReservoirs.oil.maximumSafeMass * 1.1, 1, 0.8))
    if not damageTracker.getDamage("engine", "oilLevelTooHigh") then
      local node = nodes.exhaust[random(#nodes.exhaust)]
      local tickSize = linearScale(randomGauss3(), 0, 3, 0, 1) ^ heatTickData.exhaustTickSizeBias
      sounds.playSoundOnceFollowNode(heatTickData.exhaustTickEventName, node, heatTickData.exhaustTickVolume, heatTickData.exhaustTickPitch, tickSize)
      heatTickData.exhaustTickBucket = 0
      heatTickData.exhaustTickBucketThreshold = heatTickData.exhaustTickPeriodGain * linearScale(randomGauss3(), 0, 3, 0.25, 1.75)
    end
      local node = nodes.engine[random(#nodes.engine)]
      local tickSize = linearScale(randomGauss3(), 0, 3, 0, 1) ^ heatTickData.engineTickSizeBias
      sounds.playSoundOnceFollowNode(heatTickData.engineTickEventName, node, heatTickData.engineTickVolume, heatTickData.engineTickPitch, tickSize)
      heatTickData.engineTickBucket = 0
      heatTickData.engineTickBucketThreshold = heatTickData.engineTickPeriodGain * linearScale(randomGauss3(), 0, 3, 0.25, 1.75)
    end
@/lua/vehicle/powertrain/combustionEngine.lua

  electrics.values.electricalLoadCoef = linearScale(device.starterEngagedCoef * min(max(device.outputAV1 * device.invStarterMaxAV, -0.5), 1), 0, 1, 1, 0.3)

  local lowFuelIgnitionErrorChance = linearScale(device.remainingFuelRatio, 0.01, 0, 0, 0.4)
  local fastIgnitionErrorCoef = device.fastIgnitionErrorSmoother:getUncapped(math.random(), dt)
  if device.idleTimer <= 0 then
    local idleTimeRandomCoef = linearScale(device.idleTimeRandomness, 0, 1, 1, randomGauss3() * 0.6666667)
    device.idleTimer = device.idleTimer + device.idleTime * idleTimeRandomCoef
  if groupType == "main" then
    device.damageFrictionCoef = device.damageFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 0.1)
    device.damageDynamicFrictionCoef = device.damageDynamicFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 0.1)
    device.damageFrictionCoef = device.damageFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 0.1)
    device.damageDynamicFrictionCoef = device.damageDynamicFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 0.1)
    device.damageIdleAVReadErrorRangeCoef = device.damageIdleAVReadErrorRangeCoef + linearScale(damageAmount, 0, 0.01, 0, 0.5)
    device.damageDynamicFrictionCoef = device.damageDynamicFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 0.1)
    device.damageIdleAVReadErrorRangeCoef = device.damageIdleAVReadErrorRangeCoef + linearScale(damageAmount, 0, 0.01, 0, 0.5)
    device.fastIgnitionErrorChance = min(device.fastIgnitionErrorChance + linearScale(damageAmount, 0, 0.01, 0, 0.05))
    device.damageIdleAVReadErrorRangeCoef = device.damageIdleAVReadErrorRangeCoef + linearScale(damageAmount, 0, 0.01, 0, 0.5)
    device.fastIgnitionErrorChance = min(device.fastIgnitionErrorChance + linearScale(damageAmount, 0, 0.01, 0, 0.05))
    device.slowIgnitionErrorChance = min(device.slowIgnitionErrorChance + linearScale(damageAmount, 0, 0.01, 0, 0.05))
    device.fastIgnitionErrorChance = min(device.fastIgnitionErrorChance + linearScale(damageAmount, 0, 0.01, 0, 0.05))
    device.slowIgnitionErrorChance = min(device.slowIgnitionErrorChance + linearScale(damageAmount, 0, 0.01, 0, 0.05))
    damageTracker.setDamage("engine", "impactDamage", true, true)
  if not subSystem then
    device.wearFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 1.0)
    device.wearDynamicFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 1.5)
    device.wearFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 1.0)
    device.wearDynamicFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 1.5)
    device.wearIdleAVReadErrorRangeCoef = linearScale(odometer, 30000000, 500000000, 1, 10)
    device.wearDynamicFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 1.5)
    device.wearIdleAVReadErrorRangeCoef = linearScale(odometer, 30000000, 500000000, 1, 10)
    local integrityState = integrity
      integrityState = {
        damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 1.0),
        damageDynamicFrictionCoef = linearScale(integrityValue, 1, 0, 1, 1.5),
        damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 1.0),
        damageDynamicFrictionCoef = linearScale(integrityValue, 1, 0, 1, 1.5),
        damageIdleAVReadErrorRangeCoef = linearScale(integrityValue, 1, 0, 1, 30),
        damageDynamicFrictionCoef = linearScale(integrityValue, 1, 0, 1, 1.5),
        damageIdleAVReadErrorRangeCoef = linearScale(integrityValue, 1, 0, 1, 30),
        fastIgnitionErrorChance = linearScale(integrityValue, 1, 0, 0, 0.4),
        damageIdleAVReadErrorRangeCoef = linearScale(integrityValue, 1, 0, 1, 30),
        fastIgnitionErrorChance = linearScale(integrityValue, 1, 0, 0, 0.4),
        slowIgnitionErrorChance = linearScale(integrityValue, 1, 0, 0, 0.4)
        fastIgnitionErrorChance = linearScale(integrityValue, 1, 0, 0, 0.4),
        slowIgnitionErrorChance = linearScale(integrityValue, 1, 0, 0, 0.4)
      }

    local frictionIntegrityValue = linearScale(device.damageFrictionCoef, 1, 5, 1, 0)
    local dynamicFrictionIntegrityValue = linearScale(device.damageDynamicFrictionCoef, 1, 5, 1, 0)
    local frictionIntegrityValue = linearScale(device.damageFrictionCoef, 1, 5, 1, 0)
    local dynamicFrictionIntegrityValue = linearScale(device.damageDynamicFrictionCoef, 1, 5, 1, 0)
    local idleAVReadErrorRangeIntegrityValue = linearScale(device.damageIdleAVReadErrorRangeCoef, 1, 50, 1, 0)
    local dynamicFrictionIntegrityValue = linearScale(device.damageDynamicFrictionCoef, 1, 5, 1, 0)
    local idleAVReadErrorRangeIntegrityValue = linearScale(device.damageIdleAVReadErrorRangeCoef, 1, 50, 1, 0)
    local slowIgnitionErrorIntegrityValue = linearScale(device.slowIgnitionErrorChance, 0, 0.4, 1, 0)
    local idleAVReadErrorRangeIntegrityValue = linearScale(device.damageIdleAVReadErrorRangeCoef, 1, 50, 1, 0)
    local slowIgnitionErrorIntegrityValue = linearScale(device.slowIgnitionErrorChance, 0, 0.4, 1, 0)
    local fastIgnitionErrorIntegrityValue = linearScale(device.fastIgnitionErrorChance, 0, 0.4, 1, 0)
    local slowIgnitionErrorIntegrityValue = linearScale(device.slowIgnitionErrorChance, 0, 0.4, 1, 0)
    local fastIgnitionErrorIntegrityValue = linearScale(device.fastIgnitionErrorChance, 0, 0.4, 1, 0)
    local coldBlockStartTimeCoef = device.requiredEnergyType == "diesel" and 4 or 2
    device.starterThrottleKillTimer = device.starterThrottleKillTime * linearScale(device.thermals.engineBlockTemperature, -20, 20, coldBlockStartTimeCoef, 1)
    device.starterEngagedCoef = 1
@/lua/vehicle/powertrain/differential.lua

  device.wearFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 2)
  local integrityState = integrity
    integrityState = {
      damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 10),
      isBroken = false
  }
  local integrityValue = linearScale(device.damageFrictionCoef, 1, 10, 1, 0)
  if device.isBroken then
@/lua/vehicle/controller/vehicleController/shiftLogic/manualGearbox.lua
  local gearRatioDifference = abs(gearbox.gearRatios[previousGearIndex] - gearbox.gearRatios[newDesiredGearIndex])
  local inertiaCoef = linearScale(engine.inertia, 0.1, 0.5, 0.1, 1)
  local gearRatioCoef = linearScale(gearRatioDifference * inertiaCoef, 0.5, 1, 1, 0.5)
  local inertiaCoef = linearScale(engine.inertia, 0.1, 0.5, 0.1, 1)
  local gearRatioCoef = linearScale(gearRatioDifference * inertiaCoef, 0.5, 1, 1, 0.5)
  local aggressionCoef = linearScale(M.smoothedValues.drivingAggression, 0.5, 1, 0.1, 1)
  local gearRatioCoef = linearScale(gearRatioDifference * inertiaCoef, 0.5, 1, 1, 0.5)
  local aggressionCoef = linearScale(M.smoothedValues.drivingAggression, 0.5, 1, 0.1, 1)
@/lua/vehicle/controller/sound/AVAS.lua

  local speedCoef = linearScale(speed, 0, maxSpeed, 0, 1)
  obj:setVolumePitchCT(forwardSound, warningVolume, 1, speedCoef, 0)
@/lua/vehicle/partCondition.lua
  local wearEndOdometer = paintAgingConstants.wearEndOdometer
  local roughnessIncrease = linearScale(paintOdometer, wearStartOdometer, wearEndOdometer, 0, paintAgingConstants.maxClearcoatRoughnessIncrease)
  local saturationCoef = linearScale(paintOdometer, wearStartOdometer, wearEndOdometer, 1, paintAgingConstants.minSaturationCoef)
  local roughnessIncrease = linearScale(paintOdometer, wearStartOdometer, wearEndOdometer, 0, paintAgingConstants.maxClearcoatRoughnessIncrease)
  local saturationCoef = linearScale(paintOdometer, wearStartOdometer, wearEndOdometer, 1, paintAgingConstants.minSaturationCoef)
  local colorBrightnessIncrease = {}
  local colorBrightnessIncrease = {}
  colorBrightnessIncrease[1] = linearScale(paintOdometer, wearStartOdometer, wearEndOdometer, 0, paintAgingConstants.maxColorBrightnessIncreaseR)
  colorBrightnessIncrease[2] = linearScale(paintOdometer, wearStartOdometer, wearEndOdometer, 0, paintAgingConstants.maxColorBrightnessIncreaseG)
  colorBrightnessIncrease[1] = linearScale(paintOdometer, wearStartOdometer, wearEndOdometer, 0, paintAgingConstants.maxColorBrightnessIncreaseR)
  colorBrightnessIncrease[2] = linearScale(paintOdometer, wearStartOdometer, wearEndOdometer, 0, paintAgingConstants.maxColorBrightnessIncreaseG)
  colorBrightnessIncrease[3] = linearScale(paintOdometer, wearStartOdometer, wearEndOdometer, 0, paintAgingConstants.maxColorBrightnessIncreaseG)
  colorBrightnessIncrease[2] = linearScale(paintOdometer, wearStartOdometer, wearEndOdometer, 0, paintAgingConstants.maxColorBrightnessIncreaseG)
  colorBrightnessIncrease[3] = linearScale(paintOdometer, wearStartOdometer, wearEndOdometer, 0, paintAgingConstants.maxColorBrightnessIncreaseG)
      paint = {
        odometer = linearScale(visualValue, 1, 0, 0, paintAgingConstants.wearEndOdometer),
        originalPaints = deepcopy(v.config.paints)
    local paintOdometer = (paintOdometerAbsoluteBaseValues[partId] or 0) + max(extensions.odometer.getRelativeRecording() - (paintOdometerRelativeStartingValues[partId] or 0), 0)
    paintCondition = {odometer = paintOdometer, visualValue = linearScale(paintOdometer, paintAgingConstants.wearStartOdometer, paintAgingConstants.wearEndOdometer, 1, 0), originalPaints = deepcopy(partPaints[partId])}
    canProvidePaintCondition = true
@/lua/vehicle/powertrain/rangeBox.lua
local function applyDeformGroupDamage(device, damageAmount)
  device.damageFrictionCoef = device.damageFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 0.1)
end
local function setPartCondition(device, subSystem, odometer, integrity, visual)
  device.wearFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 2)
  local integrityState = integrity
    local integrityValue = integrity
    integrityState = {damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 50), isBroken = false}
  end
  local integrityState = {damageFrictionCoef = device.damageFrictionCoef, isBroken = device.isBroken}
  local integrityValue = linearScale(device.damageFrictionCoef, 1, 50, 1, 0)
  if device.isBroken then
@/lua/vehicle/powertrain/cvtGearbox.lua
local function applyDeformGroupDamage(device, damageAmount)
  device.damageFrictionCoef = device.damageFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 0.1)
end
local function setPartCondition(device, subSystem, odometer, integrity, visual)
  device.wearFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 2)
  local integrityState = integrity
    local integrityValue = integrity
    integrityState = {damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 50), isBroken = false}
  end
  local integrityState = {damageFrictionCoef = device.damageFrictionCoef, isBroken = device.isBroken}
  local integrityValue = linearScale(device.damageFrictionCoef, 1, 50, 1, 0)
  if device.isBroken then
@/lua/vehicle/powertrain/splitShaft.lua
local function applyDeformGroupDamage(device, damageAmount)
  device.damageFrictionCoef = device.damageFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 0.1)
  device.damageLockTorqueCoef = device.damageLockTorqueCoef + linearScale(damageAmount, 0, 0.01, 0, 0.05)
  device.damageFrictionCoef = device.damageFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 0.1)
  device.damageLockTorqueCoef = device.damageLockTorqueCoef + linearScale(damageAmount, 0, 0.01, 0, 0.05)
  device.damageViscousTorqueCoef = device.damageViscousTorqueCoef + linearScale(damageAmount, 0, 0.01, 0, 0.05)
  device.damageLockTorqueCoef = device.damageLockTorqueCoef + linearScale(damageAmount, 0, 0.01, 0, 0.05)
  device.damageViscousTorqueCoef = device.damageViscousTorqueCoef + linearScale(damageAmount, 0, 0.01, 0, 0.05)
end
local function setPartCondition(device, subSystem, odometer, integrity, visual)
  device.wearFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 2)
  device.wearLockTorqueCoef = linearScale(odometer, 30000000, 500000000, 1, 0.7)
  device.wearFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 2)
  device.wearLockTorqueCoef = linearScale(odometer, 30000000, 500000000, 1, 0.7)
  device.wearViscousTorqueCoef = linearScale(odometer, 30000000, 500000000, 1, 0.7)
  device.wearLockTorqueCoef = linearScale(odometer, 30000000, 500000000, 1, 0.7)
  device.wearViscousTorqueCoef = linearScale(odometer, 30000000, 500000000, 1, 0.7)
  local integrityState = integrity
    integrityState = {
      damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 10),
      damageLockTorqueCoef = linearScale(integrityValue, 1, 0, 1, 0.1),
      damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 10),
      damageLockTorqueCoef = linearScale(integrityValue, 1, 0, 1, 0.1),
      damageViscousTorqueCoef = linearScale(integrityValue, 1, 0, 1, 0.1)
      damageLockTorqueCoef = linearScale(integrityValue, 1, 0, 1, 0.1),
      damageViscousTorqueCoef = linearScale(integrityValue, 1, 0, 1, 0.1)
    }
  }
  local frictionIntegrityValue = linearScale(device.damageFrictionCoef, 1, 10, 1, 0)
  local lockTorqueIntegrityValue = linearScale(device.damageFrictionCoef, 1, 0.1, 1, 0)
  local frictionIntegrityValue = linearScale(device.damageFrictionCoef, 1, 10, 1, 0)
  local lockTorqueIntegrityValue = linearScale(device.damageFrictionCoef, 1, 0.1, 1, 0)
  local viscousTorqueIntegrityValue = linearScale(device.damageFrictionCoef, 1, 0.1, 1, 0)
  local lockTorqueIntegrityValue = linearScale(device.damageFrictionCoef, 1, 0.1, 1, 0)
  local viscousTorqueIntegrityValue = linearScale(device.damageFrictionCoef, 1, 0.1, 1, 0)
  local integrityValue = min(frictionIntegrityValue, lockTorqueIntegrityValue, viscousTorqueIntegrityValue)
@/lua/vehicle/powertrain/shaft.lua
local function applyDeformGroupDamage(device, damageAmount)
  device.damageFrictionCoef = device.damageFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 0.1)
end
local function setPartCondition(device, subSystem, odometer, integrity, visual)
  device.wearFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 1.5)
  local integrityState = integrity
    local integrityValue = integrity
    integrityState = {damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 50), isBroken = false}
  end
  local integrityState = {damageFrictionCoef = device.damageFrictionCoef, isBroken = device.isBroken}
  local integrityValue = linearScale(device.damageFrictionCoef, 1, 50, 1, 0)
  if device.isBroken then
@/lua/vehicle/powertrain/electricWinch.lua
local function applyDeformGroupDamage(device, damageAmount)
  device.damageFrictionCoef = device.damageFrictionCoef + linearScale(damageAmount, 0, 0.01, 0, 0.1)
end
local function setPartCondition(device, subSystem, odometer, integrity, visual)
  device.wearFrictionCoef = linearScale(odometer, 30000000, 1000000000, 1, 2)
  local integrityState = integrity
    local integrityValue = integrity
    integrityState = {damageFrictionCoef = linearScale(integrityValue, 1, 0, 1, 50), isBroken = false}
  end
  local integrityState = {damageFrictionCoef = device.damageFrictionCoef, isBroken = device.isBroken}
  local integrityValue = linearScale(device.damageFrictionCoef, 1, 50, 1, 0)
  if device.isBroken then
@/lua/vehicle/props.lua
  if prop.scaleLight and prop.lightBrightness and prop.flareScale and prop.lightColor then
    local lightBrightness = linearScale(val, prop.scaleLightBrightnessMinInput, prop.scaleLightBrightnessMaxInput, 0, prop.lightBrightness)
    local flareScale = linearScale(val, prop.scaleLightFlareScaleMinInput, prop.scaleLightFlareScaleMaxInput, 0, prop.flareScale)
    local lightBrightness = linearScale(val, prop.scaleLightBrightnessMinInput, prop.scaleLightBrightnessMaxInput, 0, prop.lightBrightness)
    local flareScale = linearScale(val, prop.scaleLightFlareScaleMinInput, prop.scaleLightFlareScaleMaxInput, 0, prop.flareScale)
    local lightColor = color(linearScale(val, 1, 0, prop.lightColor.r, prop.lightColor.r - prop.scaleLightColorOffsetRed), linearScale(val, 1, 0, prop.lightColor.g, prop.lightColor.g - prop.scaleLightColorOffsetGreen), linearScale(val, 1, 0, prop.lightColor.b, prop.lightColor.b - prop.scaleLightColorOffsetBlue), prop.lightColor.a)
    local flareScale = linearScale(val, prop.scaleLightFlareScaleMinInput, prop.scaleLightFlareScaleMaxInput, 0, prop.flareScale)
    local lightColor = color(linearScale(val, 1, 0, prop.lightColor.r, prop.lightColor.r - prop.scaleLightColorOffsetRed), linearScale(val, 1, 0, prop.lightColor.g, prop.lightColor.g - prop.scaleLightColorOffsetGreen), linearScale(val, 1, 0, prop.lightColor.b, prop.lightColor.b - prop.scaleLightColorOffsetBlue), prop.lightColor.a)
    obj:setPropLight(prop.pid, lightBrightness, flareScale, lightColor)
    local flareScale = linearScale(val, prop.scaleLightFlareScaleMinInput, prop.scaleLightFlareScaleMaxInput, 0, prop.flareScale)
    local lightColor = color(linearScale(val, 1, 0, prop.lightColor.r, prop.lightColor.r - prop.scaleLightColorOffsetRed), linearScale(val, 1, 0, prop.lightColor.g, prop.lightColor.g - prop.scaleLightColorOffsetGreen), linearScale(val, 1, 0, prop.lightColor.b, prop.lightColor.b - prop.scaleLightColorOffsetBlue), prop.lightColor.a)
    obj:setPropLight(prop.pid, lightBrightness, flareScale, lightColor)
    local flareScale = linearScale(val, prop.scaleLightFlareScaleMinInput, prop.scaleLightFlareScaleMaxInput, 0, prop.flareScale)
    local lightColor = color(linearScale(val, 1, 0, prop.lightColor.r, prop.lightColor.r - prop.scaleLightColorOffsetRed), linearScale(val, 1, 0, prop.lightColor.g, prop.lightColor.g - prop.scaleLightColorOffsetGreen), linearScale(val, 1, 0, prop.lightColor.b, prop.lightColor.b - prop.scaleLightColorOffsetBlue), prop.lightColor.a)
    obj:setPropLight(prop.pid, lightBrightness, flareScale, lightColor)
@/lua/vehicle/controller/braking/hydraulicPumpBrake.lua
  --brake pedal and hill assist are additive, but do not exceed normal brake torque if combined
  brakeR = clamp(brakeR + linearScale(throttleAdjustedHillAssistCoef, 0, 1, 0, 0.8), 0, 1)
@/lua/ge/extensions/career/modules/vehiclePerformance.lua
  local vehVelocity = getObjectByID(vehId):getVelocity():length()
  local fov = linearScale(vehVelocity, 2, maxVelocity, 20, 65)
  core_camera.setFOV(vehId, fov)