-- 
-- Gearbox 6 Gears
-- Specialization class for Gearbox with 6 gears
-- author: Blacky_BPG
-- date:  23.02.14
-- Thanks for help testing to Marc85
-- 
-- Update 07.03.14
--		* added Stop motor when starting from high gears
--		* added overspeeding the engine when downshifting during high speed
-- 

GearBox6 = {};

function GearBox6.prerequisitesPresent(specializations)
	print("Specialization Gearbox6 by Blacky_BPG");
	return SpecializationUtil.hasSpecialization(Motorized, specializations);
end;

function GearBox6:load(xmlFile)
	if g_newGUISkin then
		self.controlpath = Utils.getFilename("Textures/coronas_hud/gearhud_ngs.dds", self.baseDirectory);
	else
		self.controlpath = Utils.getFilename("Textures/coronas_hud/gearhud.dds", self.baseDirectory);
	end;
	self.setGear = SpecializationUtil.callSpecializationsFunction("setGear");
	self.hudGearChangeWidth = 0.18;
	self.hudGearChangeHeight = 0.043;
	self.hudGearChangePoxX = 0.4599;
	self.hudGearChangePoxY = 0.9495;
	self.hudGearChangeOverlay = Overlay:new("hudGearChangeControl", self.controlpath, self.hudGearChangePoxX, self.hudGearChangePoxY, self.hudGearChangeWidth, self.hudGearChangeHeight);
	self.gearSet = false;
	self.gearN = true;
	self.gearR = false;
	self.gear1 = false;
	self.gear2 = false;
	self.gear3 = false;
	self.gear4 = false;
	self.gear5 = false;
	self.gear6 = false;
	self.reverse = false;

	self.hasGearShutDown = false;
	local speedCheckStr = getXMLString(xmlFile, "vehicle.gearBoxLowSpeed#two");
	if speedCheckStr ~= nil then
		self.hasGearShutDown = true;
		self.gearShutDownTwo = getXMLFloat(xmlFile, "vehicle.gearBoxLowSpeed#two");
		self.gearShutDownThree = getXMLFloat(xmlFile, "vehicle.gearBoxLowSpeed#three");
		self.gearShutDownFour = getXMLFloat(xmlFile, "vehicle.gearBoxLowSpeed#four");
		self.gearShutDownFive = getXMLFloat(xmlFile, "vehicle.gearBoxLowSpeed#five");
		self.gearShutDownSix = getXMLFloat(xmlFile, "vehicle.gearBoxLowSpeed#six");
	end;

	self.hasRPMOverride = false;
	local speedCheckStr = getXMLString(xmlFile, "vehicle.gearBoxHighSpeed#one");
	if speedCheckStr ~= nil then
		self.hasRPMOverride = true;
		self.rpmOverrideOne = getXMLFloat(xmlFile, "vehicle.gearBoxHighSpeed#one");
		self.rpmOverrideTwo = getXMLFloat(xmlFile, "vehicle.gearBoxHighSpeed#two");
		self.rpmOverrideThree = getXMLFloat(xmlFile, "vehicle.gearBoxHighSpeed#three");
		self.rpmOverrideFour = getXMLFloat(xmlFile, "vehicle.gearBoxHighSpeed#four");
		self.rpmOverrideFive = getXMLFloat(xmlFile, "vehicle.gearBoxHighSpeed#five");
	end;

	brakeSoundFile = Utils.getFilename("sounds/brake.wav", self.baseDirectory);
	self.brakeSoundId = createSample("brakeSound");
	loadSample(self.brakeSoundId, brakeSoundFile, false);
	self.brakePlaying = false;
	
	gearChangeSoundFile = Utils.getFilename("sounds/gear.wav", self.baseDirectory);
	self.gearChangeSoundId = createSample("gearChangeSound");
	loadSample(self.gearChangeSoundId, gearChangeSoundFile, false);
	if self.motor ~= nil then
		self.gearBrakeForce = self.motor.brakeForce;
		if self.motor.minRpm ~= nil then
			if self.fa == nil then
				self.fa = {};
			end;
			self.fa.backupRpmMin = self.motor.minRpm; -- FuelAdjust Value
			self.saveMinRpm = self.motor.minRpm;  	-- PloughingSpec Value
			self.gearsRPMBackup = self.motor.minRpm; -- Gears Value
			self.standardMinRpm = self.motor.minRpm; -- AttacherSetRpm Value
			self.gearShiftFix = false;
			self.backupPitch = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.motorSound#pitchOffset"), 1.0);
			self.backupRunPitch = getXMLFloat(xmlFile, "vehicle.motorSoundRun#pitchOffset");
			self.pitchMax = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.motorSound#pitchMax"), 2.0);
			self.pitchRunMax = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.motorSound#pitchMax"), 2.0);
			self.backupMaxRpm = self.motor.maxRpm[3];
			self.pitchFactor = (self.pitchMax - self.backupPitch) / (self.motor.maxRpm[3] - self.motor.minRpm);
			self.pitchRunFactor = (self.pitchRunMax - self.backupRunPitch) / (self.motor.maxRpm[3] - self.motor.minRpm);
			self.maxPitchDetected = 0;
		end;
	end;
end;

function GearBox6:delete()
end;

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

function GearBox6:setGear(gearR,gearN,gear1,gear2,gear3,gear4,gear5,gear6,reverse,mustSet)
	self.gearR = gearR;
	self.gearN = gearN;
	self.gear1 = gear1;
	self.gear2 = gear2;
	self.gear3 = gear3;
	self.gear4 = gear4;
	self.gear5 = gear5;
	self.gear6 = gear6;
	self.reverse = reverse;
	if mustSet ~= nil and mustSet then
		self.gearSet = true;
	end;
end;

function GearBox6:readStream(streamId, connection)
	self.gearR = streamReadBool(streamId);
	self.gearN = streamReadBool(streamId);
	self.gear1 = streamReadBool(streamId);
	self.gear2 = streamReadBool(streamId);
	self.gear3 = streamReadBool(streamId);
	self.gear4 = streamReadBool(streamId);
	self.gear5 = streamReadBool(streamId);
	self.gear6 = streamReadBool(streamId);
	self.reverse = streamReadBool(streamId);
end;

function GearBox6:writeStream(streamId, connection)
	streamWriteBool(streamId, self.gearR);
	streamWriteBool(streamId, self.gearN);
	streamWriteBool(streamId, self.gear1);
	streamWriteBool(streamId, self.gear2);
	streamWriteBool(streamId, self.gear3);
	streamWriteBool(streamId, self.gear4);
	streamWriteBool(streamId, self.gear5);
	streamWriteBool(streamId, self.gear6);
	streamWriteBool(streamId, self.reverse);
end;

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

function GearBox6:update(dt)
	if self.gearSet == true then
		GearBoxEvent.sendEvent(self, self.gearR,self.gearN,self.gear1,self.gear2,self.gear3,self.gear4,self.gear5,self.gear6,self.reverse);
		self.gearSet = false;
	end;
	if self.isEntered then
			if InputBinding.hasEvent(InputBinding.gearUp) then
				if self.gearR == true then
					self.gearN = true;
					self.gearR = false;
				elseif self.gearN == true then
					self.reverse = false;
					self.gear1 = true;
					self.gearN = false;
				elseif self.gear1 == true then
					self.gear2 = true;
					self.gear1 = false;
				elseif self.gear2 == true then
					self.gear3 = true;
					self.gear2 = false;
				elseif self.gear3 == true then
					self.gear4 = true;
					self.gear3 = false;
				elseif self.gear4 == true then
					self.gear5 = true;
					self.gear4 = false;
				elseif self.gear5 == true then
					self.gear6 = true;
					self.gear5 = false;
				end;
				self.gearSet = true;
				playSample(self.gearChangeSoundId, 1, 1, 0);
			end;
			if InputBinding.hasEvent(InputBinding.gearDown) then
				if self.gear6 == true then
					self.gear5 = true;
					self.gear6 = false;
				elseif self.gear5 == true then
					self.gear4 = true;
					self.gear5 = false;
				elseif self.gear4 == true then
					self.gear3 = true;
					self.gear4 = false;
				elseif self.gear3 == true then
					self.gear2 = true;
					self.gear3 = false;
				elseif self.gear2 == true then
					self.gear1 = true;
					self.gear2 = false;
				elseif self.gear1 == true then
					self.gearN = true;
					self.gear1 = false;
				elseif self.gearN == true then
					self.gearR = true;
					self.reverse = true;
					self.gearN = false;
				end;
				self.gearSet = true;
				playSample(self.gearChangeSoundId, 1, 1, 0);
			end;

		local axisDir = -(InputBinding.getDigitalInputAxis(InputBinding.AXIS_MOVE_FORWARD_VEHICLE));
		if axisDir > 0 then
			if self.hasGearShutDown and self.isMotorStarted then
				local kmh = (self.lastSpeed*self.speedDisplayScale*3600);
				if self.gear6 and kmh < (self.gearShutDownSix / 2) then
					self:setManualIgnitionMode(3);
					self:setManualIgnitionMode(1);
				elseif self.gear5 and kmh < (self.gearShutDownFive / 2) then
					self:setManualIgnitionMode(3);
					self:setManualIgnitionMode(1);
				elseif self.gear4 and kmh < (self.gearShutDownFour / 2) then
					self:setManualIgnitionMode(3);
					self:setManualIgnitionMode(1);
				elseif self.gear3 and kmh < (self.gearShutDownThree / 2) then
					self:setManualIgnitionMode(3);
					self:setManualIgnitionMode(1);
				elseif self.gear2 and kmh < (self.gearShutDownTwo / 2) then
					self:setManualIgnitionMode(3);
					self:setManualIgnitionMode(1);
				end;
			end;
			self.motor:setSpeedLevel(0, true)
			if self.gearsRPMBackup ~= nil and self.gearN then
				if self.motor.minRpm ~= nil and self.motor.minRpm > 0 and self.motor.minRpm < self.motor.maxRpm[3] then
					self.motor.minRpm = math.min(self.motor.maxRpm[3]-5,self.motor.minRpm + 20);
					self.fa.backupRpmMin = self.motor.minRpm; -- FuelAdjust Value
					self.saveMinRpm = self.motor.minRpm;  	-- PloughingSpec Value
					self.standardMinRpm = self.motor.minRpm; -- AttacherSetRpm Value
				end;
			end;
		else
			if self.gearN then
				if self.gearsRPMBackup ~= nil then
					if self.motor.minRpm ~= nil and self.motor.minRpm > 0 then
						self.motor.minRpm = self.motor.minRpm - 16;
						self.fa.backupRpmMin = self.motor.minRpm; -- FuelAdjust Value
						self.saveMinRpm = self.motor.minRpm;  	-- PloughingSpec Value
						self.standardMinRpm = self.motor.minRpm; -- AttacherSetRpm Value
						if self.motor.minRpm < self.gearsRPMBackup then
							self.gearShiftFix = false;
							self.motor.minRpm = self.gearsRPMBackup;
							self.fa.backupRpmMin = self.motor.minRpm; -- FuelAdjust Value
							self.saveMinRpm = self.motor.minRpm;  	-- PloughingSpec Value
							self.standardMinRpm = self.motor.minRpm; -- AttacherSetRpm Value
						end;
					end;
				end;
			else
				if self.gearsRPMBackup ~= nil then
					if self.motor.minRpm ~= nil and self.motor.minRpm > 0 then
						if self.gearsRPMBackup < self.motor.minRpm then
							if not self.gearShiftFix then
								self.gearShiftFix = true;
								self.motor.minRpm = ((self.motor.minRpm - self.gearsRPMBackup) / 2) + self.gearsRPMBackup;
								self.fa.backupRpmMin = self.motor.minRpm; -- FuelAdjust Value
								self.saveMinRpm = self.motor.minRpm;  	-- PloughingSpec Value
								self.standardMinRpm = self.motor.minRpm; -- AttacherSetRpm Value
							else
								self.motor.minRpm = self.motor.minRpm - 50;
								self.fa.backupRpmMin = self.motor.minRpm; -- FuelAdjust Value
								self.saveMinRpm = self.motor.minRpm;  	-- PloughingSpec Value
								self.standardMinRpm = self.motor.minRpm; -- AttacherSetRpm Value
								if self.motor.minRpm <= self.gearsRPMBackup then
									self.gearShiftFix = false;
								end;
							end;
						end;
						if self.motor.minRpm < self.gearsRPMBackup then
							self.gearShiftFix = false;
							self.motor.minRpm = self.gearsRPMBackup;
							self.fa.backupRpmMin = self.motor.minRpm; -- FuelAdjust Value
							self.saveMinRpm = self.motor.minRpm;  	-- PloughingSpec Value
							self.standardMinRpm = self.motor.minRpm; -- AttacherSetRpm Value
						end;
					end;
				end;
			end;
		end;
		if axisDir < 0 then
			self:setBrakeLightsVisibility(true);
			self.motor.brakeForce = self.gearBrakeForce
			if self.brakeSoundId ~= nil and not self.brakePlaying then
				playSample(self.brakeSoundId,1,1,0);
				self.brakePlaying = true;
			end;
		else
			self.motor.brakeForce = self.gearBrakeForce / 2;
			self.brakePlaying = false;
			self:setBrakeLightsVisibility(false);
			self.braking = false;
		end;
		if self.isMotorStarted then
			local pitchMulti = 0;
			if self.hasRPMOverride then
				local kmh = (self.lastSpeed*self.speedDisplayScale*3600);
				local calcPitch = 0;
				if self.gear1 and kmh > self.rpmOverrideOne then
					calcPitch = self.rpmOverrideOne;
				elseif self.gear2 and kmh > self.rpmOverrideTwo then
					calcPitch = self.rpmOverrideTwo;
				elseif self.gear3 and kmh > self.rpmOverrideThree then
					calcPitch = self.rpmOverrideThree;
				elseif self.gear4 and kmh > self.rpmOverrideFour then
					calcPitch = self.rpmOverrideFour;
				elseif self.gear5 and kmh > self.rpmOverrideFive then
					calcPitch = self.rpmOverrideFive;
				end;
				if calcPitch > 0 then
					if self.maxPitchDetected == 0 then
						self.maxPitchDetected = getSamplePitch(self.motorSoundRun);
					end;
					pitchMulti = self.maxPitchDetected + ((self.maxPitchDetected / self.backupMaxRpm * (self.backupMaxRpm / calcPitch * (kmh - calcPitch))) / 3);
					if self.motorSound3D ~= nil then
						setSamplePitch(getAudioSourceSample(self.motorSound3D), pitchMulti);
					end;
					if self.motorSoundRun ~= nil then
						setSamplePitch(self.motorSoundRun, pitchMulti);
					end;
				end;
			end;
			local ratio = 0;
			local rpmRange = 0;
			if self.gearR then
				ratio = 14;
				rpmRange = 300;
				if self.setState ~= nil then self:setState("reverse",true) end;
			elseif self.gearN then
				ratio = 0;
				if self.setState ~= nil then self:setState("reverse",false) end;
			elseif self.gear1 then
				ratio = 15;
				rpmRange = 250;
				if self.setState ~= nil then self:setState("reverse",false) end;
			elseif self.gear2 then
				ratio = 10;
				rpmRange = 200;
				if self.setState ~= nil then self:setState("reverse",false) end;
			elseif self.gear3 then
				ratio = 7.5;
				rpmRange = 200;
				if self.setState ~= nil then self:setState("reverse",false) end;
			elseif self.gear4 then
				ratio = 5.5;
				rpmRange = 200;
				if self.setState ~= nil then self:setState("reverse",false) end;
			elseif self.gear5 then
				ratio = 4.0;
				rpmRange = 150;
				if self.setState ~= nil then self:setState("reverse",false) end;
			elseif self.gear6 then
				ratio = 2.7;
				rpmRange = 1;
				if self.setState ~= nil then self:setState("reverse",false) end;
			end;
			self.motor.backwardGearRatio = ratio;
			self.motor.forwardGearRatios = {ratio/2,ratio/1.5,ratio,ratio/1.75};
			self.motor.rpmFadeOutRange = rpmRange;

			if self.motor.minRpm > self.gearsRPMBackup then
				local pitchSet = ((self.backupMaxRpm - (self.backupMaxRpm - self.motor.minRpm) - self.gearsRPMBackup) * self.pitchFactor) + self.backupPitch;
				self.motorSoundPitchOffset = pitchSet;
				setSamplePitch(self.motorSound, pitchSet);
			end;
		else
			local ratio = 0;
			self.motor.backwardGearRatio = 0;
			self.motor.forwardGearRatios = {0,0,0,0};
			if self.tipState ~= nil and self.tipState > 0 then
				self:onEndTip();
			end;
		end;
	end;
end;

function GearBox6:draw()

	if self.isEntered then
		if self.hudGearChangeOverlay ~= nil then
			self.hudGearChangeOverlay:render();
		end;
			if self.gearR then
				setTextColor(1,0,0,1);
				renderText(0.5900, 0.9600, 0.025, "R");
			else
				setTextColor(1,1,1,1);
				renderText(0.5900, 0.9600, 0.025, "R");
			end;
			if self.gearN then
				setTextColor(0,0.8,0,1);
				renderText(0.5770, 0.9600, 0.025, "N");
			else
				setTextColor(1,1,1,1);
				renderText(0.5770, 0.9600, 0.025, "N");
			end;
			if self.gear1 then
				setTextColor(1,0,0,1);
				renderText(0.5640, 0.9600, 0.025, "1");
			else
				setTextColor(1,1,1,1);
				renderText(0.5640, 0.9600, 0.025, "1");
			end;
			if self.gear2 then
				setTextColor(1,0,0,1);
				renderText(0.5510, 0.9600, 0.025, "2");
			else
				setTextColor(1,1,1,1);
				renderText(0.5510, 0.9600, 0.025, "2");
			end;
			if self.gear3 then
				setTextColor(1,0,0,1);
				renderText(0.5380, 0.9600, 0.025, "3");
			else
				setTextColor(1,1,1,1);
				renderText(0.5380, 0.9600, 0.025, "3");
			end;
			if self.gear4 then
				setTextColor(1,0,0,1);
				renderText(0.5250, 0.9600, 0.025, "4");
			else
				setTextColor(1,1,1,1);
				renderText(0.5250, 0.9600, 0.025, "4");
			end;
			if self.gear5 then
				setTextColor(1,0,0,1);
				renderText(0.5120, 0.9600, 0.025, "5");
			else
				setTextColor(1,1,1,1);
				renderText(0.5120, 0.9600, 0.025, "5");
			end;
			if self.gear6 then
				setTextColor(1,0,0,1);
				renderText(0.4990, 0.9600, 0.025, "6");
			else
				setTextColor(1,1,1,1);
				renderText(0.4990, 0.9600, 0.025, "6");
			end;
		end;
		setTextColor(1,1,1,1);
	end;

function GearBox6:onEnter()
end;

function GearBox6:onLeave()
	self.gearN = true;
	self.gearR = false;
	self.gear1 = false;
	self.gear2 = false;
	self.gear3 = false;
	self.gear4 = false;
	self.gear5 = false;
	self.gear6 = false;
	self.reverse = false;
	self:setGear(self.gearR, self.gearN, self.gear1, self.gear2, self.gear3, self.gear4, self.gear5, self.gear6, self.reverse, true);
end;

function GearBox6:drawGrainLevel(level, capacity, warnPercent)
end;

local origSteerableupdateVehiclePhysics = Steerable.updateVehiclePhysics;
Steerable.updateVehiclePhysics = function(self, axisForward, axisForwardIsAnalog, axisSide, axisSideIsAnalog, dt)
	if self.gearR == nil or self.reverse == nil then
		return origSteerableupdateVehiclePhysics(self, axisForward, axisForwardIsAnalog, axisSide, axisSideIsAnalog, dt);
	end;
	local acceleration = 0;
	if self.isMotorStarted and self.motorStartTime <= self.time then
		acceleration = -axisForward;
		if math.abs(acceleration) > 0.8 then
			if self.motor.speedLevel ~= 0 then
				self.lastAcceleration = self.lastAcceleration*0.5;
			end;
			self.motor:setSpeedLevel(0, true)
		end;
		if self.motor.speedLevel ~= 0 then
			acceleration = self.motor.accelerations[self.motor.speedLevel];
		end;
	end;
	if self.fuelFillLevel == 0 then
		acceleration = 0;
	end;

	local axisDir = -axisForward;
	if self.reverse then
		if self.gearR then
			if axisDir > 0 or self.motor.speedLevel ~= 0 then
				acceleration = -0.12;
				self.movingDirection = -1;
			end;
		end;
	else
		if self.gearN then
			acceleration = 0;
			self.movingDirection = 0;
		else
			self.movingDirection = 1;
			if axisDir > 0 or self.motor.speedLevel ~= 0 then
				local factor = 1;
				if self.gear1 then
					factor = 2.0;
				elseif self.gear2 then
					factor = 3.0;
				elseif self.gear3 then
					factor = 4.5;
				elseif self.gear4 then
					factor = 6.0;
				elseif self.gear5 then
					factor = 7.5;
				elseif self.gear6 then
					factor = 9.0;
				end;
				local kmh = (self.lastSpeed*self.speedDisplayScale*3600)+1;
				local tmp = 0.14 / 80;
				acceleration = 0.01 + (tmp * kmh * factor);
			end;
		end;
	end;

	if axisDir > 0 then
		self.motor:setSpeedLevel(0, true)
		if self.gearsRPMBackup ~= nil and self.gearN then
			if self.motor.minRpm ~= nil and self.motor.minRpm > 0 and self.motor.minRpm < self.motor.maxRpm[3] then
				self.motor.minRpm = math.min(self.motor.maxRpm[3]-5,self.motor.minRpm + 20);
				self.fa.backupRpmMin = self.motor.minRpm; -- FuelAdjust Value
				self.saveMinRpm = self.motor.minRpm;  	-- PloughingSpec Value
				self.standardMinRpm = self.motor.minRpm; -- AttacherSetRpm Value
			end;
		end;
	elseif axisDir < 0 then
		local kmh = (self.movingDirection*self.lastSpeed*3600);
		if kmh > 5 then
			acceleration = -0.05;
		elseif kmh < 0.7 then
			acceleration = 0.05;
		else
			acceleration = 0;
		end;
		self:setBrakeLightsVisibility(true);
		self.motor.brakeForce = self.gearBrakeForce
	else
		self.motor.brakeForce = self.gearBrakeForce / 2;
		self.brakePlaying = false;
		self:setBrakeLightsVisibility(false);
		self.braking = false;
		if self.gearN then
			if self.gearsRPMBackup ~= nil then
				if self.motor.minRpm ~= nil and self.motor.minRpm > 0 then
					self.motor.minRpm = self.motor.minRpm - 16;
					self.fa.backupRpmMin = self.motor.minRpm; -- FuelAdjust Value
					self.saveMinRpm = self.motor.minRpm;  	-- PloughingSpec Value
					self.standardMinRpm = self.motor.minRpm; -- AttacherSetRpm Value
					if self.motor.minRpm < self.gearsRPMBackup then
						self.gearShiftFix = false;
						self.motor.minRpm = self.gearsRPMBackup;
						self.fa.backupRpmMin = self.motor.minRpm; -- FuelAdjust Value
						self.saveMinRpm = self.motor.minRpm;  	-- PloughingSpec Value
						self.standardMinRpm = self.motor.minRpm; -- AttacherSetRpm Value
					end;
				end;
			end;
		else
			if self.gearsRPMBackup ~= nil then
				if self.motor.minRpm ~= nil and self.motor.minRpm > 0 then
					if self.gearsRPMBackup < self.motor.minRpm then
						if not self.gearShiftFix then
							self.gearShiftFix = true;
							self.motor.minRpm = ((self.motor.minRpm - self.gearsRPMBackup) / 2) + self.gearsRPMBackup;
							self.fa.backupRpmMin = self.motor.minRpm; -- FuelAdjust Value
							self.saveMinRpm = self.motor.minRpm;  	-- PloughingSpec Value
							self.standardMinRpm = self.motor.minRpm; -- AttacherSetRpm Value
						else
							self.motor.minRpm = self.motor.minRpm - 50;
							self.fa.backupRpmMin = self.motor.minRpm; -- FuelAdjust Value
							self.saveMinRpm = self.motor.minRpm;  	-- PloughingSpec Value
							self.standardMinRpm = self.motor.minRpm; -- AttacherSetRpm Value
							if self.motor.minRpm <= self.gearsRPMBackup then
								self.gearShiftFix = false;
							end;
						end;
					end;
					if self.motor.minRpm < self.gearsRPMBackup then
						self.gearShiftFix = false;
						self.motor.minRpm = self.gearsRPMBackup;
						self.fa.backupRpmMin = self.motor.minRpm; -- FuelAdjust Value
						self.saveMinRpm = self.motor.minRpm;  	-- PloughingSpec Value
						self.standardMinRpm = self.motor.minRpm; -- AttacherSetRpm Value
					end;
				end;
			end;
		end;
	end;

	local ratio = 0;
	local rpmRange = 0;
	if self.isMotorStarted then
		if self.gearR then
			ratio = 14;
			rpmRange = 300;
		elseif self.gearN then
			ratio = 0;
		elseif self.gear1 then
			ratio = 15;
			rpmRange = 250;
		elseif self.gear2 then
			ratio = 10;
			rpmRange = 200;
		elseif self.gear3 then
			ratio = 7.5;
			rpmRange = 200;
		elseif self.gear4 then
			ratio = 5.5;
			rpmRange = 200;
		elseif self.gear5 then
			ratio = 4.0;
			rpmRange = 150;
		elseif self.gear6 then
			ratio = 2.7;
			rpmRange = 1;
		end;
	else
		acceleration = 0;
	end;
	self.motor.backwardGearRatio = ratio;
	self.motor.forwardGearRatios = {ratio/2,ratio/1.5,ratio,ratio/1.75};
	self.motor.rpmFadeOutRange = rpmRange;

	acceleration = Steerable.calculateRealAcceleration(self, acceleration, dt);

	local inputAxisX = axisSide;
	if axisSideIsAnalog then
		local targetRotatedTime = 0;
		if inputAxisX < 0 then
			targetRotatedTime = math.min(-self.maxRotTime*inputAxisX, self.maxRotTime);
		else
			targetRotatedTime = math.max(self.minRotTime*inputAxisX, self.minRotTime);
		end;
		local maxTime = self.maxRotatedTimeSpeed*dt;
		if math.abs(targetRotatedTime-self.rotatedTime) > maxTime then
			if targetRotatedTime > self.rotatedTime then
				self.rotatedTime = self.rotatedTime + maxTime;
			else
				self.rotatedTime = self.rotatedTime - maxTime;
			end;
		else
			self.rotatedTime = targetRotatedTime;
		end;
	else
		local rotScale = math.min(1.0/(self.lastSpeed*self.speedRotScale+self.speedRotScaleOffset), 1);
		if inputAxisX < 0 then
			self.rotatedTime = math.min(self.rotatedTime - dt/1000*inputAxisX*rotScale, self.maxRotTime);
		elseif inputAxisX > 0 then
			self.rotatedTime = math.max(self.rotatedTime - dt/1000*inputAxisX*rotScale, self.minRotTime);
		else
			if self.autoRotateBackSpeed ~= 0 then
				if self.rotatedTime > 0 then
					self.rotatedTime = math.max(self.rotatedTime - dt/1000*self.autoRotateBackSpeed*rotScale, 0);
				else
					self.rotatedTime = math.min(self.rotatedTime + dt/1000*self.autoRotateBackSpeed*rotScale, 0);
				end;
			end;
		end;
	end;

	if self.firstTimeRun then
		WheelsUtil.updateWheelsPhysics(self, dt, self.lastSpeed, acceleration, false, self.requiredDriveMode)
	end;
end;

GearBoxEvent = {};
GearBoxEvent_mt = Class(GearBoxEvent, Event);

InitEventClass(GearBoxEvent, "GearBoxEvent");

function GearBoxEvent:emptyNew()
	local self = Event:new(GearBoxEvent_mt);
	self.className="GearBoxEvent";
	return self;
end;

function GearBoxEvent:new(vehicle, gearR, gearN, gear1, gear2, gear3, gear4, gear5, gear6, reverse)
	local self = GearBoxEvent:emptyNew()
	self.vehicle = vehicle;
	self.gearR = gearR;
	self.gearN = gearN;
	self.gear1 = gear1;
	self.gear2 = gear2;
	self.gear3 = gear3;
	self.gear4 = gear4;
	self.gear5 = gear5;
	self.gear6 = gear6;
	self.reverse = reverse;
	return self;
end;

function GearBoxEvent:readStream(streamId, connection)
	local id = streamReadInt32(streamId);
	self.gearR = streamReadBool(streamId);
	self.gearN = streamReadBool(streamId);
	self.gear1 = streamReadBool(streamId);
	self.gear2 = streamReadBool(streamId);
	self.gear3 = streamReadBool(streamId);
	self.gear4 = streamReadBool(streamId);
	self.gear5 = streamReadBool(streamId);
	self.gear6 = streamReadBool(streamId);
	self.reverse = streamReadBool(streamId);
	self.vehicle = networkGetObject(id);
	self:run(connection);
end;

function GearBoxEvent:writeStream(streamId, connection)
	streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
	streamWriteBool(streamId, self.gearR);
	streamWriteBool(streamId, self.gearN);
	streamWriteBool(streamId, self.gear1);
	streamWriteBool(streamId, self.gear2);
	streamWriteBool(streamId, self.gear3);
	streamWriteBool(streamId, self.gear4);
	streamWriteBool(streamId, self.gear5);
	streamWriteBool(streamId, self.gear6);
	streamWriteBool(streamId, self.reverse);
end;

function GearBoxEvent:run(connection)
	if self.vehicle ~= nil then
		if not connection:getIsServer() then
			g_server:broadcastEvent(GearBoxEvent:new(self.vehicle, self.gearR, self.gearN, self.gear1, self.gear2, self.gear3, self.gear4, self.gear5, self.gear6, self.reverse), nil, connection, self.vehicle);
		end;
		if self.vehicle.setGear ~= nil then
			self.vehicle:setGear(self.gearR, self.gearN, self.gear1, self.gear2, self.gear3, self.gear4, self.gear5, self.gear6, self.reverse);
		end;
	end;
end;

function GearBoxEvent.sendEvent(vehicle, gearR, gearN, gear1, gear2, gear3, gear4, gear5, gear6, reverse)
	if g_server ~= nil then
		g_server:broadcastEvent(GearBoxEvent:new(vehicle, gearR,gearN,gear1,gear2,gear3,gear4,gear5,gear6,reverse), nil, nil, vehicle);
	else
		g_client:getServerConnection():sendEvent(GearBoxEvent:new(vehicle, gearR,gearN,gear1,gear2,gear3,gear4,gear5,gear6,reverse));
	end;
end;
