  --
  -- Ferg_Baler
  -- Class for all Ferg_Balers
  --
 -- @author  Stefan Geiger
  -- @date  10/09/08
  --
  -- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.

  
Ferg_Baler = {};
function Ferg_Baler.prerequisitesPresent(specializations)
      return SpecializationUtil.hasSpecialization(Fillable, specializations) and SpecializationUtil.hasSpecialization(ImplementLinks, specializations) and SpecializationUtil.hasSpecialization(Baler, specializations);
end;
  
function Ferg_Baler:load(xmlFile)

	  self.setTransRot = SpecializationUtil.callSpecializationsFunction("setTransRot");
	  self.TransRotAnimation = getXMLString(xmlFile, "vehicle.TransRot#animationName");
	  self.TransRot = false;
	  self.setRotatePickup = SpecializationUtil.callSpecializationsFunction("setRotatePickup");
	  self.RotatePickupAnimation = getXMLString(xmlFile, "vehicle.RotatePickup#animationName");
	  self.RotatePickup = false;
	  self.setArmOne = SpecializationUtil.callSpecializationsFunction("setArmOne");
	  self.ArmOneAnimation = getXMLString(xmlFile, "vehicle.armOne#animationName");
	  self.ArmOne = false;	
	  self.emptyBaler = SpecializationUtil.callSpecializationsFunction("emptyBaler");
	  self.bEmptyBaler = false;	
	  
	  self.getIsAreaActive = Utils.overwrittenFunction(self.getIsAreaActive, Ferg_Baler.getIsAreaActive);	

 	  self.setVehicleRpmUp = SpecializationUtil.callSpecializationsFunction("setVehicleRpmUp");
	  self.saveMinRpm = 0; 
	  
	  self.strawParticleSystems = {};
      local i = 0;
      while true do
        local namei = string.format("vehicle.strawParticleSystems.strawParticleSystems(%d)", i);
		local nodei = Utils.indexToObject(self.components, getXMLString(xmlFile, namei .. "#index"));
		if nodei == nil then
			break;
		end; 
        Utils.loadParticleSystem(xmlFile, self.strawParticleSystems, namei, nodei, false, nil, self.baseDirectory)		
		i = i +1;		
      end;
	  
	  self.grassParticleSystems = {};
      local i = 0;
      while true do
        local namei = string.format("vehicle.grassParticleSystems.grassParticleSystems(%d)", i);
		local nodei = Utils.indexToObject(self.components, getXMLString(xmlFile, namei .. "#index"));
		if nodei == nil then
			break;
		end; 
        Utils.loadParticleSystem(xmlFile, self.grassParticleSystems, namei, nodei, false, nil, self.baseDirectory)		
		i = i +1;		
      end;	  
	  
	self.drumNode1 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.drum#index"));
    self.drumRotationScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.drum#rotationScale"), 1);
	self.taildoor = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.taildoor#index"));	
	self.pickup = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.pickup#index"));	

	local rotationPartNodePacker = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.Packer#index"));
    if rotationPartNodePacker ~= nil then
        self.rotationPartPacker = {};
        self.rotationPartPacker.node = rotationPartNodePacker;

        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.rotationPartPacker#minRot"));
        self.rotationPartPacker.minRot = {};
        self.rotationPartPacker.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartPacker.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartPacker.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.Packer#maxRot"));
        self.rotationPartPacker.maxRot = {};
        self.rotationPartPacker.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartPacker.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartPacker.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        self.rotationPartPacker.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.Packer#rotTime"), 2)*1000;
        self.rotationPartPacker.touchRotLimit = Utils.degToRad(Utils.getNoNil(getXMLString(xmlFile, "vehicle.Packer#touchRotLimit"), 10));
    end
 
	local rotationPartNodePacker2 = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.Packer2#index"));
    if rotationPartNodePacker2 ~= nil then
        self.rotationPartPacker2 = {};
        self.rotationPartPacker2.node = rotationPartNodePacker2;

        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.rotationPartPacker2#minRot"));
        self.rotationPartPacker2.minRot = {};
        self.rotationPartPacker2.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartPacker2.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartPacker2.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.Packer2#maxRot"));
        self.rotationPartPacker2.maxRot = {};
        self.rotationPartPacker2.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartPacker2.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartPacker2.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        self.rotationPartPacker2.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.Packer2#rotTime"), 2)*1000;
        self.rotationPartPacker2.touchRotLimit = Utils.degToRad(Utils.getNoNil(getXMLString(xmlFile, "vehicle.Packer2#touchRotLimit"), 10));
    end
	
	local rotationPartNodePacker3 = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.Packer3#index"));
    if rotationPartNodePacker3 ~= nil then
        self.rotationPartPacker3 = {};
        self.rotationPartPacker3.node = rotationPartNodePacker3;

        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.rotationPartPacker3#minRot"));
        self.rotationPartPacker3.minRot = {};
        self.rotationPartPacker3.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartPacker3.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartPacker3.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.Packer3#maxRot"));
        self.rotationPartPacker3.maxRot = {};
        self.rotationPartPacker3.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartPacker3.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartPacker3.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        self.rotationPartPacker3.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.Packer3#rotTime"), 2)*1000;
        self.rotationPartPacker3.touchRotLimit = Utils.degToRad(Utils.getNoNil(getXMLString(xmlFile, "vehicle.Packer3#touchRotLimit"), 10));
    end
	
	self.Packer = false;
	self.test = 300;
	
	self.isTurnedOn = false;	
    self.bales = {};
	
	self.speedRotatingParts = {};
     local i=0;
     while true do
          local baseName = string.format("vehicle.speedRotatingParts.speedRotatingPart(%d)", i);
          local index = getXMLString(xmlFile, baseName.. "#index");
          if index == nil then
              break;
          end;
          local node = Utils.indexToObject(self.components, index);
          if node ~= nil then
              local entry = {};
              entry.node = node;
              entry.rotationSpeedScale = getXMLFloat(xmlFile, baseName.."#rotationSpeedScale");
              if entry.rotationSpeedScale == nil then
                  entry.rotationSpeedScale = 1.0/Utils.getNoNil(getXMLFloat(xmlFile, baseName.."#radius"), 1);
              end;
  
  
              table.insert(self.speedRotatingParts, entry);
          end;
          i = i+1;
      end;
	  
	self.rotateSpinners = {};
	local i=0;
	while true do
		local baseName = string.format("vehicle.rotateSpinners.node(%d)", i);
		local index = getXMLString(xmlFile, baseName.. "#index");
		local x,y,z = Utils.getVectorFromString(getXMLString(xmlFile, baseName.. "#rotationSpeed"));
		local rotationSpeed = {x,y,z};
		local runOutTime = Utils.getNoNil(getXMLFloat(xmlFile, baseName.. "#runOutTime"), 2)*1000;
		if index == nil or rotationSpeed == nil or runOutTime == nil then
			break;
		end;
		local node = Utils.indexToObject(self.components, index);
		if node ~= nil then
			local entry = {};
			entry.node = node;
			entry.runOutTime = runOutTime;
			entry.rotationSpeedMax = rotationSpeed;
			entry.rotationSpeedMin = {0,0,0};
			entry.rotationSpeedCurrent = {0,0,0};
			table.insert(self.rotateSpinners, entry);
		end;
		i = i+1;
	end;	
	  
	  self.isAttached = false;	
      self.printWarningTime = 0;
      self.printWarningTime1 = 0;
	  self.previousLevel = 0;	
	  self.currentFruitType = FruitUtil.FRUITTYPE_UNKNOWN; 
end;

function Ferg_Baler:delete()

 	if self.grassParticleSystems ~= nil then
		Utils.setEmittingState(self.grassParticleSystems, false);
	end;
 	if self.strawParticleSystems ~= nil then
		Utils.setEmittingState(self.strawParticleSystems, false);
	end;	
end;
  
function Ferg_Baler:readStream(streamId, connection)
 	self.bEmptyBaler = streamReadBool(streamId); 
    self:setTransRot(streamReadBool(streamId), true);
    self:setRotatePickup(streamReadBool(streamId), true);
    self:setArmOne(streamReadBool(streamId), true);
end;

 
function Ferg_Baler:writeStream(streamId, connection)
	streamWriteBool(streamId, self.bEmptyBaler);
    streamWriteBool(streamId, self.TransRot);
    streamWriteBool(streamId, self.RotatePickup);
	streamWriteBool(streamId, self.ArmOne);
end;

function Ferg_Baler:readUpdateStream(streamId, timestamp, connection)
	if connection:getIsServer() then

	end;
  
end;
  
function Ferg_Baler:writeUpdateStream(streamId, connection, dirtyMask)
  	if not connection:getIsServer() then

	end;
end;

function Ferg_Baler:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
    if not resetVehicles then
		if self.TransRotAnimation ~= nil then
			local isTransRotOn = getXMLBool(xmlFile, key.."#isTransRotOn");
			if isTransRotOn ~= nil then
				self:setTransRot(isTransRotOn, true);
				if self.playAnimation ~= nil then
					AnimatedVehicle.updateAnimationByName(self, self.TransRotAnimation, 99999999);
					if self.updateCylinderedInitial ~= nil then
						self:updateCylinderedInitial();
					end
				end
			end;
		end;
		if self.RotatePickupAnimation ~= nil then
			local isRotatePickupOn = getXMLBool(xmlFile, key.."#isRotatePickupOn");
			if isRotatePickupOn ~= nil then
				self:setRotatePickup(isRotatePickupOn, true);
				if self.playAnimation ~= nil then
					AnimatedVehicle.updateAnimationByName(self, self.RotatePickupAnimation, 99999999);
					if self.updateCylinderedInitial ~= nil then
						self:updateCylinderedInitial();
					end
				end
			end;
		end;	
		if self.ArmOneAnimation ~= nil then
			local isArmOneOn = getXMLBool(xmlFile, key.."#isArmOneOn");
			if isArmOneOn ~= nil then
				self:setArmOne(isArmOneOn, true);
				if self.playAnimation ~= nil then
					AnimatedVehicle.updateAnimationByName(self, self.ArmOneAnimation, 99999999);
					if self.updateCylinderedInitial ~= nil then
						self:updateCylinderedInitial();
					end
				end
			end;
		end;		
		self.bEmptyBaler = getXMLBool(xmlFile, key.."#EmptyBaler");
    end
  
    return BaseMission.VEHICLE_LOAD_OK;
end;
  
function Ferg_Baler:getSaveAttributesAndNodes(nodeIdent)
	local attributes = '';
	local mystring = 'EmptyBaler="'.. tostring(self.bEmptyBaler) .. '"';
	attributes = attributes .. mystring;
	local mystring = ' isTransRotOn="' .. tostring(self.isTransRotOn) ..'"';	
	attributes = attributes .. mystring;
	local mystring = ' isRotatePickupOn="' .. tostring(self.isRotatePickupOn) ..'"';	
	attributes = attributes .. mystring;	
	local mystring = ' isArmOneOn="' .. tostring(self.isArmOneOn) ..'"';	
	attributes = attributes .. mystring;
	
    local node = nil;
	return attributes, node;
end;
  
function Ferg_Baler:mouseEvent(posX, posY, isDown, isUp, button)
end;
  
function Ferg_Baler:keyEvent(unicode, sym, modifier, isDown)
end;
  
function Ferg_Baler:update(dt)
	if not self:getIsActive() then
 		if self.taildoorInRange then		
			if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA2) then
				self:setArmOne(not self.isArmOneOn);
			end;	
			if self.isArmOneOn then
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("raise_taildoor"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA2);
			else
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("lower_taildoor"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA2);
			end;
		end; 
 		if self.pickupInRange then		
			if InputBinding.hasEvent(InputBinding.LOWER_IMPLEMENT) then
				self:setRotatePickup(not self.isRotatePickupOn);
			end;
			if self.isRotatePickupOn then
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("RAISE_PICKUP"), self.typeDesc), InputBinding.LOWER_IMPLEMENT);
			else
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("LOWER_PICKUP"), self.typeDesc), InputBinding.LOWER_IMPLEMENT);
			end;
		end; 		
	end;
      if self:getIsActiveForInput() then  
        if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA2) then
            self:setTransRot(not self.isTransRotOn);
         end;
		if InputBinding.isPressed(InputBinding.IMPLEMENT_EXTRA) and self.PTOId then
			self.printWarningTime = self.time + 1200;
		end;
      end;
   
end;
  
function Ferg_Baler:updateTick(dt)

	if g_currentMission.player ~= nil then
		local nearestDistance = 1.5;
		local x1,y1,z1 = getWorldTranslation(self.taildoor);
		local x2,y2,z2 = getWorldTranslation(g_currentMission.player.rootNode);
		local distance = Utils.vector3Length(x1-x2,y1-y2,z1-z2);
		if distance < nearestDistance then
			self.taildoorInRange = true; 
		else
			self.taildoorInRange = false; 
		end;
		local x3,y3,z3 = getWorldTranslation(self.pickup);
		local distance = Utils.vector3Length(x3-x2,y3-y2,z3-z2);
		if distance < nearestDistance then
			self.pickupInRange = true; 
		else
			self.pickupInRange = false; 
		end;
	end;
      self.wasToFast = false;
      if self:getIsActive() then
		if self.fillLevel > 0 and not self.isTransRotOn then
			-- self:emptyBaler(not self.bEmptyBaler);
			self.bEmptyBaler = true;	
		else
			self.bEmptyBaler = false;			
		end;	  
		if not self.attacherVehicle.isMotorStarted then
			self.isTurnedOn = false;
		end;
		if self.PTOId then
			self.isTurnedOn = false;
		end;
		local isKeyEvent = false;	
		if self.isTurnedOn then
 			isKeyEvent = true;	
		else
 			isKeyEvent = false;	
		end;
		self:setVehicleRpmUp(dt, isKeyEvent);	
          if not self.isTransRotOn then
				self.isTurnedOn = false;
          end;
          if self.isTransRotOn and not self.isArmOneOn then
				self.isTurnedOn = false;
          end;
		self.lastArea = 0;		  
         if self.isTurnedOn then
		 	-- self.currentFruitType = FruitUtil.fillTypeToFruitType[fillType];
			if self.drumNode1 ~= nil and self.previousLevel ~= self.fillLevel and self.movingDirection ~= 0 then
				rotate(self.drumNode1, self.drumRotationScale * -2 * 1, 0, 0);
				if FruitUtil.fillTypeToFruitType[self.currentFillType] == FruitUtil.FRUITTYPE_GRASS or FruitUtil.fillTypeToFruitType[self.currentFillType] == FruitUtil.FRUITTYPE_DRYGRASS then 
					Utils.setEmittingState(self.grassParticleSystems, true);
					Utils.setEmittingState(self.strawParticleSystems, false);						
				elseif FruitUtil.fillTypeToFruitType[self.currentFillType] == FruitUtil.FRUITTYPE_BARLEY or FruitUtil.fillTypeToFruitType[self.currentFillType] == FruitUtil.FRUITTYPE_WHEAT then
					Utils.setEmittingState(self.grassParticleSystems, false);
					Utils.setEmittingState(self.strawParticleSystems, true);					
				end
				self.previousLevel = self.fillLevel;
			else
				Utils.setEmittingState(self.strawParticleSystems, false);	
				Utils.setEmittingState(self.grassParticleSystems, false);				
			end;
 			self.test = self.test - dt;
			if self.test < 0 then
				self.rotationMaxPacker = not self.rotationMaxPacker;
				self.test = 300;
			end;
			if self.fillLevel > 100 then
				self.rotationMaxPacker3 = true;
			else
				self.rotationMaxPacker3 = false;
			end;
		end;
			if self.rotationPartPacker ~= nil then
				local x, y, z = getRotation(self.rotationPartPacker.node);
				local rot = {x,y,z};
				local newRot = Utils.getMovedLimitedValues(rot, self.rotationPartPacker.maxRot, self.rotationPartPacker.minRot, 3, self.rotationPartPacker.rotTime, dt, not self.rotationMaxPacker);
				setRotation(self.rotationPartPacker.node, unpack(newRot));
			end	
			if self.rotationPartPacker2 ~= nil then
				local x, y, z = getRotation(self.rotationPartPacker2.node);
				local rot = {x,y,z};
				local newRot = Utils.getMovedLimitedValues(rot, self.rotationPartPacker2.maxRot, self.rotationPartPacker2.minRot, 3, self.rotationPartPacker2.rotTime, dt, not self.rotationMaxPacker2);
				setRotation(self.rotationPartPacker2.node, unpack(newRot));
			end		
			if self.rotationPartPacker3 ~= nil then
				local x, y, z = getRotation(self.rotationPartPacker3.node);
				local rot = {x,y,z};
				local newRot = Utils.getMovedLimitedValues(rot, self.rotationPartPacker3.maxRot, self.rotationPartPacker3.minRot, 3, self.rotationPartPacker3.rotTime, dt, not self.rotationMaxPacker3);
				setRotation(self.rotationPartPacker3.node, unpack(newRot));
			end	
			
			for k, spinner in pairs(self.rotateSpinners) do
				local values = Utils.getMovedLimitedValues(spinner.rotationSpeedCurrent, spinner.rotationSpeedMax, spinner.rotationSpeedMin, 3, spinner.runOutTime, dt, not self.isTurnedOn);
				spinner.rotationSpeedCurrent = values;
				rotate(spinner.node, unpack(spinner.rotationSpeedCurrent));
			end;

		if self.isServer then
        if self.bEmptyBaler then		
			if self.isServer then
				if self.time > self.baleLastPositionTime+100 then
					for i=1, table.getn(self.bales) do
						local bale = self.bales[i];
						bale.lastX, bale.lastY, bale.lastZ = getWorldTranslation(bale.id);
					end;
					self.baleLastPositionTime = self.time;
				end;
			end;		
		
			local done = true;
			for k=table.getn(self.bales), 1, -1 do
				local bale = self.bales[k];
				if bale.time > 0.4 then
					local sendTime = math.min(1.0, bale.time+(dt/10000));
					
					if self.baleAnimCurve ~= nil then
						local bale = self.bales[k];
						bale.time = sendTime;
						local v = self.baleAnimCurve:get(bale.time);
						setTranslation(bale.id, v[1], v[2], v[3]);
						setRotation(bale.id, v[4], v[5], v[6]);
						if bale.time >= 1 then
							local deltaRealTime = (self.time - self.baleLastPositionTime)/1000;
							if self.time == self.baleLastPositionTime then
								deltaRealTime = 1;
							end;
							local x,y,z = getWorldTranslation(bale.id);
							local rx,ry,rz = getWorldRotation(bale.id);
								local baleObject = Bale:new(self.isServer, self.isClient);
								baleObject:load(bale.filename, x,y,z,rx,ry,rz, bale.fillLevel);
								baleObject:register();

								local lx, ly, lz = bale.lastX, bale.lastY, bale.lastZ;
								setLinearVelocity(baleObject.nodeId, (x-lx)/deltaRealTime, (y-ly)/deltaRealTime, (z-lz)/deltaRealTime);
							delete(bale.id);
							table.remove(self.bales, k);

							-- increase bale count if variable exists (baling mission)
							if g_currentMission.baleCount ~= nil then
								g_currentMission.baleCount = g_currentMission.baleCount + 1;
							end;
							if self.CurrentFergBalesCount ~= nil and self.TotalFergBalesCount ~= nil then
								self.CurrentFergBalesCount = self.CurrentFergBalesCount +1;
								self.TotalFergBalesCount = self.TotalFergBalesCount +1;
							end;												
						end;
						
						if self.isServer then
							if noEventSend == nil or not noEventSend then
								g_server:broadcastEvent(BalerSetBaleTimeEvent:new(self, k, bale.time), nil, nil, self);
							end;
						end;
						
					end;		
					
					done = false;
				end;
			end; 
        end;		
        end;			
		if not self.isTransRotOn then
			self.dropBales = true;	
		end;
		
		if self.isTransRotOn then
			self.dropBales = false;			
		end;
		for i, jointDesc in pairs(self.componentJoints) do
		   setJointFrame(self.componentJoints[i].jointIndex, 0, self.componentJoints[i].jointNode);
		end;    
	end;
end;
  
function Ferg_Baler:draw()
      if self.isClient and self.attacherVehicle.isMotorStarted then

        if self.isTransRotOn then
            g_currentMission:addHelpButtonText(string.format(g_i18n:getText("TRANSPORT"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA2);
        else
            g_currentMission:addHelpButtonText(string.format(g_i18n:getText("FIELD"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA2);
        end;
		if not self.isTransRotOn and InputBinding.isPressed(InputBinding.IMPLEMENT_EXTRA) then
			g_currentMission:addWarning(g_i18n:getText("fieldError"), 0.018, 0.033);
		end;
		if self.isTransRotOn then
			if not self.isArmOneOn and InputBinding.isPressed(InputBinding.IMPLEMENT_EXTRA) then
				g_currentMission:addWarning(g_i18n:getText("taildoorError"), 0.018, 0.033);
			end;	
		end;
		if self.printWarningTime > self.time and self.isTransRotOn then
			g_currentMission:addWarning(g_i18n:getText("turnON_Error"), 0.018, 0.033);
		end;
      end;
end;
  
function Ferg_Baler:onDetach()
      if self.deactivateOnDetach then
          Ferg_Baler.onDeactivate(self);
      else

      end;
	for k, steerable in pairs(g_currentMission.steerables) do
		if self.attacherVehicleCopy == steerable then
			steerable.motor.minRpm = self.saveMinRpm;
			self.attacherVehicleCopy = nil;
		end;
		self.currentFruitType = FruitUtil.FRUITTYPE_UNKNOWN;	
	end;
	
end;
  
function Ferg_Baler:onLeave()
      if self.deactivateOnLeave then
          Ferg_Baler.onDeactivate(self);
      else

      end;
	if self.strawParticleSystems ~= nil then
		Utils.setEmittingState(self.strawParticleSystems, false);
	end; 
	if self.grassParticleSystems ~= nil then
		Utils.setEmittingState(self.grassParticleSystems, false);
	end;	
	self.currentFruitType = FruitUtil.FRUITTYPE_UNKNOWN;
end;

function Ferg_Baler:onAttach(attacherVehicle)
	self.currentFruitType = FruitUtil.FRUITTYPE_UNKNOWN;
	self.attacherVehicle = attacherVehicle;
	if self.attacherVehicleCopy == nil then
		self.attacherVehicleCopy = self.attacherVehicle;
	end;
	self.saveMinRpm = self.attacherVehicle.motor.minRpm;
end; 
  
function Ferg_Baler:onDeactivate()

      self.isTurnedOn = false;
      Ferg_Baler.onDeactivateSounds(self)
 	if self.strawParticleSystems ~= nil then
		Utils.setEmittingState(self.strawParticleSystems, false);
	end;
 	if self.grassParticleSystems ~= nil then
		Utils.setEmittingState(self.grassParticleSystems, false);
	end;	
end;
  
function Ferg_Baler:onDeactivateSounds()

end;

function Ferg_Baler:getIsAreaActive(superFunc, area)
    if superFunc ~= nil then
			return superFunc(self, area) and self.isRotatePickupOn;
    end;
	return self.isRotatePickupOn;	
end;

function Ferg_Baler:setTransRot(isTransRot,noEventSend)
	SetTransRotEvent.sendEvent(self, isTransRot, noEventSend);
	-- Play TransRot animation --
	self.isTransRotOn = isTransRot;
	if self.isTransRotOn then
		if self.TransRotAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.TransRotAnimation, 1, nil, true);
			self.TransRot = true;
		end;
	else
		if self.TransRotAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.TransRotAnimation, -1, nil, true);
			self.TransRot = false;
		end;
	end;	
end;

function Ferg_Baler:setRotatePickup(isRotatePickup,noEventSend)
	SetRotatePickupEvent.sendEvent(self, isRotatePickup, noEventSend);
	-- Play RotatePickup animation --
	self.isRotatePickupOn = isRotatePickup;
	if self.isRotatePickupOn then
		if self.RotatePickupAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.RotatePickupAnimation, 1, nil, true);
			self.RotatePickup = true;
		end;
	else
		if self.RotatePickupAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.RotatePickupAnimation, -1, nil, true);
			self.RotatePickup = false;
		end;
	end;	
end;

function Ferg_Baler:setArmOne(isArmOne,noEventSend)
	SetArmOneEvent.sendEvent(self, isArmOne, noEventSend);
	-- Play ArmOne animation --
	self.isArmOneOn = isArmOne;
	if self.isArmOneOn then
		if self.ArmOneAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.ArmOneAnimation, 1, nil, true);
			self.ArmOne = true;
		end;
	else
		if self.ArmOneAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.ArmOneAnimation, -1, nil, true);
			self.ArmOne = false;
		end;
	end;	
end;

function Ferg_Baler:validateAttacherJoint(implement, jointDesc, dt)
        return true;
end;

function Ferg_Baler:setVehicleRpmUp(dt, isActive)
	if self.attacherVehicle ~= nil and self.saveMinRpm ~= 0 then
		if dt ~= nil then
			if isActive == true then
				self.attacherVehicle.motor.minRpm = math.max(self.attacherVehicle.motor.minRpm-dt, -1000);
			else
				self.attacherVehicle.motor.minRpm = math.min(self.attacherVehicle.motor.minRpm+dt*2, self.saveMinRpm);
			end;
		else
			self.attacherVehicle.motor.minRpm = self.saveMinRpm;
		end;
		if self.attacherVehicle.isMotorStarted then
			local fuelUsed = 0.000000011*math.abs(self.attacherVehicle.motor.minRpm);
			self.attacherVehicle:setFuelFillLevel(self.attacherVehicle.fuelFillLevel-fuelUsed);
			g_currentMission.missionStats.fuelUsageTotal = g_currentMission.missionStats.fuelUsageTotal + fuelUsed;
			g_currentMission.missionStats.fuelUsageSession = g_currentMission.missionStats.fuelUsageSession + fuelUsed;
		end;
	end;
end;

function Ferg_Baler:emptyBaler(state, noEventSend)	
	SetEmptyBalerEvent.sendEvent(self, state, noEventSend);
	self.bEmptyBaler = state;
end;

SetEmptyBalerEvent = {};
SetEmptyBalerEvent_mt = Class(SetEmptyBalerEvent, Event);

InitEventClass(SetEmptyBalerEvent, "SetEmptyBalerEvent");

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

function SetEmptyBalerEvent:new(vehicle, state)
    local self = SetEmptyBalerEvent:emptyNew()
    self.vehicle = vehicle;
	self.state = state;
	return self;
end;

function SetEmptyBalerEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
    self.vehicle = networkGetObject(id);
	self.state = streamReadFloat32(streamId);
    self:run(connection);
end;

function SetEmptyBalerEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));	
	streamWriteFloat32(streamId, self.state);
end;

function SetEmptyBalerEvent:run(connection)
	self.vehicle:emptyBaler(self.state, true);
	if not connection:getIsServer() then
		g_server:broadcastEvent(SetEmptyBalerEvent:new(self.vehicle, self.state), nil, connection, self.vehicle);
	end;
end;

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

SetTransRotEvent = {};
SetTransRotEvent_mt = Class(SetTransRotEvent, Event);

InitEventClass(SetTransRotEvent, "SetTransRotEvent");

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

function SetTransRotEvent:new(vehicle, isTransRot)
    local self = SetTransRotEvent:emptyNew()
    self.vehicle = vehicle;
	self.isTransRot = isTransRot;
    return self;
end;

function SetTransRotEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
	self.isTransRot = streamReadBool(streamId);
    self.vehicle = networkGetObject(id);
    self:run(connection);
end;

function SetTransRotEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
	streamWriteBool(streamId, self.isTransRot);
end;

function SetTransRotEvent:run(connection)   
	self.vehicle:setTransRot(self.isTransRot, true);
    if not connection:getIsServer() then
        g_server:broadcastEvent(SetTransRotEvent:new(self.vehicle, self.isTransRot), nil, connection, self.vehicle);
    end;
end;

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

SetRotatePickupEvent = {};
SetRotatePickupEvent_mt = Class(SetRotatePickupEvent, Event);

InitEventClass(SetRotatePickupEvent, "SetRotatePickupEvent");

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

function SetRotatePickupEvent:new(vehicle, isRotatePickup)
    local self = SetRotatePickupEvent:emptyNew()
    self.vehicle = vehicle;
	self.isRotatePickup = isRotatePickup;
    return self;
end;

function SetRotatePickupEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
	self.isRotatePickup = streamReadBool(streamId);
    self.vehicle = networkGetObject(id);
    self:run(connection);
end;

function SetRotatePickupEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
	streamWriteBool(streamId, self.isRotatePickup);
end;

function SetRotatePickupEvent:run(connection)   
	self.vehicle:setRotatePickup(self.isRotatePickup, true);
    if not connection:getIsServer() then
        g_server:broadcastEvent(SetRotatePickupEvent:new(self.vehicle, self.isRotatePickup), nil, connection, self.vehicle);
    end;
end;

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


SetArmOneEvent = {};
SetArmOneEvent_mt = Class(SetArmOneEvent, Event);

InitEventClass(SetArmOneEvent, "SetArmOneEvent");

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

function SetArmOneEvent:new(vehicle, isArmOne)
    local self = SetArmOneEvent:emptyNew()
    self.vehicle = vehicle;
	self.isArmOne = isArmOne;
    return self;
end;

function SetArmOneEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
	self.isArmOne = streamReadBool(streamId);
    self.vehicle = networkGetObject(id);
    self:run(connection);
end;

function SetArmOneEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
	streamWriteBool(streamId, self.isArmOne);
end;

function SetArmOneEvent:run(connection)   
	self.vehicle:setArmOne(self.isArmOne, true);
    if not connection:getIsServer() then
        g_server:broadcastEvent(SetArmOneEvent:new(self.vehicle, self.isArmOne), nil, connection, self.vehicle);
    end;
end;

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