--
-- Self-Leveling v2.0
-- Specialization for Multi Self-Leveling 
--
-- @author  	***Gya*** IFF_Team( http://web.italianfarmers.net/ )
-- @version 	v2.0
-- @date  		08/08/2013
-- @history:	v1.0 - Initial version 01/09/2012
--


M400_Advance = {};

M400_Advance.SELFLEVELOFF = 0;
M400_Advance.MANUALLEVEL = 1;
M400_Advance.SELFLEVELV = 2;
M400_Advance.STRADALEV = 3;


function M400_Advance.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Combine, specializations);
end;

function M400_Advance:load(xmlFile)
	
	self.currentTool = M400_Advance.STRADALEV;
	self.setCurrentTool = SpecializationUtil.callSpecializationsFunction("setCurrentTool");
	self.MonitorTool = 0;
	self.setMonitorTool = SpecializationUtil.callSpecializationsFunction("setMonitorTool");
	self.selectTool = "FrontLevOFF";
	self.EvenMode = 0;
	self.setModeTool = SpecializationUtil.callSpecializationsFunction("setModeTool");
	self.setSelectTool = SpecializationUtil.callSpecializationsFunction("setSelectTool");
	self.DSplan = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.DSplan#index"));
	self.OpenGTV = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.OpenGTV#index"));
	self.fan = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.Reut#index"));
    self.fanRotation = 0;
	self.Roteri = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.Roteri#index"));
	self.Roteri1 = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.Roteri1#index"));
	self.Roteri2 = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.Roteri2#index"));
    self.RoteriRotation = 0;
    self.RotersRotation = 0;
	
	--Animated Wheels --
 
 self.numAnimeWheels = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.AnimeWheels#count"), 0);
    self.AnimeWheels = {};
    for i=1, self.numAnimeWheels do
        local AnimeWheelsnamei = string.format("vehicle.AnimeWheels.RFWheel" .. "%d", i);
        self.AnimeWheels[i] = {};
		self.AnimeWheels[i].index = Utils.indexToObject(self.components, getXMLString(xmlFile, AnimeWheelsnamei .. "#index"));
		self.AnimeWheels[i].refWheel = Utils.getNoNil(getXMLInt(xmlFile,  AnimeWheelsnamei .. "#referenceWheel"), 1);			
    end;
	
	-- Switches--------
	self.numSwitches = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.switches#count"),0);
	self.switch = {};
	for i=1, self.numSwitches do
		local objname = string.format("vehicle.switches.switch" .. "%d", i);
		self.switch[i] = {};
		self.switch[i] = Utils.indexToObject(self.components, getXMLString(xmlFile, objname .. "#index"));
	end;
	
	----------------- GASOLIO INDICATORI----------
	self.fuelIndicatorsGroup = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.fuelIndicators#index"));
	self.numFuelIndicators = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.fuelIndicators#count"), 0);
	self.fuelIndicators = {};
    for i=1, self.numFuelIndicators do
        local objname = string.format("vehicle.fuelIndicators.fuelIndicator" .. "%d", i);
		self.fuelIndicators[i] = {};
        self.fuelIndicators[i].rotNode = Utils.indexToObject(self.components, getXMLString(xmlFile, objname .. "#rotNode"));
		setVisibility(self.fuelIndicators[i].rotNode,true);
    end;
	
	self.EvemL = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.RifLeft#index"));
	self.EvemR = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.RifRight#index"));
	
	self.txL, self.tyL, self.tzL = getTranslation(self.EvemL);
	self.txR, self.tyR, self.tzR = getTranslation(self.EvemR);
	self.wxL, self.wyL, self.wzL = getTranslation(self.wheels[3].repr);
	self.wxR, self.wyR, self.wzR = getTranslation(self.wheels[4].repr);
	self.deltaLwy = self.tyL - self.wyL;
	self.deltaRwy = self.tyR - self.wyR;
	
	--Hydraulica---
	
	self.setHydraulicDirection = SpecializationUtil.callSpecializationsFunction("setHydraulicDirection");
	
	local hydraulicsCount = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.hydraulics#count"), 0);	
	self.hydraulics = {};	
	for i=1, hydraulicsCount do
		local hydraulicName = string.format("vehicle.hydraulics.hydraulic%d", i);		
		self.hydraulics[i] = {};		
		self.hydraulics[i].node = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#index"));
		self.hydraulics[i].punch = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#punch"));
		self.hydraulics[i].translationPunch = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#punchFixpoint"));
		self.hydraulics[i].fixPoint = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#fixpoint"));	
		local xUp, yUp, zUp = Utils.getVectorFromString(Utils.getNoNil(getXMLString(xmlFile, hydraulicName .. "#upVectors"),"0 1 0"));
		self.hydraulics[i].upVectors = {xUp, yUp, zUp};
		
		local ax, ay, az;		
		if self.hydraulics[i].punch ~= nil then
			ax, ay, az = getWorldTranslation(self.hydraulics[i].punch);
		else
			ax, ay, az = getWorldTranslation(self.hydraulics[i].node);
		end;
		if self.hydraulics[i].translationPunch ~= nil then
			local bx, by, bz = getWorldTranslation(self.hydraulics[i].translationPunch);		
			self.hydraulics[i].punchDistance = Utils.vector3Length(ax-bx, ay-by, az-bz);
			
		end;
end;
	
	self.hydraulicSoundEnabled = false;
	local hydraulicSound = getXMLString(xmlFile, "vehicle.hydraulicSound#file");
	if hydraulicSound ~= nil and hydraulicSound ~= "" then
		hydraulicSound  = Utils.getFilename(hydraulicSound, self.baseDirectory);
		self.hydraulicSound = createSample("hydraulicSound");
		loadSample(self.hydraulicSound, hydraulicSound, false);
		self.hydraulicSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.hydraulicSound#pitchOffset"), 1);
		self.hydraulicSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.hydraulicSound#pitchMax"), 2.0);
	end;
	
	--WarningSound--
	
    self.WarningSoundEnabled = false;
	local WarningSound = getXMLString(xmlFile, "vehicle.WarningSound#file");
	if WarningSound ~= nil and WarningSound ~= "" then
    WarningSound = Utils.getFilename(WarningSound, self.baseDirectory);
    self.WarningSound = createSample("WarningSound");
    loadSample(self.WarningSound, WarningSound, false);
	self.WarningSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.WarningSound#pitchOffset"), 1);
	self.WarningSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.WarningSound#pitchMax"), 2.0);
	
	end;
	   -- Leve ---
	self.levaindicatori = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.levaindicatori#index"));
	self.levalater = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.levalater#index"));
	self.levalongi = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.levalongi#index"));
	self.ActivLater = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.ActivLater#index"));
	self.ActivFront = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.ActivFront#index"));
	
	--balance--
	
	self.vic = {};
	self.vic.balancePart = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.balance#balancePart"));
	
	--joint ponte anteriore--
	
	self.kinkJoint = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.kinkSteering#kinkJoint"), 0);
	self.kinkOrientation = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.kinkSteering#Orientation"));
	
		
    self.myCast = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.myCast#index"));
    self.myCast1 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.myCast1#index"));
    self.myCast2 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.myCast2#index"));
    self.myLevlZ = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.myLevlZ#index"));
	
	--ActivLev
	
    self.myLevLT = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.myLevLT#index"));
    self.myLevFR = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.myLevFR#index"));
    self.myLevBL = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.myLevBL#index"));
	setVisibility(self.myLevLT,false);	
	setVisibility(self.myLevFR,false);	
	setVisibility(self.myLevBL,false);	
	
	self.EvenLModder = true;
	self.ModalitiSTR = true;
	self.EvenAL = false;
	self.EvenLM = false;
	--self.WarningSunt  = true;
	self.isSelectable = true;
	self.OpenGT = false;
    self.autoBeacon = false;
	self.lastRotation = 0;
	self.lastXRotation = 0;
	self.lastZRotation = 0;
	self.setHydraulicTime = 30;
		
end;

function M400_Advance:delete()
end;
function M400_Advance:mouseEvent(posX, posY, isDown, isUp, button)
end;
function M400_Advance:readStream(streamId, connection)
	self:setCurrentTool(streamReadInt8(streamId), true);
	self:setMonitorTool(streamReadInt8(streamId), true);
	self:setSelectTool(streamReadInt8(streamId), true);
	self:setModeTool(streamReadInt8(streamId), true);
	self.OpenGT = streamReadInt8(streamId);
end;
function M400_Advance:writeStream(streamId, connection)
	streamWriteInt8(streamId, self.currentTool);
	streamWriteInt8(streamId, self.MonitorTool);
	streamWriteInt8(streamId, self.selectTool);
	streamWriteInt8(streamId, self.EvenMode);
	streamWriteInt8(streamId, self.OpenGT);
end;
function M400_Advance:keyEvent(unicode, sym, modifier, isDown)
end;

function M400_Advance:update(dt)	

		if self.lastRotation  ~= nil then
		local xAttacher, yAttacher, zAttacher = getRotation(self.myCast2);
			self.lastRotation = xAttacher;
			end;

		if self.lastXRotation  ~= nil then
		local xAttacher, yAttacher, zAttacher = getRotation(self.myLevlZ);
			self.lastXRotation = zAttacher;
			end;

		if self.lastZRotation  ~= nil then
		local xAttacher, yAttacher, zAttacher = getRotation(self.myCast1);
			self.lastZRotation = zAttacher;
			end;
	-- select active tool

	if self:getIsActiveForInput() then
	if InputBinding.hasEvent(InputBinding.ModeMonitor) then
		self:setMonitorTool(self.MonitorTool+1); 
			if self.MonitorTool > 4 then
			self.MonitorTool = 0 ; 
			end;
		end;
	end; 
	if self:getIsActiveForInput() then
	if self.MonitorTool == 0 then
			self:setAnimationTime(8, 0 );
		elseif self.MonitorTool == 1 then
			self:setAnimationTime(8, 1 );
		elseif self.MonitorTool == 2 then
			self:setAnimationTime(8, 2 );
		elseif self.MonitorTool == 3 then
			self:setAnimationTime(8, 3 );
		elseif self.MonitorTool == 4 then
			self:setAnimationTime(8, 4 );
	end;
end;

	if self:getIsActiveForInput() then
		if InputBinding.hasEvent(InputBinding.OpenToGrain) then
			self.OpenGT = not self.OpenGT;
			end;
		end;

	if self:getIsActiveForInput() then
		if InputBinding.hasEvent(InputBinding.DeciverMode) then
		self:setModeTool(self.EvenMode+1); 
			if self.EvenMode > 3 then
				self.EvenMode = 0;
			end;
		end;
	end;
 	if self.isMotorStarted then
	   if self.motor.lastMotorRpm > 0.008 then
		self.fanRotation = self.fanRotation + 20;
		setRotation(self.fan, Utils.degToRad(self.fanRotation), 0, 0);
			--setVisibility(self.DSplan, true);
	else
		setRotation(self.fan, 0, 0, 0);
			--setVisibility(self.DSplan, false);
		end;
	end;
	

	
    if self.isThreshing then          
      self:setAnimationTime(7, 7); 
		self.RoteriRotation = self.RoteriRotation + 40;
		self.RotersRotation = self.RotersRotation + 20;
		setRotation(self.Roteri, Utils.degToRad(self.RoteriRotation), 0, 0);
		setRotation(self.Roteri1, 0, 0, Utils.degToRad(self.RotersRotation));
		setRotation(self.Roteri2, Utils.degToRad(self.RotersRotation), 0, 0);
      else
      self:setAnimationTime(7, 0);
		setRotation(self.Roteri, 0, 0, 0);
		setRotation(self.Roteri1, 0, 0, 0);
		setRotation(self.Roteri2, 0, 0, 0);
	 end;

				
 --if self:getIsActiveForInput() then
 if self:getIsActiveForInput() and self.EvenMode == 0 then
    if InputBinding.isPressed(InputBinding.StretrRA) then
     if self.animationParts[7].clipSpeed < 4 then
      self.animationParts[7].clipSpeed = self.animationParts[7].clipSpeed+0.02;
	   end;
	  elseif InputBinding.isPressed(InputBinding.StretrFR) then
	    if self.animationParts[7].clipSpeed > 0.5 then
      self.animationParts[7].clipSpeed = self.animationParts[7].clipSpeed-0.02;
          end;
	  elseif InputBinding.isPressed(InputBinding.SetrRear) then
	    if self.animationParts[7].clipSpeed > 0.5 then
      self.animationParts[7].clipSpeed = self.animationParts[7].clipSpeed-0.3;
	  end;
	  end;
end;
	
 if self:getIsActiveForInput() and self.EvenMode == 1 then
		if InputBinding.isPressed(InputBinding.SetrFront) then
			self:setAnimationTime(10, self.animationParts[10].currentPosition+(self.animationParts[10].offSet+dt), false);
		elseif InputBinding.isPressed(InputBinding.SetrRear) then
			self:setAnimationTime(10, self.animationParts[10].currentPosition-(self.animationParts[10].offSet+dt), false);
		end;
		--end;
	--if self.EvenMode  == 1 then
		if InputBinding.isPressed(InputBinding.StretrFR) then
			self:setAnimationTime(11, self.animationParts[11].currentPosition+(self.animationParts[11].offSet+dt), false);
		elseif InputBinding.isPressed(InputBinding.StretrRA) then
			self:setAnimationTime(11, self.animationParts[11].currentPosition-(self.animationParts[11].offSet+dt), false);
			end;
		end;
if self:getIsActiveForInput() and self.EvenMode  == 2 then
		if InputBinding.isPressed(InputBinding.SetrFront) then
			self:setAnimationTime(12, self.animationParts[12].currentPosition+(self.animationParts[12].offSet+dt), false);
		elseif InputBinding.isPressed(InputBinding.SetrRear) then
			self:setAnimationTime(12, self.animationParts[12].currentPosition-(self.animationParts[12].offSet+dt), false);
		end;
		--end;
	--if self.EvenMode  == 2 then
		if InputBinding.isPressed(InputBinding.StretrFR) then
			self:setAnimationTime(13, self.animationParts[13].currentPosition+(self.animationParts[13].offSet+dt), false);
		elseif InputBinding.isPressed(InputBinding.StretrRA) then
			self:setAnimationTime(13, self.animationParts[13].currentPosition-(self.animationParts[13].offSet+dt), false);
			end;
		end;
if self:getIsActiveForInput() and self.EvenMode  == 3 then
		if InputBinding.isPressed(InputBinding.SetrFront) then
			self:setAnimationTime(14, self.animationParts[14].currentPosition+(self.animationParts[14].offSet+dt), false);
		elseif InputBinding.isPressed(InputBinding.SetrRear) then
			self:setAnimationTime(14, self.animationParts[14].currentPosition-(self.animationParts[14].offSet+dt), false);
		end;
	--end;
	--if self.EvenMode  == 3 then
		if InputBinding.isPressed(InputBinding.StretrFR) then
			self:setAnimationTime(15, self.animationParts[15].currentPosition+(self.animationParts[15].offSet+dt), false);
		elseif InputBinding.isPressed(InputBinding.StretrRA) then
			self:setAnimationTime(15, self.animationParts[15].currentPosition-(self.animationParts[15].offSet+dt), false);
			--end;
		--end;
	end;
end;


    if not self:getIsActive() and self.autoBeacon then
        if self.beaconLightsActive then
            for _, beaconLight in pairs(self.beaconLights) do
                rotate(beaconLight.node, 0, beaconLight.speed*dt, 0);
        end;    
    end;
end;
	
	     --Modaliti Movin part
		 
  --if self:getIsActive() then
  if self:getIsActiveForInput() then
    if InputBinding.hasEvent(InputBinding.LMORERPM) then
		self:setSelectTool("FrontLevOFF");
		elseif InputBinding.hasEvent(InputBinding.LLESSRPM) then
		self:setSelectTool("FrontLevML");
		elseif InputBinding.hasEvent(InputBinding.LRESETRPM) then
		self:setSelectTool("FrontLevAL");
		end;
end;

	     --Hydro-animate and reference part
		 
if self:getIsActive() then
			
		self.setHydraulicTime = 30;	
	end;

	if self.setHydraulicTime > 0 then
		for k,v in pairs(self.hydraulics) do 
			self:setHydraulicDirection(k);
		end;
		self.setHydraulicTime = self.setHydraulicTime - 1;
		end; 
		
	--Animate Wheel
	local Lwx, Lwy, Lwz = getTranslation(self.wheels[3].repr);
	local Ltx, Lty, Ltz = getTranslation(self.EvemL);
	setTranslation(self.EvemL, Ltx, (Lwy+self.deltaLwy), Ltz);
	
	local Rwx, Rwy, Rwz = getTranslation(self.wheels[4].repr);
	local Rtx, Rty, Rtz = getTranslation(self.EvemR);
	setTranslation(self.EvemR, Rtx, (Rwy+self.deltaRwy), Rtz);

	
	--- rotate the little wheels
	for i=1, self.numAnimeWheels do	
			
		local q = self.AnimeWheels[i].refWheel
	
		local x,y,z = getRotation(self.wheels[q].repr);
		local RFWheel = self.AnimeWheels[i].index;
		setRotation(RFWheel, x,y,z);
	end;
	if self:getIsActiveForInput() then
		if self.ModalitiSTR then
		if InputBinding.hasEvent(InputBinding.LEVELOFFV) then
			self:setCurrentTool(M400_Advance.SELFLEVELOFF);
			elseif InputBinding.hasEvent(InputBinding.MLLEVELV) then
			self:setCurrentTool(M400_Advance.MANUALLEVEL);
			elseif InputBinding.hasEvent(InputBinding.SELFLEVELV) then
			self:setCurrentTool(M400_Advance.SELFLEVELING);
			end;
		end;
		if self.EvenLModder then
		if InputBinding.hasEvent(InputBinding.LEVELOFFV) then
			self:setCurrentTool(M400_Advance.SELFLEVELOFF);
			elseif  InputBinding.hasEvent(InputBinding.STRADALEV) then
			self:setCurrentTool(M400_Advance.STRADALEV);
		end;
	end;
end;
	
	
	if self.currentTool == M400_Advance.STRADALEV and self.isMotorStarted then
		self:setAnimationTime(4, self.animationParts[4].offSet, false); 
		self.ModalitiSTR = false;
		
		
	elseif self.currentTool == M400_Advance.SELFLEVELOFF and self.isMotorStarted then 
		self:setAnimationTime(4, self.animationParts[4].animDuration, false);
		self.ModalitiSTR = true;
	end;
	if self:getIsActive() then
		if self.selectTool == "FrontLevOFF" then 
		self.EvenFAL = false;
		elseif self.selectTool == "FrontLevML" then
		self.EvenFAL = false;
		elseif self.selectTool == "FrontLevAL" then
		self.EvenFAL = true;
	end;
end;

if self:getIsActive() then
		if self.currentTool == M400_Advance.SELFLEVELOFF then
	self.EvenLModder = true;
	self.EvenAL = false;
	self.EvenLM = false;
		elseif self.currentTool == M400_Advance.MANUALLEVEL then
	self.EvenLModder = false;
	self.EvenLM = true;
	self.EvenAL = false;
		elseif self.currentTool == M400_Advance.SELFLEVELING then
	self.EvenLModder = false;
	self.EvenLM = true;
	self.EvenAL = true;
	end;
end;
		 
	if self.EvenLM or self.EvenLModder then
	   self.Sun1 = false;
	   self.Sun2 = false;
	   self.SunD = false;
	   self.SunS = false;
	   self.RunD = true;
	   self.RunS = false;
	end;
	
if self:getIsActive() then
		if self.kinkJoint ~= 0 then
			setJointFrame(self.componentJoints[self.kinkJoint].jointIndex , 0, self.componentJoints[self.kinkJoint].jointNode);   
			local x, y, z = getRotation(self.kinkOrientation);	    
			setRotation(self.kinkOrientation, 0,y,0);
	 end;	
end;

    --AUTOLEVEL--
	
	--PonteForntale Level X--	
	
	if self.EvenFAL  and self.isMotorStarted then
	local x,y,z = getRotation(self.myCast);
	if x >= Utils.degToRad(89) then
	   self.Sun2 = false;
	
	   else
	   local x,y,z = getRotation(self.myCast);
	if x < Utils.degToRad(90) then
	   self.Sun2 = true;
	   end;
	end;	
end;	   
	if self.EvenFAL   and self.isMotorStarted then
	local x,y,z = getRotation(self.myCast);
	if x <= Utils.degToRad(90)  then
	   self.Sun1 = false;
	   
	   else
	local x,y,z = getRotation(self.myCast);
	if x  > Utils.degToRad(91) then
	   self.Sun1 = true;
	   end;
	end;
end;
	
      --Warning and max/min Level Z--	
	   
	if self.EvenAL then
	local x,y,z = getRotation(self.myLevlZ);
	  if z <= Utils.degToRad(11.2) then
	   self.RunS = false;
	   
	   else
	   
	if z > Utils.degToRad(11.7) then
	   self.RunS = true;
	   end;
	end;
end;	
	
	if self.EvenAL then
	local x,y,z = getRotation(self.myLevlZ);
	if z <= Utils.degToRad(-11.2) then
	   self.RunD = false;
	   
	   else
	   
	if z > Utils.degToRad(-11.7) then
	   self.RunD = true;
	   end;
	end;
end;

   --Combinato Ponte/Barra Laterale and Warning--   
	   
	   
if self.EvenAL and not self.EvenLModder then

	local x,y,z = getRotation(self.myCast);
	if z >= Utils.degToRad(180)  then
	   self.SunS = false;
	   
	   else
	   
	local x,y,z = getRotation(self.myCast);
	if z > 0 and z < Utils.degToRad(183) then
	   self.SunS = true;
	   end;
	   end;
end;	   		
if self.EvenAL and not self.EvenLModder then

	local x,y,z = getRotation(self.myCast);
	if z <= Utils.degToRad(-180) then
	   self.SunD = false;
	
	   else
	   
	local x,y,z = getRotation(self.myCast);
	if z < 0 and z > Utils.degToRad(-177) then
	   self.SunD = true;
	   end;	
	   end;
end;


   --Ponte Posteriore X--
   
if self:getIsActive() then
	if self.selectTool == "FrontLevML" and self.isMotorStarted then
	if  InputBinding.isPressed(InputBinding.Laxe_DOWN) and self:getIsActiveForInput() then
			self:setAnimationTime(3, self.animationParts[3].currentPosition-(self.animationParts[3].offSet+dt), false);
			
	elseif InputBinding.isPressed(InputBinding.Laxe_UP) and self:getIsActiveForInput() then
			self:setAnimationTime(3, self.animationParts[3].currentPosition+(self.animationParts[3].offSet+dt), false);
			end;
			
			elseif self.selectTool == "FrontLevAL"  and self.isMotorStarted then
	if self.Sun1 then
			self:setAnimationTime(3, self.animationParts[3].currentPosition-(self.animationParts[3].offSet+dt), false);
			
	elseif self.Sun2 then
			self:setAnimationTime(3, self.animationParts[3].currentPosition+(self.animationParts[3].offSet+dt), false);
			
			end;
	elseif self.selectTool == "FrontLevOFF" and self.isMotorStarted then  
		self:setAnimationTime(3, self.animationParts[3].startPosition, false);
	end;
end;

  --Ponte Anteriore Laterale Z--
  
if self:getIsActive() then 
	if self.currentTool == M400_Advance.MANUALLEVEL and self.isMotorStarted then
		if InputBinding.isPressed(InputBinding.Laxe_DX) and self:getIsActiveForInput() then --kp_9
			self:setAnimationTime(1, self.animationParts[1].currentPosition+(self.animationParts[1].offSet+dt), false);
			
		elseif InputBinding.isPressed(InputBinding.Laxe_SX) and self:getIsActiveForInput() then --kp_8
			self:setAnimationTime(1, self.animationParts[1].currentPosition-(self.animationParts[1].offSet+dt), false);
			end;
			
		elseif self.currentTool == M400_Advance.SELFLEVELING  and self.isMotorStarted then
		if self.SunS then --kp_9
			self:setAnimationTime(1, self.animationParts[1].currentPosition+(self.animationParts[1].offSet+dt), false);
			
		elseif self.SunD then --kp_8
			self:setAnimationTime(1, self.animationParts[1].currentPosition-(self.animationParts[1].offSet+dt), false);
			
		end;
	elseif self.currentTool == M400_Advance.SELFLEVELOFF and self.isMotorStarted then 
		self:setAnimationTime(1, self.animationParts[1].startPosition, false);
	end; 
end;

   --Barra Laterale Z--
   
if self:getIsActive() then
	if self.currentTool == M400_Advance.MANUALLEVEL and self.isMotorStarted then
		if InputBinding.isPressed(InputBinding.Baxe_DX) and self:getIsActiveForInput() then --kp_6
			self:setAnimationTime(2, self.animationParts[2].currentPosition+(self.animationParts[2].offSet+dt), false);
			
		elseif InputBinding.isPressed(InputBinding.Baxe_SX) and self:getIsActiveForInput() then --kp_5
			self:setAnimationTime(2, self.animationParts[2].currentPosition-(self.animationParts[2].offSet+dt), false);
			end;
			
		elseif self.currentTool == M400_Advance.SELFLEVELING  and self.isMotorStarted then
		if self.SunS then --kp_6
			self:setAnimationTime(2, self.animationParts[2].currentPosition+(self.animationParts[2].offSet+dt), false);
			
		elseif self.SunD then --kp_5
			self:setAnimationTime(2, self.animationParts[2].currentPosition-(self.animationParts[2].offSet+dt), false);
			
		end;
	elseif self.currentTool == M400_Advance.SELFLEVELOFF and self.isMotorStarted then 
		self:setAnimationTime(2, self.animationParts[2].startPosition, false);
		end;
end;

     --Balance
	 
if self:getIsActive() then
			local ax, ay, az = getWorldTranslation(self.vic.balancePart);
			local bx = 0;
			local by = 1100000;
			local bz = 0;
			x, y, z = worldDirectionToLocal(getParent(self.vic.balancePart), bx-ax, by-ay, bz-az);
			setDirection(self.vic.balancePart, x, y, z, 0, 0, 1);
			end;
			
	-- Activ Level
if self:getIsActive() then
			if not self.animationParts[1].inputDone then
		setVisibility(self.myLevLT,true);
		else
		setVisibility(self.myLevLT,false);
		end;
	end;
if self:getIsActive() then
			if not self.animationParts[2].inputDone then
		setVisibility(self.myLevBL,true);
		else
		setVisibility(self.myLevBL,false);
		end;
	end;
if self:getIsActive() then
			if not self.animationParts[3].inputDone then
		setVisibility(self.myLevFR,true);
		else
		setVisibility(self.myLevFR,false);
	end;
end;
			
	-- hydraulics sounds
	if self:getIsActiveForSound() then
		local hydraulicSoundEnabled = false;
		for i=1, 4 do
			if not self.animationParts[i].inputDone then
				hydraulicSoundEnabled = true;
			end;
		end;
		if hydraulicSoundEnabled then
			if not self.hydraulicSoundEnabled and self.hydraulicSound ~= nil then
				playSample(self.hydraulicSound, 0, self.hydraulicSoundVolume, 0);
				setSamplePitch(self.hydraulicSound, self.hydraulicSoundPitchOffset-0.4);
				self.hydraulicSoundEnabled = true;
			end;
		else
			if self.hydraulicSoundEnabled then
				stopSample(self.hydraulicSound);
				self.hydraulicSoundEnabled = false;
			end;
		end;
	end;

	--Opening Grain Tank
	if self:getIsActive() then
	if self.OpenGT  then
		self:setAnimationTime(6, self.animationParts[6].animDuration, false); 
			setVisibility(self.OpenGTV, true);
       else
		self:setAnimationTime(6, self.animationParts[6].offSet, false);
			setVisibility(self.OpenGTV, false);
	end;
    end;

    --Warning Self Leveling Sounds
	
 if self:getIsActiveForSound() then
	 if self.WarningSound ~= nil then
		if not self.RunD or self.RunS then
			WarningSoundEnabled = true;
			else
			WarningSoundEnabled = false;
			end;
		end;
	end;
	if WarningSoundEnabled then
        if not self.WarningSoundEnabled  and self.WarningSound ~= nil then
            playSample(self.WarningSound, 0, WarningSoundEnabled , 0 );
			setSamplePitch(self.WarningSound, self.WarningSoundPitchOffset-0.4);
            self.WarningSoundEnabled = true;
			end;
		else
	        if self.WarningSoundEnabled then
            stopSample(self.WarningSound);
            self.WarningSoundEnabled = false;
        end;
    end;
end;


function M400_Advance:draw()
	if self.isMotorStarted then
	if self.currentTool == M400_Advance.SELFLEVELOFF then
				g_currentMission:addHelpButtonText(g_i18n:getText("LEVELOFFV"), InputBinding.LEVELOFFV);
		elseif self.currentTool == M400_Advance.SELFLEVELING  then
				g_currentMission:addHelpButtonText(g_i18n:getText("SELFLEVELV"), InputBinding.SELFLEVELV);
		elseif self.currentTool == M400_Advance.MANUALLEVEL then
				g_currentMission:addHelpButtonText(g_i18n:getText("MLLEVELV"), InputBinding.MLLEVELV);
		elseif self.currentTool == M400_Advance.STRADALEV then
				g_currentMission:addHelpButtonText(g_i18n:getText("STRADALEV"), InputBinding.STRADALEV);
	end;
end;
    if self.currentTool == M400_Advance.MANUALLEVEL then
		if InputBinding.isPressed(InputBinding.Laxe_UP) then
				g_currentMission:addHelpButtonText(g_i18n:getText("Laxe_UP"), InputBinding.Laxe_UP);
		elseif InputBinding.isPressed(InputBinding.Laxe_DOWN) then
				g_currentMission:addHelpButtonText(g_i18n:getText("Laxe_DOWN"), InputBinding.Laxe_DOWN);
end;
		if InputBinding.isPressed(InputBinding.Laxe_DX) then
				g_currentMission:addHelpButtonText(g_i18n:getText("Laxe_DX"), InputBinding.Laxe_DX);
		elseif InputBinding.isPressed(InputBinding.Laxe_SX) then
				g_currentMission:addHelpButtonText(g_i18n:getText("Laxe_SX"), InputBinding.Laxe_SX);
end;
		if InputBinding.isPressed(InputBinding.Baxe_DX) then
				g_currentMission:addHelpButtonText(g_i18n:getText("Baxe_DX"), InputBinding.Baxe_DX);
		elseif InputBinding.isPressed(InputBinding.Baxe_SX) then
				g_currentMission:addHelpButtonText(g_i18n:getText("Baxe_SX"), InputBinding.Baxe_SX);
		end;
	end;
	if self.OpenGT  then
        g_currentMission:addHelpButtonText(g_i18n:getText("CloseToGrain"), InputBinding.OpenToGrain);
		else
        g_currentMission:addHelpButtonText(g_i18n:getText("OpenToGrain"), InputBinding.OpenToGrain);
		end;
		if InputBinding.isPressed(InputBinding.LMORERPM) then
				g_currentMission:addHelpButtonText(g_i18n:getText("LMORERPM"), InputBinding.LMORERPM);
		elseif InputBinding.isPressed(InputBinding.LLESSRPM) then
				g_currentMission:addHelpButtonText(g_i18n:getText("LLESSRPM"), InputBinding.LLESSRPM);
		elseif InputBinding.isPressed(InputBinding.LRESETRPM) then
				g_currentMission:addHelpButtonText(g_i18n:getText("LRESETRPM"), InputBinding.LRESETRPM);
		end;
			if self.EvenMode == 0 then
				g_currentMission:addHelpButtonText(g_i18n:getText("DeciverMode"), InputBinding.DeciverMode);
			elseif self.EvenMode == 1 then
				g_currentMission:addHelpButtonText(g_i18n:getText("DeciverMode1"), InputBinding.DeciverMode);
			elseif self.EvenMode == 2 then 
				g_currentMission:addHelpButtonText(g_i18n:getText("DeciverMode2"), InputBinding.DeciverMode);
			elseif self.EvenMode == 3 then
				g_currentMission:addHelpButtonText(g_i18n:getText("DeciverMode3"), InputBinding.DeciverMode);
			end;
end;

function M400_Advance:updateTick(dt) 

    if self:getIsActive() then	
		if self.isMotorStarted then
			setVisibility(self.DSplan, true);
		else			
			setVisibility(self.DSplan, false);
		end;
	end;
	--switch
	if self.switch[1] ~= nil then
		if self.isMotorStarted then
			setRotation(self.switch[1], math.rad(0), math.rad(-70), math.rad(0));
		else
			setRotation(self.switch[1], math.rad(0), math.rad(0), math.rad(0));
		end;
	end;
	if self.switch[2] ~= nil then
    if self.isThreshing then 
			setRotation(self.switch[2], math.rad(35), math.rad(0), math.rad(0));
		else
			setRotation(self.switch[2], math.rad(0), math.rad(0), math.rad(0));
		end;
	end;
	--ActivLevelLaterale
	if self.ActivLater ~= nil then
	if self.currentTool == M400_Advance.MANUALLEVEL then
			setRotation(self.ActivLater, math.rad(0), math.rad(12), math.rad(-90));
		elseif self.currentTool == M400_Advance.SELFLEVELING  then
			setRotation(self.ActivLater, math.rad(0), math.rad(-12), math.rad(-90));
		else
			setRotation(self.ActivLater, math.rad(0), math.rad(0), math.rad(-90));
		end;
		else
			setRotation(self.ActivLater, math.rad(0), math.rad(0), math.rad(-90));
	end;
	--ActivLevelLaterale
	if self.ActivFront ~= nil then
	if self.selectTool == "FrontLevML" then
			setRotation(self.ActivFront, math.rad(0), math.rad(12), math.rad(-90));
		elseif self.selectTool == "FrontLevAL" then
			setRotation(self.ActivFront, math.rad(0), math.rad(-12), math.rad(-90));
		else
			setRotation(self.ActivFront, math.rad(0), math.rad(0), math.rad(-90));
		end;
		else
			setRotation(self.ActivFront, math.rad(0), math.rad(0), math.rad(-90));
	end;
	if self.levalater ~= nil then
	if self.currentTool == M400_Advance.MANUALLEVEL then
		if InputBinding.isPressed(InputBinding.Laxe_SX) and self:getIsActiveForInput() then
				setRotation(self.levalater, 0,  math.rad(12) , 0);
		elseif InputBinding.isPressed(InputBinding.Laxe_DX) and self:getIsActiveForInput() then
				setRotation(self.levalater, 0,  math.rad(-12) , 0);
		else
			setRotation(self.levalater, 0, math.rad(0) , 0);
			end;
		else
			setRotation(self.levalater, 0, math.rad(0) , 0);
			end;
		end;
	if self.levalongi ~= nil then
	--if self.currentTool == M400_Advance.MANUALLEVEL then
	if self.selectTool == "FrontLevML" then
		if InputBinding.isPressed(InputBinding.Laxe_UP) and self:getIsActiveForInput() then
				setRotation(self.levalongi, 0, math.rad(-12), math.rad(90));
		elseif InputBinding.isPressed(InputBinding.Laxe_DOWN) and self:getIsActiveForInput() then
				setRotation(self.levalongi, 0, math.rad(12), math.rad(90));
		else
			setRotation(self.levalongi, 0, math.rad(0), math.rad(90));
			end;
		else
			setRotation(self.levalongi, 0, math.rad(0), math.rad(90));
		end;
	end;
end;
function M400_Advance:updateFuelIndicators()
	local amountOfFuelPerIndicator = self.fuelCapacity/10;
	local timesToIterate = self.fuelFillLevel/amountOfFuelPerIndicator;
	timesToIterate = math.floor(timesToIterate);
	if self.oldTimesToIterate ~= timesToIterate then
		for i=1, self.numFuelIndicators do
			setVisibility(self.fuelIndicators[i].rotNode, false);
		end;
		for i=1, timesToIterate do
			setVisibility(self.fuelIndicators[i].rotNode, true);
		end;
	end;
	self.oldTimesToIterate = timesToIterate;
end;

function M400_Advance:setHydraulicDirection(index)
	local hydraulic = self.hydraulics[index];

	if hydraulic.fixPoint ~= nil then
		local ax, ay, az = getWorldTranslation(hydraulic.node);
		local bx, by, bz = getWorldTranslation(hydraulic.fixPoint);
		local x, y, z = worldDirectionToLocal(getParent(hydraulic.node), bx-ax, by-ay, bz-az);
		local xUp, yUp, zUp = unpack(hydraulic.upVectors);
		setDirection(hydraulic.node, x, y, z, xUp, yUp, zUp);
		if hydraulic.punch ~= nil then
			local distance = Utils.vector3Length(ax-bx, ay-by, az-bz);
			setTranslation(hydraulic.punch, 0, 0, distance-hydraulic.punchDistance);
		end;
	end;
end;

function M400_Advance:onEnter()
end;


function M400_Advance:onDeactivateSounds()
	if self.hydraulicSoundEnabled then
		stopSample(self.hydraulicSound);
		self.hydraulicSoundEnabled = false;
	end;
	 if self.WarningSoundEnabled then
        stopSample(self.WarningSound);
        WarningSoundEnabled = false;
       end;
end;

function M400_Advance:onDeactivate()
	M400_Advance.onDeactivateSounds(self)
end;

function M400_Advance:onLeave()
	if self.deactivateOnLeave then
		M400_Advance.onDeactivate(self);
	else
		M400_Advance.onDeactivateSounds(self)
	end;
end;
  
function M400_Advance:validateAttacherJoint(implement, jointDesc, dt)
    return true;
end;

function M400_Advance:setCurrentTool(currentTool, noEventSend)
	SetCurrentToolEvent.sendEvent(self, currentTool, noEventSend)
	self.currentTool = currentTool;
end;

--Levels events
SetCurrentToolEvent = {};
SetCurrentToolEvent_mt = Class(SetCurrentToolEvent, Event);

InitEventClass(SetCurrentToolEvent, "SetCurrentToolEvent");

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

function SetCurrentToolEvent:new(vehicle, activeTool)
    local self = SetCurrentToolEvent:emptyNew()
    self.vehicle = vehicle;
	self.activeTool = activeTool;
    return self;
end;

function SetCurrentToolEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
	self.activeTool = streamReadInt8(streamId);
    self.vehicle = networkGetObject(id);
    self:run(connection);
end;

function SetCurrentToolEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
	streamWriteInt8(streamId, self.activeTool);
end;

function SetCurrentToolEvent:run(connection)   
	self.vehicle:setCurrentTool(self.activeTool, true);
    if not connection:getIsServer() then
        g_server:broadcastEvent(SetCurrentToolEvent:new(self.vehicle, self.activeTool), nil, connection, self.vehicle);
    end;
end;

function SetCurrentToolEvent.sendEvent(vehicle, activeTool, noEventSend)
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			g_server:broadcastEvent(SetCurrentToolEvent:new(vehicle, activeTool), nil, nil, vehicle);
		else
			g_client:getServerConnection():sendEvent(SetCurrentToolEvent:new(vehicle, activeTool));
		end;
	end;
end;


-- Monitor events

function M400_Advance:setMonitorTool(MonitorTool, noEventSend)
	SetMonitorToolEvent.sendEvent(self, MonitorTool, noEventSend)
	self.MonitorTool = MonitorTool;
end;

SetMonitorToolEvent = {};
SetMonitorToolEvent_mt = Class(SetMonitorToolEvent, Event);

InitEventClass(SetMonitorToolEvent, "SetMonitorToolEvent");

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

function SetMonitorToolEvent:new(vehicle, activeTool)
    local self = SetMonitorToolEvent:emptyNew()
    self.vehicle = vehicle;
	self.activeTool = activeTool;
    return self;
end;

function SetMonitorToolEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
	self.activeTool = streamReadInt8(streamId);
    self.vehicle = networkGetObject(id);
    self:run(connection);
end;

function SetMonitorToolEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
	streamWriteInt8(streamId, self.activeTool);
end;

function SetMonitorToolEvent:run(connection)   
	self.vehicle:setMonitorTool(self.activeTool, true);
    if not connection:getIsServer() then
        g_server:broadcastEvent(SetMonitorToolEvent:new(self.vehicle, self.activeTool), nil, connection, self.vehicle);
    end;
end;

function SetMonitorToolEvent.sendEvent(vehicle, activeTool, noEventSend)
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			g_server:broadcastEvent(SetMonitorToolEvent:new(vehicle, activeTool), nil, nil, vehicle);
		else
			g_client:getServerConnection():sendEvent(SetMonitorToolEvent:new(vehicle, activeTool));
		end;
	end;
end;

-- Level Front events

function M400_Advance:setSelectTool(selectTool, noEventSend)
	SetSelectToolEvent.sendEvent(self, selectTool, noEventSend)
	self.selectTool = selectTool;
end;

SetSelectToolEvent = {};
SetSelectToolEvent_mt = Class(SetSelectToolEvent, Event);

InitEventClass(SetSelectToolEvent, "SetSelectToolEvent");

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

function SetSelectToolEvent:new(vehicle, activeTool)
    local self = SetSelectToolEvent:emptyNew()
    self.vehicle = vehicle;
	self.activeTool = activeTool;
    return self;
end;

function SetSelectToolEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
	self.activeTool = streamReadInt8(streamId);
    self.vehicle = networkGetObject(id);
    self:run(connection);
end;

function SetSelectToolEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
	streamWriteInt8(streamId, self.activeTool);
end;

function SetSelectToolEvent:run(connection)   
	self.vehicle:setSelectTool(self.activeTool, true);
    if not connection:getIsServer() then
        g_server:broadcastEvent(SetSelectToolEvent:new(self.vehicle, self.activeTool), nil, connection, self.vehicle);
    end;
end;

function SetSelectToolEvent.sendEvent(vehicle, activeTool, noEventSend)
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			g_server:broadcastEvent(SetSelectToolEvent:new(vehicle, activeTool), nil, nil, vehicle);
		else
			g_client:getServerConnection():sendEvent(SetSelectToolEvent:new(vehicle, activeTool));
		end;
	end;
end;
--Anim Part events

function M400_Advance:setModeTool(EvenMode, noEventSend)
	SetEvenModeEvent.sendEvent(self, EvenMode, noEventSend)
	self.EvenMode = EvenMode;
end;

SetEvenModeEvent = {};
SetEvenModeEvent_mt = Class(SetEvenModeEvent, Event);

InitEventClass(SetEvenModeEvent, "SetEvenModeEvent");

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

function SetEvenModeEvent:new(vehicle, activeTool)
    local self = SetEvenModeEvent:emptyNew()
    self.vehicle = vehicle;
	self.activeTool = activeTool;
    return self;
end;

function SetEvenModeEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
	self.activeTool = streamReadInt8(streamId);
    self.vehicle = networkGetObject(id);
    self:run(connection);
end;

function SetEvenModeEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
	streamWriteInt8(streamId, self.activeTool);
end;

function SetEvenModeEvent:run(connection)   
	self.vehicle:setModeTool(self.activeTool, true);
    if not connection:getIsServer() then
        g_server:broadcastEvent(SetEvenModeEvent:new(self.vehicle, self.activeTool), nil, connection, self.vehicle);
    end;
end;

function SetEvenModeEvent.sendEvent(vehicle, activeTool, noEventSend)
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			g_server:broadcastEvent(SetEvenModeEvent:new(vehicle, activeTool), nil, nil, vehicle);
		else
			g_client:getServerConnection():sendEvent(SetEvenModeEvent:new(vehicle, activeTool));
		end;
	end;
end;