--
-- powerShift
-- Specialization for power shift with speeder and throttle handle on steerables
--
-- @author  Knagsted
-- @date  15/03/10
--

-- Do not edit without my permission
--

powerShift = {};

function powerShift.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Steerable, specializations);
end;

function powerShift:load(xmlFile)
	self.powerShiftEnabled = SpecializationUtil.callSpecializationsFunction("powerShiftEnabled");
	self.updateWheelsPhysics = SpecializationUtil.callSpecializationsFunction("updateWheelsPhysics");
	--self.updateGearDisplay = SpecializationUtil.callSpecializationsFunction("updateGearDisplay");
	
	self.clutchAnimation = SpecializationUtil.callSpecializationsFunction("clutchAnimation");
	self.brakeAnimation = SpecializationUtil.callSpecializationsFunction("brakeAnimation");
	self.speederAnimation = SpecializationUtil.callSpecializationsFunction("speederAnimation");
	
	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, 800);
    motorMaxRpm2 = Utils.getNoNil(motorMaxRpm2, 1000);
    motorMaxRpm3 = Utils.getNoNil(motorMaxRpm3, 1800);
    local motorMaxRpm = {motorMaxRpm1, motorMaxRpm2, motorMaxRpm3};
    self.motorMaxRpmLimit = motorMaxRpm;
	
	self.orgMaxTorques = self.motor.maxTorques;
	
	--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"));
	
	--Sounds
	GearShiftSoundFile = Utils.getFilename("Sons/gearShift.wav", self.baseDirectory);
    self.GearShiftSoundId = createSample("GearShiftSound");
    loadSample(self.GearShiftSoundId, GearShiftSoundFile, false);
    self.GearShiftPlaying = false;
		
	self.gearShiftSound = false;	

    local powershiftMotorSound = getXMLString(xmlFile, "vehicle.motorSound#file");
    if powershiftMotorSound ~= nil and powershiftMotorSound ~= "" then
        powershiftMotorSound = Utils.getFilename(powershiftMotorSound, self.baseDirectory);
        self.powershiftMotorSound = createSample("powershiftMotorSound");
        loadSample(self.powershiftMotorSound, powershiftMotorSound, false);
        self.powershiftMotorSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.motorSound#pitchOffset"), 0);
        self.powershiftMotorSoundPitchScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.motorSound#pitchScale"), 0.05);
        self.powershiftMotorSoundPitchMax = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.motorSound#pitchMax"), 2.0);
        self.powershiftMotorSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.motorSound#volume"), 1.0);
    end;

    local powershiftMotorSoundRun = getXMLString(xmlFile, "vehicle.motorSoundRun#file");
    if powershiftMotorSoundRun ~= nil and powershiftMotorSoundRun ~= "" then
        powershiftMotorSoundRun = Utils.getFilename(powershiftMotorSoundRun, self.baseDirectory);
        self.powershiftMotorSoundRun = createSample("powershiftMotorSoundRun");
        loadSample(self.powershiftMotorSoundRun, powershiftMotorSoundRun, false);
        self.powershiftMotorSoundRunPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.motorSoundRun#pitchOffset"), 0);
        self.powershiftMotorSoundRunPitchScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.motorSoundRun#pitchScale"), 0.05);
        self.powershiftMotorSoundRunPitchMax = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.motorSoundRun#pitchMax"), 2.0);
        self.powershiftMotorSoundRunVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.motorSoundRun#volume"), 1.0);
    end;
		
    -- Percentage of full throttle
	self.powerShiftMinRpm = 850;
    self.throttlePercentage = self.backupMinRpmManual/self.motorMaxRpmLimit[3];
	self.powerShiftThrottlePercentage = self.powerShiftMinRpm/self.motorMaxRpmLimit[3];
	self.myCurrentGear = 0;
	self.noOfForwardGears = 16;
	self.noOfBackwardGears = 4;
	self.myCurrentGearLevel = 0;
	self.rewUpTime = 1500;
	self.rewUpTimeOffSet = 0;
	self.orgMotorSoundRunPitchMax = self.motorSoundRunPitchMax;
	self.orgMotorSoundPitchMax = self.motorSoundPitchMax;
	self.myLastAcceleration = 0;
	self.myLastGear = 0;
	self.automaticGearBoxMode = 0;
	self.enabledPowershiftGearBox = true;
	self.backupBrakeForce = self.motor.brakeForce;
	self.rpmMeterValue = 0;
	self.handbrakeOn = true;
	self.myLastGearShiftMode = 0;
	self.motor.backwardBackupGearRatio = self.motor.backwardGearRatio;
	self.motor.forwardBackupGearRatios = self.motor.forwardGearRatios;
	self.newAcceleration = 0;
	self.doBrake = false;
	self.SoundInitialized = false;
	self.playMotorSound = false;
	self.myAccelerationOffset = 0;
	self.animationName = "";
	self.hasBeenClutched = true;
	self.lastHandBrake = false;
	self.MF8140 = true;
	self.HUDpath = Utils.getFilename("Scripts/HUD/MF8140.png", self.baseDirectory);
	self.HUDWidth = 0.140;
    self.HUDHeight = 0.150;
	self.HUDPoxX = 0.87;
    self.HUDPoxY = 0.3;
    self.HUDOverlay = Overlay:new("HUD", self.HUDpath, self.HUDPoxX, self.HUDPoxY, self.HUDWidth, self.HUDHeight);
end;

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

    if self.powershiftMotorSound ~= nil then
        delete(self.powershiftMotorSound);
    end;
    if self.powershiftMotorSoundRun ~= nil then
        delete(self.powershiftMotorSoundRun);
    end;
    --[[if self.powershiftMotorStartSound ~= nil then
        delete(self.powershiftMotorStartSound);
    end;
    if self.powershiftMotorStopSound ~= nil then
        delete(self.powershiftMotorStopSound);
    end;]]
end;

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

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

function powerShift:updateTick(dt)
	 if self.isEntered and self.isClient and self.isMotorStarted then
		if self.enabledPowershiftGearBox and not self.isAITractorActivated and not self.isAutopilotActivated then
			for k, wheel in pairs(self.wheels) do
				wheel.hasGroundContact = false;
			end;
			
			local acceleration = self.newAcceleration;
			
			local brake = false;
			if self.doBrake or self.handbrakeOn then
				brake = true;
				acceleration = 0;
			end;
			
			if self.firstTimeRun then
				self:updateWheelsPhysics(self, dt, self.lastSpeed, acceleration, brake, 1);
			end;
		end;
	end;
end;

function powerShift:update(dt)
	--if not self.backupsSet then
		--self.backupForwardGearRatio = self.forwardGearRatios;
		--self.backupBackwardGearRatio = self.backwardGearRatio;
		--self.backupsSet = true;
	--end;
	
    if self.isEntered and self.isMotorStarted and not self.isMouseActive then
	    -- Handle input
        if self:getIsActiveForInput() and not (self.hudTriggered or self.show_hud) then
		    -- Raise and lower the throttle percentage
            if InputBinding.isPressed(InputBinding.MFMORERPM) and self.throttlePercentage < 1 then
		        self.throttlePercentage = self.throttlePercentage + 0.0003 * dt; 
		    	self.handThrottleEnabled = true;
		    elseif InputBinding.isPressed(InputBinding.MFLESSRPM) and self.throttlePercentage > self.backupMinRpmManual/self.motorMaxRpmLimit[3] then 
		        self.throttlePercentage = self.throttlePercentage - 0.0003 * dt; 
			    self.handThrottleEnabled = true;
	        end;
			
			if InputBinding.isPressed(InputBinding.MFMORERPM) and self.powerShiftThrottlePercentage < 1 then
		        self.powerShiftThrottlePercentage = self.powerShiftThrottlePercentage + 0.0002 * dt; 
		    	self.handThrottleEnabled = true;
		    elseif InputBinding.isPressed(InputBinding.MFLESSRPM) and self.powerShiftThrottlePercentage > self.powerShiftMinRpm/self.motorMaxRpmLimit[3] then 
		        self.powerShiftThrottlePercentage = self.powerShiftThrottlePercentage - 0.0002 * dt; 
			    self.handThrottleEnabled = true;
	        end;
			
			if self.powerShiftThrottlePercentage > 1 then
				self.powerShiftThrottlePercentage = 1;
			end;
		
			--renderText(0.5, 0.1, 0.020, string.format(self.throttlePercentage));
			--renderText(0.5, 0.2, 0.020, string.format(self.powerShiftThrottlePercentage));
			
	    	-- Disable hand throttle
		    if InputBinding.hasEvent(InputBinding.MFRESETRPM) then
		        self.handThrottleEnabled = false;
				self.motor.minRpm = self.backupMinRpmManual;
				self.throttlePercentage = self.backupMinRpmManual/self.motorMaxRpmLimit[3];
				self.powerShiftThrottlePercentage = self.powerShiftMinRpm/self.motorMaxRpmLimit[3];
		    end;
								
			local updateGears = false;
			--[[if InputBinding.hasEvent(InputBinding.GEARUP) then
				self.myCurrentGearLevel = self.myCurrentGearLevel + (self.noOfForwardGears/110)
				updateGears = true;
			end;]]
			local previousGearLevel = self.myCurrentGearLevel;
				
			if not updateGears and InputBinding.isPressed(InputBinding.MFJDGEARUP) then
				self.myCurrentGearLevel = self.myCurrentGearLevel + 0.0008 * dt
				updateGears = true;
					
				if not self.hasBeenClutched and self.myLastGear < 0 then
					if self.myCurrentGearLevel > 0 then
						updateGears = false;
						self.myCurrentGearLevel = previousGearLevel;
					end;
				end;
			end;
		if InputBinding.hasEvent(InputBinding.MFHUD) then
			self.MF8140 = not self.MF8140;
		end;	

			--[[if not updateGears and InputBinding.hasEvent(InputBinding.GEARDOWN) then
				self.myCurrentGearLevel = self.myCurrentGearLevel - (self.noOfForwardGears/110)
				updateGears = true;
			end;]]

			if not updateGears and InputBinding.isPressed(InputBinding.MFJDGEARDOWN) then
				self.myCurrentGearLevel = self.myCurrentGearLevel - 0.0008 * dt
				updateGears = true;
				
				if not self.hasBeenClutched and self.myLastGear > 0 then
					if self.myCurrentGearLevel < 0 then
						updateGears = false;
						self.myCurrentGearLevel = previousGearLevel;
					end;
				end;
			end;			
				
			if updateGears then
				if self.myCurrentGearLevel > 0 then
					if self.myCurrentGearLevel > 100 then
						self.myCurrentGearLevel = 100;
					end;
					
					self.myCurrentGear = math.ceil(100/self.noOfForwardGears * self.myCurrentGearLevel);
					if self.myCurrentGear > self.noOfForwardGears then
						self.myCurrentGear = self.noOfForwardGears;
					end;
					
					self.hasBeenClutched = false;
					
				elseif self.myCurrentGearLevel < 0 then
					if self.myCurrentGearLevel < -25 then
						self.myCurrentGearLevel = -25;
					end;
					
					self.myCurrentGear = math.floor(25/self.noOfBackwardGears * self.myCurrentGearLevel);
					if self.myCurrentGear < -self.noOfBackwardGears then
						self.myCurrentGear = -self.noOfBackwardGears;
					end;
					
					self.hasBeenClutched = false;
				else
					self.myCurrentGear = 0;
				end;
		    end;
						
			if InputBinding.hasEvent(InputBinding.MFJDNEUTRAL) then
				self.myCurrentGear = 0;
				self.myCurrentGearLevel = 0;
				self.hasBeenClutched = true;
		    end;
						
			if InputBinding.hasEvent(InputBinding.DISABLEPOWERSHIFTGB) then
				if not self.isAITractorActivated and not self.isAutopilotActivated then
					self.enabledPowershiftGearBox = not self.enabledPowershiftGearBox;
				end;
				
				self.soundSwitched = true;
		    end;
			
			if InputBinding.hasEvent(InputBinding.MFHANDBRAKE) then
				self.handbrakeOn = not self.handbrakeOn;
		    end;
        end;
		
	end;
	
	
	
	--Do not support speedlevel4
	if self.motor.speedLevel == 4 then
		self.motor.speedLevel = 2;
	end;
	
	--renderText(0.5, 0.70, 0.020, string.format("self.lastSpeed " .. "%.3f",self.lastSpeed));
		
	--Do powershift gearbox
	if self.enabledPowershiftGearBox and not self.isAITractorActivated and not self.isAutopilotActivated then
		if self.isEntered then
			self.motor.speedLevel = 0;

			self.motor.minRpm = self.backupMinRpmManual;
			self:powerShiftEnabled(dt);
		end;
	else

	--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.motor.speedLevel ~= 0 then
			--renderText(0.5, 0.50, 0.015, string.format(self.motor.maxTorques[self.motor.speedLevel]));
		--end;
		
		
		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.MFACCELERATE) 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.06;
					end;
				elseif InputBinding.isPressed(InputBinding.MFDECELERATE) 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.06;
					end;
				end;
			end;
		end;
	end;
end;

function powerShift:stopMotor()
    self.motor.minRpm = self.backupMinRpmManual;
	self.myLastAcceleration = 0;
	powerShift.stopSounds(self);
end;
	
function powerShift:onLeave()
    self.motor.minRpm = self.backupMinRpmManual;
	self.myLastAcceleration = 0;
	powerShift.stopSounds(self);

	self.motor.brakeForce = 6;
	newAcceleration = 0;
	self.newAcceleration = 0;
	self.doBrake = true;
end;

function powerShift:stopSounds()
	self.playPowershiftMotorSound = false;
	if self.powershiftMotorSound ~= nil then
        stopSample(self.powershiftMotorSound);
    end;

    if self.powershiftMotorSoundRun ~= nil then
        stopSample(self.powershiftMotorSoundRun);
    end;
end;

function powerShift:startMotor()
end;

function powerShift:draw()
	if not self.isAITractorActivated and not self.isAutopilotActivated then
		if self.isMotorStarted and not self.enabledPowershiftGearBox then
			setTextBold(true);
			setTextColor(1, 0, 0, 1.0);
			renderText(0.85, 0.183, 0.018, string.format("Auto"));
			g_currentMission:addExtraPrintText(string.format("Taste %s: Reactivieren Powershift transmision", InputBinding.getKeyNamesOfDigitalAction(InputBinding.DISABLEPOWERSHIFTGB)));
		else
			g_currentMission:addExtraPrintText(string.format("Taste %s: Deactivieren Powershift transmision", InputBinding.getKeyNamesOfDigitalAction(InputBinding.DISABLEPOWERSHIFTGB)));
			renderText(0.85, 0.183, 0.018, string.format("Manu"));
		end;
	end;
	if 	self.MF8140 and self.isMotorStarted then
		self.HUDOverlay:render();
		setTextBold(true);
		setTextColor(0, 0, 0, 1.0);
		
		if self.enabledPowershiftGearBox and not self.isAITractorActivated and not self.isAutopilotActivated then
			renderText(0.955, 0.355, 0.0180, string.format("%d ",self.rpmMeterValue));
			if self.motor.speedLevel == 0 or self.motor.speedLevel == 3 then
				if self.myCurrentGear < 0 then
					renderText(0.97, 0.4, 0.0180,"R"..string.format(-1 * self.myCurrentGear));
				else
					renderText(0.97, 0.4, 0.0180,string.format("%d ",self.myCurrentGear));
				end;
			end;
		else		
			if self.motor.speedLevel ~= 0 then
				renderText(0.955, 0.355, 0.0180, string.format("%d ",self.motor.maxRpm[self.motor.speedLevel]));
			else
				renderText(0.955, 0.355, 0.0180, string.format("%d ",self.motor.maxRpm[3]));
			end;
		end;
		
		renderText(0.93, 0.305, 0.0180,string.format("%d ",self.lastSpeed * 3600).."km/h");
		
		if self.handbrakeOn then
			setTextBold(true);
			setTextColor(1, 0, 0, 1.0);
			renderText(0.93, 0.183, 0.018, string.format("P-Brake"));
		end;
	end;
end;

function powerShift:powerShiftEnabled(dt)
	if self.isEntered then
	
		self.gearRatio = 0;
		local ratio = 0;
		self.gearRatio = 1;
		if self.myCurrentGear == 1 then
			ratio = 3;
		elseif self.myCurrentGear == 2 then
			ratio = 3.4;
		elseif self.myCurrentGear == 3 then
			ratio =3.8;
		elseif self.myCurrentGear == 4 then
			ratio = 4.2;
		elseif self.myCurrentGear == 5 then
			ratio = 4.6;
		elseif self.myCurrentGear == 6 then
			ratio = 5;
		elseif self.myCurrentGear == 7 then
			ratio = 5.5;
		elseif self.myCurrentGear == 8 then
			ratio = 6;
		elseif self.myCurrentGear == 9 then
			ratio = 6.5;
		elseif self.myCurrentGear == 10 then
			ratio = 7;
		elseif self.myCurrentGear == 11 then
			ratio = 7.5;
		elseif self.myCurrentGear == 12 then
			ratio = 8;
		elseif self.myCurrentGear == 13 then
			ratio = 8.5;
		elseif self.myCurrentGear == 14 then
			ratio = 10;
		elseif self.myCurrentGear == 15 then
			ratio = 13;
		elseif self.myCurrentGear == 16 then
			ratio = 15;
		elseif self.myCurrentGear == -1 then
			ratio = -2;
		elseif self.myCurrentGear == -2 then
			ratio = -4;
		elseif self.myCurrentGear == -3 then
			ratio = -6;
		elseif self.myCurrentGear == -4 then
			ratio = -8;
		end;
		
		
		self.motor.backwardGearRatio = -1 * ratio;
		self.motor.forwardGearRatios = {ratio/2,ratio/1.5,ratio};
				
		local acceleration = 0;
		self.updatedAcceleration = 0;
		local throttleAcceleration = 0;
		
		--renderText(0.5, 0.9, 0.0250,-InputBinding.getDigitalInputAxis(InputBinding.AXIS_FORWARD));
		--renderText(0.5, 0.8, 0.0250, self.playMotorSound);
		--if g_currentMission.allowSteerableMoving then --and not self.playMotorSound then
			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 MFSPEEDER in a combine. Only throttle
			--if acceleration > 0 then
				--acceleration = 0;
			--end;
			
			if acceleration >= 0 then
				--self.motor.speedLevel = 3;
			else
				--self.motor.speedLevel = 0;
			end;
		--end;
		
		self.updatedAcceleration = acceleration + self.myAccelerationOffset;
		
		if acceleration <= 0 and self.powerShiftThrottlePercentage < self.powerShiftMinRpm/self.motorMaxRpmLimit[3] then
			self.updatedAcceleration = 0;
		elseif self.powerShiftThrottlePercentage > self.powerShiftMinRpm/self.motorMaxRpmLimit[3] and acceleration <= 0 then
			self.updatedAcceleration = self.powerShiftThrottlePercentage + self.myAccelerationOffset;
			throttleAcceleration = self.powerShiftThrottlePercentage;
		end;
		
		if self.throttleLeaver ~= nil then
			setRotation(self.throttleLeaver, Utils.degToRad(self.powerShiftThrottlePercentage * 80),0,0);
		end;
		
		--Pedal animation management for pedals
		if InputBinding.getAnalogInputAxis(InputBinding.AXIS_MOVE_FORWARD_VEHICLE) ~= 0 then
			--user has a MFSPEEDER pedal
			self:speederAnimation(dt, acceleration, self.updatedAcceleration);
		else
			--user is using buttons
			self:speederAnimation(dt, self.updatedAcceleration, self.updatedAcceleration);
		end;
		self:brakeAnimation(dt, acceleration);
		self:clutchAnimation(dt, acceleration);

		-- Slow rev up and down	
		if math.floor(self.updatedAcceleration*100) >  math.floor(self.myLastAcceleration*100) and (self.myCurrentGear == 0 or acceleration <= 0) then
			self.updatedAcceleration = self.myLastAcceleration + 0.0005 * dt;
			self.myLastAcceleration = self.updatedAcceleration; --+ self.myAccelerationOffset;
		elseif math.floor(self.updatedAcceleration*100) <  math.floor(self.myLastAcceleration*100) and (self.myCurrentGear == 0 or acceleration <= 0)then
			self.updatedAcceleration = self.myLastAcceleration - 0.0004 * dt; 
			self.myLastAcceleration = self.updatedAcceleration;-- + self.myAccelerationOffset;
		elseif math.floor(self.updatedAcceleration*100) >  math.floor(self.myLastAcceleration*100) then
			self.updatedAcceleration = self.myLastAcceleration + (0.0003 * dt - (ratio/4000));
			self.myLastAcceleration = self.updatedAcceleration;-- + self.myAccelerationOffset;
		elseif math.floor(self.updatedAcceleration*100) <  math.floor(self.myLastAcceleration*100) then
			self.updatedAcceleration = self.myLastAcceleration - (0.0002 * dt - (ratio/4000)); 
			self.myLastAcceleration = self.updatedAcceleration;-- + self.myAccelerationOffset;
		end;
		
		if ((self.updatedAcceleration < acceleration and acceleration > 0) or (self.updatedAcceleration < throttleAcceleration and throttleAcceleration > 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 self.updatedAcceleration <= self.powerShiftMinRpm/self.motorMaxRpmLimit[3] then
			self.updatedAcceleration = 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.myLastGear < self.myCurrentGear and self.myCurrentGear > 0 then 
			if mySpeed > 2 then
				if acceleration >= 0 and self.updatedAcceleration > 0 then
					self.myLastAcceleration = self.myLastAcceleration - 0.2;
					if self.myLastAcceleration < 0.2 then
						self.myLastAcceleration = 0.2;
					end;
				end;
			end;

			if self:getIsActiveForSound() then
				if not self.GearShiftPlaying then
					playSample(self.GearShiftSoundId, 1, 0.5, 0);
				end;
			end;

			self.animationName = "gearUpForward";
			self:playAnimation(self.animationName, 1, nil, true)

		elseif self.myLastGear > self.myCurrentGear and self.myCurrentGear > 0 then 
			if mySpeed > 2 then
				if acceleration >= 0 and self.updatedAcceleration > 0 then
					self.myLastAcceleration = self.myLastAcceleration + 0.1;
					if self.myLastAcceleration > 1.7 then
						self.myLastAcceleration = 1.7;
					end;
				end;
			end;
			
			if self:getIsActiveForSound() then
				if not self.GearShiftPlaying then
					playSample(self.GearShiftSoundId, 1, 0.5, 0);
				end;
			end;
			
			self.animationName = "gearDownForward";
			self:playAnimation(self.animationName, 1, nil, true)
			
		elseif self.myLastGear > 0 and self.myCurrentGear == 0 then
			if not self.GearShiftPlaying then
				playSample(self.GearShiftSoundId, 1, 0.5, 0);
			end;
			
			self.animationName = "gearForwardToNeutral";
			self:playAnimation(self.animationName, 1, nil, true)
			
		elseif self.myLastGear == 0 and self.myCurrentGear < 0 then
			if not self.GearShiftPlaying then
				playSample(self.GearShiftSoundId, 1, 0.5, 0);
			end;
			
			self.animationName = "gearNeutralToReverse";
			self:playAnimation(self.animationName, 1, nil, true)

		elseif 	self.myLastGear < self.myCurrentGear and self.myCurrentGear < 0 then 
			if mySpeed > 2 then
				if acceleration >= 0 and self.updatedAcceleration > 0 then
					self.myLastAcceleration = self.myLastAcceleration + 0.1;
					if self.myLastAcceleration > 1.5 then
						self.myLastAcceleration = 1.5;
					end;
				end;
			end;

			if self:getIsActiveForSound() then
				if not self.GearShiftPlaying then
					playSample(self.GearShiftSoundId, 1, 0.5, 0);
				end;
			end;
			
			self.animationName = "gearDownReverse";
			self:playAnimation(self.animationName, 1, nil, true)
			
		elseif self.myLastGear > self.myCurrentGear and self.myCurrentGear < 0 then 
			if mySpeed > 2 then
				if acceleration >= 0 and self.updatedAcceleration > 0 then
					self.myLastAcceleration = self.myLastAcceleration - 0.2;
					if self.myLastAcceleration < 0.2 then
						self.myLastAcceleration = 0.2;
					end;
				end;
			end;

			if self:getIsActiveForSound() then
				if not self.GearShiftPlaying then
					playSample(self.GearShiftSoundId, 1, 0.5, 0);
				end;
			end;
			
			self.animationName = "gearUpReverse";
			self:playAnimation(self.animationName, 1, nil, true)
			
		elseif self.myLastGear < 0 and self.myCurrentGear == 0 then
			if not self.GearShiftPlaying then
				playSample(self.GearShiftSoundId, 1, 0.5, 0);
			end;
			
			self.animationName = "gearReverseToNeutral";
			self:playAnimation(self.animationName, 1, nil, true)
			
		end;
		
		if self.myLastAcceleration < 0.1 then
			self.myLastAcceleration = 0.1;
		end;
				
		--update gear display
		--self:updateGearDisplay();
				
		--RPM meter value
		
		self.rpmMeterValue = self.updatedAcceleration * self.motorMaxRpmLimit[3];

		--Sound adjustments
		
				--Throttle Sound	
		self.lastRoundPerMinute = 0;
		self.motor.lastMotorRpm = 0;
		
		local roundPerSecond = 0;
		
		if self.myLastAcceleration > 0 then
			if acceleration >= 0 and self.myCurrentGear > 0 then
				roundPerSecond = self.myLastAcceleration * 48 - (self.myCurrentGear * 0.3);
			elseif acceleration >= 0 and self.myCurrentGear < 0 then
				roundPerSecond = self.myLastAcceleration * 48 + (self.myCurrentGear * 0.3);
			else
				roundPerSecond = self.myLastAcceleration * 48;
			end;
			if roundPerSecond < 0 then
				roundPerSecond = 0;
			end;
		end;

		
		if self.isMotorStarted then

			if self.powershiftMotorSound ~= nil then
				
				local pitch = math.min(self.powershiftMotorSoundPitchOffset - (0.25 - self.updatedAcceleration * 0.25)  + self.powershiftMotorSoundPitchScale*math.abs(roundPerSecond), self.powershiftMotorSoundPitchMax);
				
				--renderText(0.5, 0.1, 0.0250, string.format("myLastAcceleration " .. self.myLastAcceleration));
				--renderText(0.5, 0.2, 0.0250, string.format("roundPerSecond " .. roundPerSecond));
				--renderText(0.5, 0.3, 0.0250, string.format("pitch " .. pitch));
				setSamplePitch(self.powershiftMotorSound, pitch);

				if self.powershiftMotorSoundRun ~= nil then
					setSamplePitch(self.powershiftMotorSoundRun, math.min(self.powershiftMotorSoundRunPitchOffset + self.powershiftMotorSoundRunPitchScale*math.abs(roundPerSecond), self.powershiftMotorSoundRunPitchMax));
				end;

			end;
			
			if self.powershiftMotorSoundRun ~= nil then

				local maxRpm  = self.motor.maxRpm[3];

				if self.updatedAcceleration > 0 then
					local rpmVolume = Utils.clamp(math.abs(roundPerSecond*60)/((maxRpm - self.motor.minRpm)), 0.0, 1.0);
					setSampleVolume(self.powershiftMotorSoundRun, rpmVolume);
				else
					local rpmVolume = Utils.clamp(math.abs(roundPerSecond*60)/((maxRpm - self.motor.minRpm)*2), 0.0, 1.0);
					setSampleVolume(self.powershiftMotorSoundRun, rpmVolume);
				end;

			end;
		end;
					
		--self.gearRatio = 1 - (((0.5) * self.updatedAcceleration) - (0.5 * self.myCurrentGear/self.noOfForwardGears));
		self.gearRatio = (0.5 + (0.5 * self.myCurrentGear/self.noOfForwardGears));
				
		--renderText(0.5, 0.6, 0.0250, string.format(self.gearRatio));
		
		if self.myCurrentGear > 0 and self.isMotorStarted then
			self.updatedAcceleration = (self.gearRatio) * self.updatedAcceleration;--((5 + (self.gearRatio))/self.noOfForwardGears) * self.updatedAcceleration;
		elseif self.myCurrentGear < 0 and self.isMotorStarted then
			self.updatedAcceleration = (self.gearRatio) * self.updatedAcceleration;
		else
			self.updatedAcceleration = 0;
		end;
		
		--renderText(0.5, 0.5, 0.0250, string.format(self.updatedAcceleration));

		if self.fuelFillLevel == 0 then
			self.updatedAcceleration = 0;
		end;
		
		--disable handbrake when we start to move
		if self.handbrakeOn and self.updatedAcceleration > 0 then
			self.handbrakeOn = false;
		end;
		
		
		
			
		if self.updatedAcceleration > 1 then
			self.updatedAcceleration = 1;
		elseif self.updatedAcceleration < -1 then
			self.updatedAcceleration = -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 self.updatedAcceleration > 0 then
			self.motor.brakeForce = 0;
		end;
			
		if (self.myCurrentGear < 0 and self.movingDirection > 0) or (self.myCurrentGear > 0 and self.movingDirection < 0)then
			self.motor.brakeForce = 6;		
		end;

		self.newAcceleration = self.updatedAcceleration;
			--Set groundcontact to false for all wheels to diable std. Steerable methods for wheel update
		--for k, wheel in pairs(self.wheels) do
			--wheel.hasGroundContact = false;
		--end;
		
		--local brake = false;
		if acceleration < 0 then
			self.doBrake = true;
		else
			self.doBrake = false;
		end;
		
		--if self.firstTimeRun and self.isEntered then
			--self:updateWheelsPhysics(self, dt, self.lastSpeed, self.updatedAcceleration, brake, 1);
		--end;
		--self.firstTimeRun = false;
		
	elseif not self.isAITractorActivated and not self.isAutopilotActivated then
		--Tractor is not entered or hired in any way so we sets "parking" brake on her
		self.motor.brakeForce = 6;
		self.updatedAcceleration = 0;
		self.newAcceleration = 0;
		self.doBrake = true;
		--if self.firstTimeRun then
			--WheelsUtil.updateWheelsPhysics(self, dt, self.lastSpeed, 0, false, 0);
		--end;
		--renderText(0.5, 0.90, 0.020, string.format("Not active part"));
	end;
	
	self.lastAcceleration = self.newAcceleration;

	self.myLastGear = self.myCurrentGear;
	self.lastHandBrake =  self.handbrakeOn;
end;

function powerShift:speederAnimation(dt, acceleration, newAcceleration)
	if self.speeder ~= nil then
		
		if acceleration > 0 then
			setRotation(self.speeder, Utils.degToRad(20 * math.abs(acceleration)),0,0);
		elseif newAcceleration > 0 then
			setRotation(self.speeder, Utils.degToRad(20 * math.abs(newAcceleration)),0,0);
		else
			setRotation(self.speeder, Utils.degToRad(0),0,0);
		end;
	end;
end;
	
function powerShift:clutchAnimation(dt, acceleration)
	if self.clutch ~= nil then
		local clutchActive = false;
		if acceleration < 0 then
			clutchActive = true;
		end;
		
		local clutchMax = {};
		clutchMax[1] = Utils.degToRad(-40);
		clutchMax[2] = Utils.degToRad(0);
		clutchMax[3] = Utils.degToRad(0);
		local clutchRotationTime = 500;
		
		local clutchMin = {};
		clutchMin[1] = Utils.degToRad(0);
		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 powerShift:brakeAnimation(dt, acceleration)
	if self.brake ~= nil then
		
		if acceleration < 0 then
			setRotation(self.brake, Utils.degToRad(-25 * math.abs(acceleration)),0,0);
		else
			setRotation(self.brake, Utils.degToRad(0),0,0);
		end;
	end;
end;

function powerShift: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;

--[[function powerShift:updateGearDisplay()
		-- Handle the digitRPMs in the display
	if self.numDigitGEAROne > 0 and self.numDigitGEARTwo > 0  then
		if self.isMotorStarted then
			if not self.handbrakeOn then
				local absoluteGearValue = self.myCurrentGear;
				
				if absoluteGearValue < 0 then
					absoluteGearValue = -absoluteGearValue;
				end;
				local tens = math.floor(absoluteGearValue/10);
				
				if tens < 0 then
					tens = -tens;
				end;
				
				for i=1, self.numDigitGEARTwo do
					setVisibility(self.digitGEARTwo[i].rotNode,false);
					setVisibility(self.digitGEARTwoLight[i].rotNode,false);
				end;
				if tens ~= nil and tens > 0  then
					setVisibility(self.digitGEARTwo[tens].rotNode,true);
					setVisibility(self.digitGEARTwoLight[tens].rotNode,true);
				elseif self.myCurrentGear < 0  then
					setVisibility(self.digitGEARTwo[11].rotNode,true);
					setVisibility(self.digitGEARTwoLight[11].rotNode,true);
				else
					setVisibility(self.digitGEARTwo[self.numDigitGEARTwo].rotNode,true);
					setVisibility(self.digitGEARTwoLight[self.numDigitGEARTwo].rotNode,true);
				end;
				
				local ones = absoluteGearValue - tens * 10;
				if ones == 0 then
					ones = 10;
				end;
				if ones < 0 then
					ones = -ones;
				end;			
				for i=1, self.numDigitGEAROne do
					setVisibility(self.digitGEAROne[i].rotNode,false);
					setVisibility(self.digitGEAROneLight[i].rotNode,false);
				end;
				setVisibility(self.digitGEAROne[ones].rotNode,true);
				setVisibility(self.digitGEAROneLight[ones].rotNode,true);
			else
				for i=1, self.numDigitGEARTwo do
					setVisibility(self.digitGEARTwo[i].rotNode,false);
					setVisibility(self.digitGEARTwoLight[i].rotNode,false);
				end;
				for i=1, self.numDigitGEAROne do
					setVisibility(self.digitGEAROne[i].rotNode,false);
					setVisibility(self.digitGEAROneLight[i].rotNode,false);
				end;
				setVisibility(self.digitGEAROne[11].rotNode,true);
				setVisibility(self.digitGEAROneLight[11].rotNode,true);
			end;
			
		else
			for i=1, self.numDigitGEAROne do
				setVisibility(self.digitGEAROne[i].rotNode,false);
				setVisibility(self.digitGEAROneLight[i].rotNode,false);
			end;
	
			for i=1, self.numDigitGEARTwo do
				setVisibility(self.digitGEARTwo[i].rotNode,false);
				setVisibility(self.digitGEARTwoLight[i].rotNode,false);
			end;
		end;
	end;
end;]]

