--
-- hydroStat
-- Specialization for hydro stat with speeder and throttle handle on steerables
--
-- @author  Knagsted
-- @date  16/07/10
--

-- Do not edit without my permission
--

hydroStat = {};

function hydroStat.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Motorized, specializations);
end;

function hydroStat:load(xmlFile)
	self.hydroStatEnabled = SpecializationUtil.callSpecializationsFunction("hydroStatEnabled");
	self.stdGearboxEnabled = SpecializationUtil.callSpecializationsFunction("stdGearboxEnabled");
	self.gearleaverAnimation = SpecializationUtil.callSpecializationsFunction("gearleaverAnimation");
	
	self.clutchAnimation = SpecializationUtil.callSpecializationsFunction("clutchAnimation");
	self.brakeAnimation = SpecializationUtil.callSpecializationsFunction("brakeAnimation");
	self.speederAnimation = SpecializationUtil.callSpecializationsFunction("speederAnimation");
	self.updateWheelsPhysics = SpecializationUtil.callSpecializationsFunction("updateWheelsPhysics");
	
	self.backupMinRpmManual = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.motor#minRpm"), 1000);
	self.handThrottleEnabled = false;
	
	-- Backup maxRpm
    local motorMaxRpmStr = getXMLString(xmlFile, "vehicle.motor#maxRpm");
    local motorMaxRpm1, motorMaxRpm2, motorMaxRpm3 = Utils.getVectorFromString(motorMaxRpmStr);
    motorMaxRpm1 = Utils.getNoNil(motorMaxRpm1, 650);
    motorMaxRpm2 = Utils.getNoNil(motorMaxRpm2, 980);
    motorMaxRpm3 = Utils.getNoNil(motorMaxRpm3, 2400);
    local motorMaxRpm = {motorMaxRpm1, motorMaxRpm2, motorMaxRpm3};
    self.motorMaxRpmLimit = motorMaxRpm;
	
	--ExhaustParticles
	self.extraExhaustParticleSystems = {};
    local exhaustParticleSystemCount = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.extraExhaustParticleSystems#count"), 0);
    for i=1, exhaustParticleSystemCount do
        local namei = string.format("vehicle.extraExhaustParticleSystems.extraExhaustParticleSystem%d", i);
        Utils.loadParticleSystem(xmlFile, self.extraExhaustParticleSystems, namei, self.components, false, nil, self.baseDirectory)
    end;
	
	--animation parts
	self.gearLeaver = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.gearLeaver#index"));
	self.throttleLeaver = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.throttleLeaver#index"));
	self.speeder = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.speeder#index"));
	self.clutch = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.clutch#index"));
	self.brake = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.brake#index"));
	self.hydroStatHandle = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.hydroStatHandle#index"));
	
	--Sounds
	GearShiftSoundFile = Utils.getFilename("Sons/gearShift.wav", self.baseDirectory);
    self.GearShiftSoundId = createSample("GearShiftSound");
    loadSample(self.GearShiftSoundId, GearShiftSoundFile, false);
    self.GearShiftPlaying = false;
	
	self.gearShiftSound = false;
	
	HydroSoundFile = Utils.getFilename("Sons/Hydrostatique2.ogg", self.baseDirectory);
    self.HydroSoundId = createSample("HydroSound");
    loadSample(self.HydroSoundId, HydroSoundFile, false);
    self.HydroPlaying = false;
	
	self.hydroSound = false;
	
    -- Percentage of full throttle
    self.throttlePercentage = self.backupMinRpmManual/self.motorMaxRpmLimit[3];
	self.currentHydroLevel = 0;
	self.noOfForwardHydroLevels = 100;
	self.noOfBackwardHydroLevels = 100;
	self.currentGear = 1;
	self.noOfGears = 3;
	self.rewUpTime = 1500;
	self.rewUpTimeOffSet = 0;
	self.orgMotorSoundRunPitchMax = self.motorSoundRunPitchMax;
	self.orgMotorSoundPitchMax = self.motorSoundPitchMax;
	self.myLastAcceleration = 0;
	self.lastHydroLevel = 0;
	self.lastGear = 0;
	self.automaticGearBoxMode = 0;
	self.enabledHydrostaticGearBox = true;
	self.backupBrakeForce = self.motor.brakeForce;
	self.powerShiftMinRpm = 850;
	self.rpmMeterValue = 0;
	self.handbrakeOn = true;
	self.hudEnabled = true;
	self.HUDpath = Utils.getFilename("Scripts/MF8140.png", self.baseDirectory);
	self.HUDWidth = 0.100;
    self.HUDHeight = 0.22;
	self.HUDPoxX = 0.90;
    self.HUDPoxY = 0.317
    self.HUDOverlay = Overlay:new("HUD", self.HUDpath, self.HUDPoxX, self.HUDPoxY, self.HUDWidth, self.HUDHeight);
	self.lastHydroLevelShiftMode = 0;
	self.motor.backwardBackupGearRatio = self.motor.backwardGearRatio;
	self.motor.forwardBackupGearRatios = self.motor.forwardGearRatios;
	self.cameraCount  = 2;	
	self.intCameraIndex = 1;
	self.newAcceleration = 0;
	self.wheelRpm = 0;
end;

function hydroStat:delete()
	Utils.deleteParticleSystem(self.extraExhaustParticleSystems);
	if self.GearShiftPlaying ~= nil then
		stopSample(self.GearShiftSoundId);
	end;
	if self.HydroSoundId ~= nil then
        stopSample(self.HydroSoundId);
    end;
end;

function hydroStat:mouseEvent(posX, posY, isDown, isUp, button)
end;

function hydroStat:keyEvent(unicode, sym, modifier, isDown)
end;

function hydroStat:updateTick(dt)
	 if self.isClient then
		if self.enabledHydrostaticGearBox --[[and not self.isAIThreshing and not self.isAutopilotActivated]] then
			for k, wheel in pairs(self.wheels) do
				wheel.hasGroundContact = false;
			end;
			
			local brake = false;
			if self.doBrake or self.handbrakeOn then
				brake = true;
			end;
			
			if self.firstTimeRun then
				self:updateWheelsPhysics(self, dt, self.lastSpeed, self.newAcceleration, brake, 1);
			end;
		end;
	end;
end;

function hydroStat:update(dt)
    if self.isEntered then
	    -- Handle input
        if self:getIsActiveForInput() then
		    -- Raise and lower the throttle percentage
            if InputBinding.isPressed(InputBinding.MORERPM) and self.throttlePercentage < 1 then
		        self.throttlePercentage = self.throttlePercentage + 0.0003 * dt; 
		    	self.handThrottleEnabled = true;
		    elseif InputBinding.isPressed(InputBinding.LESSRPM) and self.throttlePercentage > self.backupMinRpmManual/self.motorMaxRpmLimit[3] then 
		        self.throttlePercentage = self.throttlePercentage - 0.0003 * dt; 
			    self.handThrottleEnabled = true;
	        end;
		
	    	-- Disable hand throttle
		    if InputBinding.hasEvent(InputBinding.RESETRPM) then
		        self.handThrottleEnabled = false;
				self.motor.minRpm = self.backupMinRpmManual;
				self.throttlePercentage = self.backupMinRpmManual/self.motorMaxRpmLimit[3];
		    end;
			
			if InputBinding.isPressed(InputBinding.UP) then
				if not self.automaticGearbox then
					self.currentHydroLevel = self.currentHydroLevel + 0.1 * dt;
					if self.currentHydroLevel >= self.noOfForwardHydroLevels then
						self.currentHydroLevel = self.noOfForwardHydroLevels;
					end;
				else
					self.automaticGearBoxMode = self.automaticGearBoxMode + 1;
					if self.automaticGearBoxMode > 1 then
						self.automaticGearBoxMode = 1;
					end;
				end;
		    end;
			
			if InputBinding.isPressed(InputBinding.DOWN) then
				if not self.automaticGearbox then
					self.currentHydroLevel = self.currentHydroLevel - 0.1 * dt;
					if self.currentHydroLevel <= -self.noOfBackwardHydroLevels then
						self.currentHydroLevel = -self.noOfBackwardHydroLevels;
					end;
				else
					self.automaticGearBoxMode = self.automaticGearBoxMode - 1;
					if self.automaticGearBoxMode < -1 then
						self.automaticGearBoxMode = -1;
					end;
				end;
		    end;
			
			if InputBinding.hasEvent(InputBinding.GEARUP) then
				self.currentGear = self.currentGear + 1;
				if self.currentGear > self.noOfGears then
					self.currentGear = self.noOfGears;
				end;
		    end;
			
			if InputBinding.hasEvent(InputBinding.GEARDOWN) then
				self.currentGear = self.currentGear - 1;
				if self.currentGear < 1 then
					self.currentGear = 1;
				end;
		    end;
			
			if InputBinding.hasEvent(InputBinding.NEUTRAL) then
				self.currentHydroLevel = 0;
		    end;
			
			if InputBinding.hasEvent(InputBinding.SWITCHGEARBOXTYPE) then
				self.automaticGearbox = not self.automaticGearbox;
		    end;
			
			if InputBinding.hasEvent(InputBinding.DISABLEHYDROSTATICGB) then
				if not self.isAITractorActivated and not self.isAutopilotActivated then
					self.enabledHydrostaticGearBox = not self.enabledHydrostaticGearBox;
				end;
				
				if self.enabledHydrostaticGearBox then
					self.motor.speedLevel = 3;
				else
					self.motor.speedLevel = 0;
				end;
		    end;
			
			if InputBinding.hasEvent(InputBinding.HANDBRAKE) then
				self.handbrakeOn = not self.handbrakeOn;
		    end;
			
			if InputBinding.hasEvent(InputBinding.MAGNUMHUD) then
				self.hudEnabled = not self.hudEnabled;
		    end;
        end;
	end;
	
	if self.currentHydroLevel ~= nil then
		self.hydroSound = true;
	else
		self.hydroSound = false;
	end;
	
	if self.isEntered and self.isMotorStarted and self.playMotorSoundTime <= self.time then
		if self.hydroSound and self:getIsActiveForSound() then
			if not self.HydroPlaying then
				playSample(self.HydroSoundId, 0, 1, 0);
				self.HydroPlaying = true;
			end;
		else
			if self.HydroPlaying then
				stopSample(self.HydroSoundId);
				self.HydroPlaying = false;
			end;
		end;
	end;
	
	--Do not support speedlevel4
	if self.motor.speedLevel == 4 then
		self.motor.speedLevel = 3;
	end;
	--Do powershift gearbox
	if self.enabledHydrostaticGearBox --[[and not self.isAIThreshing and not self.isAutopilotActivated]] then
		self.motor.speedLevel = 0;
			
		self.motor.minRpm = self.backupMinRpmManual;
		self:hydroStatEnabled(dt);
	else
		self:stdGearboxEnabled(dt);
	end;

end;

function hydroStat:stopMotor()
    self.motor.minRpm = self.backupMinRpmManual;
	self.myLastAcceleration = 0;
	if self.HydroPlaying then
		stopSample(self.HydroSoundId);
		self.HydroPlaying = false;
	end;
end;
	
function hydroStat:onLeave()
    self.motor.minRpm = self.backupMinRpmManual;
	if self.HydroPlaying then
		stopSample(self.HydroSoundId);
		self.HydroPlaying = false;
	end;
end;

function hydroStat:onEnter()
	--self.currentCameraIndex = 1;
end;

function hydroStat:startMotor()

end;

function hydroStat:draw()
	if not self.isAITractorActivated and not self.isAutopilotActivated then
		if self.isMotorStarted and not self.enabledHydrostaticGearBox then
			g_currentMission:addExtraPrintText(string.format("Touche %s: Reactive hydroStat transmision", InputBinding.getKeyNamesOfDigitalAction(InputBinding.DISABLEHYDROSTATICGB)));
		else
			g_currentMission:addExtraPrintText(string.format("Touche %s: Desactive hydroStat transmision", InputBinding.getKeyNamesOfDigitalAction(InputBinding.DISABLEHYDROSTATICGB)));
		end;
	end;
	if self.hudEnabled then
		self.HUDOverlay:render();
		setTextBold(true);
		setTextColor(0, 0, 0, 1.0);
			
		if self.isMotorStarted then
			if self.enabledHydrostaticGearBox --[[and not self.isAIThreshing and not self.isAutopilotActivated]] then
				renderText(0.909, 0.425, 0.0250, string.format("%d ",self.rpmMeterValue).."rpm");
				if self.motor.speedLevel == 0 or self.motor.speedLevel == 3 then
					renderText(0.907, 0.455, 0.055,string.format("%d ",self.currentGear));
					--local hydro = math.floor((self.hydro+2.5)/5)*5;
					renderText(0.932, 0.465, 0.0250, string.format("%d ",self.currentHydroLevel).."%");
				end;
			else
				if self.motor.speedLevel ~= 0 then
					renderText(0.909, 0.425, 0.0250, string.format("%d ",self.motor.maxRpm[self.motor.speedLevel]).."rpm");
				else
					renderText(0.909, 0.425, 0.0250, string.format("%d ",self.motor.maxRpm[3]).."rpm");
				end;
			end;
		end;

		if self.handbrakeOn then
			setTextBold(true);
			setTextColor(1, 0, 0, 1.0);
			renderText(0.909, 0.18, 0.020, string.format("P-Brake"));
		end;
	end;
end;

function hydroStat:hydroStatEnabled(dt)	
	if self.isEntered then
		self.gearRatio = 0;
		local ratio = 0;
		
		
		if self.currentGear == 3 then
			if self.currentHydroLevel >= 0  then
				self.gearRatio = self.currentHydroLevel/90;
				ratio = 31.5 - self.currentHydroLevel/8;
			else
				self.gearRatio = self.currentHydroLevel/90;
				ratio = -31.5 - self.currentHydroLevel/8;
			end;
		elseif self.currentGear == 2 then
			if self.currentHydroLevel >= 0  then
				self.gearRatio = self.currentHydroLevel/90;
				ratio = 13-self.currentHydroLevel/15;
			else
				self.gearRatio = self.currentHydroLevel/90;
				ratio = -13 - self.currentHydroLevel/15;
			end;
		elseif self.currentGear == 1 then
			if self.currentHydroLevel >= 0  then
				self.gearRatio = self.currentHydroLevel/90;
				ratio = 8.5 - self.currentHydroLevel/20;
			else
				self.gearRatio = self.currentHydroLevel/90;
				ratio = -8.5 - self.currentHydroLevel/20;
			end;
		end;
		
		self.motor.backwardGearRatio = -1*ratio;

		self.motor.forwardGearRatios = {ratio/2,ratio/1.5,ratio};
				
		local acceleration = 0;
		local newAcceleration = 0;
		
		acceleration = -InputBinding.getAnalogInputAxis(InputBinding.AXIS_MOVE_FORWARD_VEHICLE);
		if InputBinding.isAxisZero(acceleration) then
			acceleration = -InputBinding.getDigitalInputAxis(InputBinding.AXIS_MOVE_FORWARD_VEHICLE);
		end;
		
		--There is no speeder in a combine. Only throttle
		if acceleration > 0 then
			acceleration = 0;
		end;
		
		self.motor.speedLevel = 0;
		

		newAcceleration = acceleration;
		if acceleration <= 0 and self.throttlePercentage < self.powerShiftMinRpm/self.motorMaxRpmLimit[3] then
			newAcceleration = 0;
		elseif self.throttlePercentage > self.powerShiftMinRpm/self.motorMaxRpmLimit[3] and acceleration <= 0 then
			newAcceleration = self.throttlePercentage;
		end;
		
		if self.throttleLeaver ~= nil then
			setRotation(self.throttleLeaver, Utils.degToRad(self.throttlePercentage * 35),0,0);
		end;
		
		if self.isEntered then
			if 	self.hydroStatHandle ~= nil then
			
				local xRotation = self.currentHydroLevel * 0.18;
				--local direction = self.movingDirection;
				
				if self.currentHydroLevel > 0 then
					setRotation(self.hydroStatHandle, Utils.degToRad(xRotation), 0 ,Utils.degToRad(-4));
				elseif self.currentHydroLevel < 0 then
					setRotation(self.hydroStatHandle, Utils.degToRad(xRotation), 0 ,Utils.degToRad(4));
				else
					setRotation(self.hydroStatHandle, 0, 0 ,0);
				end;
			end;
		end;
		
		--Pedal animation management for pedals
		if InputBinding.getAnalogInputAxis(InputBinding.AXIS_MOVE_FORWARD_VEHICLE) ~= 0 then
			--user has a speeder pedal
			self:speederAnimation(dt, acceleration, newAcceleration);
		else
			--user is using buttons
			self:speederAnimation(dt, newAcceleration, newAcceleration);
		end;
		self:brakeAnimation(dt, acceleration);
		self:clutchAnimation(dt, acceleration);

		-- Slow rev up and down	
		if math.floor(newAcceleration*100) >  math.floor(self.myLastAcceleration*100) and self.currentHydroLevel == 0 then
			newAcceleration = self.myLastAcceleration + 0.0003 * dt;
			self.myLastAcceleration = newAcceleration;
		elseif math.floor(newAcceleration*100) <  math.floor(self.myLastAcceleration*100) and self.currentHydroLevel == 0 then
			newAcceleration = self.myLastAcceleration - 0.0003 * dt; 
			self.myLastAcceleration = newAcceleration;
		elseif math.floor(newAcceleration*100) >  math.floor(self.myLastAcceleration*100) then
			newAcceleration = self.myLastAcceleration + (0.0003 * dt - (self.gearRatio/400));
			--newAcceleration = self.myLastAcceleration + 0.0012 * dt;
			self.myLastAcceleration = newAcceleration;
		elseif math.floor(newAcceleration*100) <  math.floor(self.myLastAcceleration*100) then
			newAcceleration = self.myLastAcceleration - (0.0003 * dt - (self.gearRatio/400)); 
			--newAcceleration = self.myLastAcceleration - 0.0010 * dt;
			self.myLastAcceleration = newAcceleration;
		end;
		
		if newAcceleration < acceleration and acceleration > 0 and self.isMotorStarted then
			self.showExtraParticles = true;
		else
			self.showExtraParticles = false;
		end;
		
		-- Always have acceleration when i gear like on a real tractor;
		if newAcceleration <= self.powerShiftMinRpm/self.motorMaxRpmLimit[3] then
			newAcceleration = self.powerShiftMinRpm/self.motorMaxRpmLimit[3];
		end;
		
		--Extra smoke particles
		Utils.setEmittingState(self.extraExhaustParticleSystems, self.showExtraParticles);
		
		local mySpeed = self.lastSpeed*3600;
		
		-- Acceleration adjustment when gearing up or down and gearshift modes
		if 	self.lastGear < self.currentGear and self.currentHydroLevel ~= 0 then 
			if mySpeed > 2 then
				if acceleration >= 0 and newAcceleration > 0 then
					self.myLastAcceleration = self.myLastAcceleration - 0.4;
					if self.myLastAcceleration < 0.4 then
						self.myLastAcceleration = 0.4;
					end;
				end;
			end;
		elseif self.lastGear > self.currentGear and self.currentHydroLevel > 0 then 
			if mySpeed > 2 then
				if acceleration >= 0 and newAcceleration > 0 then
					self.myLastAcceleration = self.myLastAcceleration + 0.3;
					if self.myLastAcceleration > 1.3 then
						self.myLastAcceleration = 1.3;
					end;
				end;
			end;
		end;
		
		if self.myLastAcceleration < 0.1 then
			self.myLastAcceleration = 0.1;
		end;
		
		--RPM meter value
		self.rpmMeterValue = newAcceleration * self.motorMaxRpmLimit[3];
				
		--Throttle Sound	
		local roundPerSecond = 0;
		
		if self.myLastAcceleration > 0 then
			if acceleration >= 0 and self.currentHydroLevel > 0 then
				roundPerSecond = self.myLastAcceleration * 32 - (self.currentHydroLevel * self.currentGear * 0.03);
			elseif acceleration >= 0 and self.currentHydroLevel < 0 then
				roundPerSecond = self.myLastAcceleration * 32 + (self.currentHydroLevel * self.currentGear * 0.03);
			else
				roundPerSecond = self.myLastAcceleration * 32;
			end;
			if roundPerSecond < 0 then
				roundPerSecond = 0;
			end;
		end;

		if table.getn(self.wheels) > 0 then
			if self.motorSound ~= nil then
				 setSamplePitch(self.motorSound, math.min(self.motorSoundPitchOffset + self.motorSoundPitchScale*math.abs(roundPerSecond), self.motorSoundPitchMax));

				if self.motorSoundRun ~= nil then
					setSamplePitch(self.motorSoundRun, math.min(self.motorSoundRunPitchOffset + self.motorSoundRunPitchScale*math.abs(roundPerSecond), self.motorSoundRunPitchMax));
				end;
				
				--adjust sound if operator is inside cab
				if self.camIndex == self.intCameraIndex then
					setSampleVolume(self.motorSound, self.motorSoundVolume/7);
				else
					setSampleVolume(self.motorSound, self.motorSoundVolume);
				end;
			end;
			
			if self.motorStartSound ~= nil then
				--adjust sound if operator is inside cab
				if self.camIndex == self.intCameraIndex then
					setSampleVolume(self.motorStartSound, self.motorStartSoundVolume/4);
				else
					setSampleVolume(self.motorStartSound, self.motorStartSoundVolume);
				end;
			end;
			
			if self.motorStopSound ~= nil then
				--adjust sound if operator is inside cab
				if self.camIndex == self.intCameraIndex then
					setSampleVolume(self.motorStopSound, 1/4);
				else
					setSampleVolume(self.motorStopSound, 1);
				end;
			end;
			
			local maxRpm  = self.motor.maxRpm[3];
			if self.motorSoundRun ~= nil then

				local rpmVolume = 1;
				
				if newAcceleration ~= 0 then
					rpmVolume = Utils.clamp(math.abs(roundPerSecond*60)/((maxRpm - self.motor.minRpm)), 0.0, 1.0);
				else
					rpmVolume = Utils.clamp(math.abs(roundPerSecond*60)/((maxRpm - self.motor.minRpm)*2), 0.0, 1.0);
				end;
				
				--adjust sound if operator is inside cab
				if self.camIndex == self.intCameraIndex then
					setSampleVolume(self.motorSoundRun, rpmVolume/5);
				else
					setSampleVolume(self.motorSoundRun, rpmVolume);
				end;
			end;

			if self.HydroSoundId ~= nil then
				local alpha = 0.9;
				local roundPerMinute = self.lastRoundPerMinute*alpha + (1-alpha)*(maxRpm-self.motor.minRpm) * math.abs(ratio) * (1/30);
				self.lastRoundPerMinute = roundPerMinute;
				local roundPerSecond = roundPerMinute / 60;
				setSamplePitch(self.HydroSoundId, math.min(1 + 0.03*math.abs(roundPerSecond), 3));
				
				--adjust sound if operator is inside cab
				if self.camIndex == self.intCameraIndex then
					setSampleVolume(self.HydroSoundId, 1/2);
				else
					setSampleVolume(self.HydroSoundId, 1);
				end;
			end;
			
			--[[if self.threshingSound ~= nil then
				if self.camIndex == self.intCameraIndex then
					setSampleVolume(self.threshingSound, 1/3);
				else
					setSampleVolume(self.threshingSound, 2);
				end;
				if self.reelSpeedValue ~= nil then
					setSamplePitch(self.threshingSound, math.min(self.threshingSoundPitchOffset + self.threshingSoundPitchScale*math.abs(self.reelSpeedValue), self.threshingSoundPitchMax));
				end;
			end;
			
			if self.BatteurSoundId ~= nil then
				if self.camIndex == self.intCameraIndex then
					setSampleVolume(self.BatteurSoundId, 1/2);
				else
					setSampleVolume(self.BatteurSoundId, 0.8);
				end;
			end;]]
		end;
		--Throttlesound done
		
		if self.currentHydroLevel > 0 and self.isMotorStarted then
			newAcceleration = (self.gearRatio) * newAcceleration;--((5 + (self.gearRatio))/self.noOfForwardHydroLevels) * newAcceleration;
		elseif self.currentHydroLevel < 0 and self.isMotorStarted then
			newAcceleration = (-self.gearRatio) * newAcceleration;
		else
			newAcceleration = 0;
		end;

		if self.fuelFillLevel == 0 then
			newAcceleration = 0;
		end;
		
		--disable handbrake when we start to move
		if self.handbrakeOn and newAcceleration > 0 then
			self.handbrakeOn = false;
		end;		
			
		if newAcceleration > 1 then
			newAcceleration = 1;
		elseif newAcceleration < -1 then
			newAcceleration = -1;
		end;
		
		self.motor.brakeForce = 6;
		--Handle brake as brake
		if acceleration < 0 then
			self.motor.brakeForce = 10 * -acceleration;
		elseif self.handbrakeOn then
			self.motor.brakeForce = 5;
		elseif newAcceleration > 0 then
			self.motor.brakeForce = 0;
		end;
		
		
		if (self.currentHydroLevel < 0 and self.movingDirection > 0) or (self.currentHydroLevel > 0 and self.movingDirection < 0)then
			self.motor.brakeForce = 6;		
		end;

		self.newAcceleration = newAcceleration;
		
		if acceleration < 0 then
			self.doBrake = true;
		else
			self.doBrake = false;
		end;
		

	--[[elseif not self.isAIThreshing and not self.isAutopilotActivated then
		--Combine is not entered or hired in any way so we sets "parking" brake on her
		self.motor.brakeForce = 6;
		newAcceleration = 0;
		self.newAcceleration = 0;
		self.doBrake = true;]]
	end;
	
	if self.currentGear ~= self.lastGear then
		self:gearleaverAnimation(dt);
		if self:getIsActiveForSound() then
			if not self.GearShiftPlaying then
				playSample(self.GearShiftSoundId, 1, 1, 0);
			end;
		end;
	end;

	self.lastAcceleration = self.newAcceleration;

	self.lastHydroLevel = self.currentHydroLevel;
	self.lastGear = self.currentGear;
end;

function hydroStat:stdGearboxEnabled(dt)
	--dont do powershift gearbox do normal gearbox with handthrottle and RPM limiter
	self.motor.backwardGearRatio = self.motor.backwardBackupGearRatio;
	self.motor.forwardGearRatios = self.motor.forwardBackupGearRatios;
	
	self.motor.brakeForce = self.backupBrakeForce;
			-- Local variables
	local alpha = 1;
	local roundPerMinute = self.lastRoundPerMinute*alpha + (1-alpha)*(self.motor.lastMotorRpm-self.motor.minRpm);
	local rpmDiff = math.abs(roundPerMinute - ((self.motorMaxRpmLimit[3] * 0.9) * self.throttlePercentage));
	
	if self.handThrottleEnabled then
		-- Lower and raise minRpm with a 100 RPM margin
		if roundPerMinute < ((self.motorMaxRpmLimit[3] * self.throttlePercentage) - 50) then
			self.motor.minRpm = self.motor.minRpm - (rpmDiff / 10);
		elseif roundPerMinute > ((self.motorMaxRpmLimit[3] * self.throttlePercentage) + 50) then
			if self.motor.minRpm <= (self.backupMinRpmManual - (rpmDiff/10)) then
				self.motor.minRpm = self.motor.minRpm + (rpmDiff / 10);
			end;
		end;
	end;
	self.rpmMeterValue = self.motor.lastMotorRpm;
	
	if self.isMotorStarted and self:getIsActiveForInput() and self.isEntered then
		if self.motor.speedLevel == 1 or self.motor.speedLevel == 2 then
			if InputBinding.isPressed(InputBinding.ACCELERATE) then
				if self.motor.maxRpm[self.motor.speedLevel] <= (self.motorMaxRpmLimit[3] - 10) then
					self.motor.maxRpm[self.motor.speedLevel] = self.motor.maxRpm[self.motor.speedLevel] + 10;
					self.motor.maxTorques[self.motor.speedLevel] = self.motor.maxTorques[self.motor.speedLevel] + 0.03;
				end;
			elseif InputBinding.isPressed(InputBinding.DECELERATE) then
				if self.motor.maxRpm[self.motor.speedLevel] >= 10 then
					self.motor.maxRpm[self.motor.speedLevel] = self.motor.maxRpm[self.motor.speedLevel] - 10;
					self.motor.maxTorques[self.motor.speedLevel] = self.motor.maxTorques[self.motor.speedLevel] - 0.03;
				end;
			end;
		end;
	end;
	
	-- adjust int sound also when not using special hydrostatic gearbox
	if self.motorSound ~= nil then
		if self.camIndex == self.intCameraIndex then
			setSampleVolume(self.motorSound, self.motorSoundVolume/7);
		else
			setSampleVolume(self.motorSound, self.motorSoundVolume);
		end;
	end;
	
	if self.motorSoundRun ~= nil then			
		if self.camIndex == self.intCameraIndex then
			setSampleVolume(self.motorSoundRun, self.motorSoundRunVolume/5);
		else
			setSampleVolume(self.motorSoundRun, self.motorSoundRunVolume);
		end;
	end;
	
	if self.motorStartSound ~= nil then
		--adjust sound if operator is inside cab
		if self.camIndex == self.intCameraIndex then
			setSampleVolume(self.motorStartSound, self.motorStartSoundVolume/4);
		else
			setSampleVolume(self.motorStartSound, self.motorStartSoundVolume);
		end;
	end;
	
	if self.motorStopSound ~= nil then
		--adjust sound if operator is inside cab
		if self.camIndex == self.intCameraIndex then
			setSampleVolume(self.motorStopSound, 1/4);
		else
			setSampleVolume(self.motorStopSound, 1);
		end;
	end;
	
	--[[if self.threshingSound ~= nil then
		if self.camIndex == self.intCameraIndex then
			setSampleVolume(self.threshingSound, 1/3);
		else
			setSampleVolume(self.threshingSound, 2);
		end;
	end;
	
	if self.BatteurSoundId ~= nil then
		if self.camIndex == self.intCameraIndex then
			setSampleVolume(self.BatteurSoundId, 1/2);
		else
			setSampleVolume(self.BatteurSoundId, 0.8);
		end;
	end;]]
	
	if self.aiMotorSound ~= nil then
		if self.camIndex == self.intCameraIndex and self.isEntered then
			setVisibility(self.aiMotorSound, false);
		elseif self.isAITractorActivated --[[and not self.isAutopilotActivated]] then
			setVisibility(self.aiMotorSound, true);
		end;
	end;
	
	--[[if self.aiThreshingSound ~= nil then
		if self.camIndex == self.intCameraIndex and self.isEntered then
			setVisibility(self.aiThreshingSound, false);
		elseif self.isAITractorActivated and not self.isAutopilotActivated then
			setVisibility(self.aiThreshingSound, true);
		end;
	end;]]
	
	if 	self.hydroStatHandle ~= nil then		
		setRotation(self.hydroStatHandle, 0, 0 ,0);
	end;
end;


function hydroStat:gearleaverAnimation(dt)
	if self.gearLeaver ~= nil then
		if self.currentGear == 1 then
			setRotation(self.gearLeaver, Utils.degToRad(10.72), Utils.degToRad(0), Utils.degToRad(-3.5));
		elseif self.currentGear == 2 then
			setRotation(self.gearLeaver, Utils.degToRad(-10.72), Utils.degToRad(0), Utils.degToRad(-4));
		elseif self.currentGear == 3 then
			setRotation(self.gearLeaver, Utils.degToRad(10.72), Utils.degToRad(0), Utils.degToRad(3.5));
		else
			setRotation(self.gearLeaver, Utils.degToRad(0),0,0);
		end;
	end;
end;

function hydroStat:speederAnimation(dt, acceleration, newAcceleration)
	if self.speeder ~= nil then
		if acceleration > 0 then
			setRotation(self.speeder, Utils.degToRad(25 * math.abs(acceleration)),0,0);
		elseif newAcceleration > 0 then
			setRotation(self.speeder, Utils.degToRad(25 * math.abs(newAcceleration)),0,0);
		else
			setRotation(self.speeder, Utils.degToRad(0),0,0);
		end;
	end;
end;
	
function hydroStat:clutchAnimation(dt, acceleration)
	if self.clutch ~= nil then
		local clutchActive = false;
		if acceleration < 0 then
			clutchActive = true;
		end;
		
		local clutchMax = {};
		clutchMax[1] = Utils.degToRad(0);
		clutchMax[2] = Utils.degToRad(0);
		clutchMax[3] = Utils.degToRad(0);
		local clutchRotationTime = 250;
		
		local clutchMin = {};
		clutchMin[1] = Utils.degToRad(-25);
		clutchMin[2] = Utils.degToRad(0);
		clutchMin[3] = Utils.degToRad(0);
		
		local x, y, z = getRotation(self.clutch);
		local rot = {x,y,z};
		local newRot = Utils.getMovedLimitedValues(rot, clutchMin, clutchMax, 3, clutchRotationTime, dt, clutchActive);
		setRotation(self.clutch, unpack(newRot));
	end;
end;

function hydroStat:brakeAnimation(dt, acceleration)
	if self.brake ~= nil then
		if acceleration < 0 then
			setRotation(self.brake, Utils.degToRad(-25 + (30 * math.abs(acceleration))),0,0);
		else
			setRotation(self.brake, Utils.degToRad(0),0,0);
		end;
	end;
end;

function hydroStat:updateWheelsPhysics(self, dt, currentSpeed, acceleration, brake, requiredDriveMode)
 
    local accelerationPedal = 0;
    local brakePedal = 0;
	
	if brake then
		accelerationPedal = 0;
		brakePedal = 1;
	else
		accelerationPedal = acceleration;
	end;
  
    local numTouching = 4;
    local numNotTouching = 0;
  
    local motorTorque = 0;
    if numTouching > 0 and math.abs(accelerationPedal) > 0.01 then
        local axisTorque, brakePedalMotor = WheelsUtil.computeAxisTorque(self, accelerationPedal);
        if axisTorque ~= 0 then
            motorTorque = axisTorque / (numTouching+numNotTouching); --*0.7);
        else
			if not brake then
				brakePedal = brakePedalMotor;
			end;
        end;
    else
        self.motor:computeMotorRpm(self.wheelRpm, accelerationPedal);
    end;
  
    for k, implement in pairs(self.attachedImplements) do
		if brake then
            implement.object:onBrake();
        else
            implement.object:onReleaseBrake();
        end;
    end;
  
    for k, wheel in pairs(self.wheels) do
        WheelsUtil.updateWheelPhysics(self, wheel, false, motorTorque, brakePedal, requiredDriveMode, dt)
    end;
  
end;
