--
-- Sipma Z224/1 specialization for FS2013
-- 
-- author:		Burner
-- date:		15.07.2013
-- version: 	v1.2
--

SipmaZ224 = {};

function SipmaZ224.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Baler, specializations);
end;

function SipmaZ224:load(xmlFile)
	self.objectInRange = SipmaZ224.objectInRange;
    self.setIsTurnedOn = SpecializationUtil.callSpecializationsFunction("setIsTurnedOn");
	self.moveBalesOutForTransport = SipmaZ224.moveBalesOutForTransport;
	self.allowPickingUp = Utils.overwrittenFunction(self.allowPickingUp, SipmaZ224.allowPickingUp);

	self.setBackFlap = SpecializationUtil.callSpecializationsFunction("setBackFlap");
	self.resetBaleCounter = SpecializationUtil.callSpecializationsFunction("resetBaleCounter");
	self.setRopePanel = SpecializationUtil.callSpecializationsFunction("setRopePanel");
	self.setHasRopes = SpecializationUtil.callSpecializationsFunction("setHasRopes");
	self.moveBalesOut = SpecializationUtil.callSpecializationsFunction("moveBalesOut");
	self.doMoveBalesOut = SpecializationUtil.callSpecializationsFunction("doMoveBalesOut");
	
	self.setMechanismPanel = SpecializationUtil.callSpecializationsFunction("setMechanismPanel");
	self.setCounterweightPanel = SpecializationUtil.callSpecializationsFunction("setCounterweightPanel");
	self.setBaleTransporterPosition = SpecializationUtil.callSpecializationsFunction("setBaleTransporterPosition");
	self.setBaleTransporterVisibility = SpecializationUtil.callSpecializationsFunction("setBaleTransporterVisibility");
	
	self.baleAnimCurveBackup = self.baleAnimCurve;
	self.firstBaleMarkerBackup = self.firstBaleMarker;

	self.backFlap = true;
	
	local pickupNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.pickupNode#index"));
	if pickupNode ~= nil then
		self.pickupNode = pickupNode;
	end;
	
	local attacherNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.attacherNode#index"));
	if attacherNode ~= nil then
		self.attacherNode = attacherNode;
	end;
	
	local backOptionsNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.backOptionsNode#index"));
	if backOptionsNode ~= nil then
		self.backOptionsNode = backOptionsNode;
	end;
	
	self.pickupWheel = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.pickupWheel#index"));
	self.baleStarNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.baleStar#index"));
	self.baleStarSpeed = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.baleStar#speed"), 1);

	self.strawParticleSystems = {};
	local i=0;
	while true do
		local key = string.format("vehicle.strawParticleSystems.strawParticleSystem(%d)", i);
		local node = getXMLString(xmlFile, key.. "#node");
		if node == nil then
			break;
		end;
		node = Utils.indexToObject(self.components, node);
		if node ~= nil then
			local psFile = getXMLString(xmlFile, key.. "#file");
			local strawParticleSystem = {};
			strawParticleSystem.particleSystem = {};
			local isStatic = Utils.getNoNil(getXMLBool(xmlFile, key.."#static"), false);
			if isStatic then
				StaticParticleSystem.loadParticleSystem(xmlFile, strawParticleSystem.particleSystem, key, self.components, false, nil, self.baseDirectory);
			else
				Utils.loadParticleSystem(xmlFile, strawParticleSystem.particleSystem, key, self.components, false, nil, self.baseDirectory);
			end;
			table.insert(self.strawParticleSystems, strawParticleSystem);
		end;
		i = i+1;
	end;
	self.grassParticleSystems = {};
	local i=0;
	while true do
		local key = string.format("vehicle.grassParticleSystems.grassParticleSystem(%d)", i);
		local node = getXMLString(xmlFile, key.. "#node");
		if node == nil then
			break;
		end;
		node = Utils.indexToObject(self.components, node);
		if node ~= nil then
			local psFile = getXMLString(xmlFile, key.. "#file");
			local grassParticleSystem = {};
			grassParticleSystem.particleSystem = {};
			local isStatic = Utils.getNoNil(getXMLBool(xmlFile, key.."#static"), false);
			if isStatic then
				StaticParticleSystem.loadParticleSystem(xmlFile, grassParticleSystem.particleSystem, key, self.components, false, nil, self.baseDirectory);
			else
				Utils.loadParticleSystem(xmlFile, grassParticleSystem.particleSystem, key, self.components, false, nil, self.baseDirectory);
			end;
			table.insert(self.grassParticleSystems, grassParticleSystem);
		end;
		i = i+1;
	end;
	
	self.soundOffset = 0;
    local balerStopSound = getXMLString(xmlFile, "vehicle.balerStopSound#file");
    if balerStopSound ~= nil and balerStopSound ~= "" then
        balerStopSound = Utils.getFilename(balerStopSound, self.baseDirectory);
        self.balerStopSound = createSample("balerStopSound");
        loadSample(self.balerStopSound, balerStopSound, false);
        self.balerStopSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehiclebalerStopSound#pitchOffset"), 1);
        self.balerStopSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.balerSound#volume"), 1.0);
    end;

    local balerStartSound = getXMLString(xmlFile, "vehicle.balerStartSound#file");
    if balerStartSound ~= nil and balerStartSound ~= "" then
        balerStartSound = Utils.getFilename(balerStartSound, self.baseDirectory);
        self.balerStartSound = createSample("balerStartSound");
        loadSample(self.balerStartSound, balerStartSound, false);
        self.balerStartSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.balerStartSound#pitchOffset"), 1);
        self.balerStartSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.balerStartSound#volume"), 1.0);
    end;
	
	local balerAISound = getXMLString(xmlFile, "vehicle.balerAISound#file");
		if balerAISound ~= nil and balerAISound ~= "" then
		balerAISound = Utils.getFilename(balerAISound, self.baseDirectory);
		self.balerAISoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.balerAISound#pitchOffset"), 0);
		self.balerAISoundRadius = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.balerAISound#radius"), 50);
		self.balerAISoundInnerRadius = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.balerAISound#innerRadius"), 10);
		self.balerAISoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.balerAISound#volume"), 1);
		self.balerAISound = createAudioSource("balerAISound", balerAISound, self.balerAISoundRadius, self.balerAISoundInnerRadius, self.balerAISoundVolume, 0);
		link(self.components[1].node, self.balerAISound);
		setVisibility(self.balerAISound, false);
	end;
	
	self.File = Utils.getFilename("Textures/hud.dds", self.baseDirectory);
	self.hudPoxX = 0.685;
    self.hudPoxY = 1-0.066; 
    self.hudWidth = 0.13325;
    self.hudHeight = 0.0513825;
    self.HUDSipma = Overlay:new("HUDSipma", self.File, self.hudPoxX, self.hudPoxY, self.hudWidth, self.hudHeight);
    self.HUD = false;
	
	self.TotalBalesCount = 0;
	self.CurrentBalesCount = 0;
	self.NoRopesBalesCount = 0;
	self.lastBaleCount = 0;
	
	self.moveBalesOutsideForTransport = false;
	self.doResetBaleCounter = false;
	
	self.ropePanelAnimation = getXMLString(xmlFile, "vehicle.ropePanel#animationName");
	self.mechanismPanelAnimation = getXMLString(xmlFile, "vehicle.mechanismPanel#animationName");
	self.counterweightPanelAnimation = getXMLString(xmlFile, "vehicle.counterweightPanel#animationName");	
	self.ropePanel = true;
	self.mechanismPanel = true;
	self.counterweightPanel = true;
	
	local ropeDoor = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.ropePanel#index"));
	if ropeDoor ~= nil then
		self.ropeDoor = ropeDoor;
	end;
	
	local mechanismDoor = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.mechanismPanel#index"));
	if mechanismDoor ~= nil then
		self.mechanismDoor = mechanismDoor;
	end;
	
	local counterweightDoor = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.counterweightPanel#index"));
	if counterweightDoor ~= nil then
		self.counterweightDoor = counterweightDoor;
	end;
	
	self.ropes = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.ropes#index"));
	self.ropesCapacity = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.ropes#capacity"), 4);
	self.hasRopes = true;
	self.isLoaded = true;
	
	self.moveBalesOutside = true;
	self.doMoveBalesOutside = false;
	self.firstTimeStart = true;
	
	self.lastFillLevel = self.fillLevel;
	self.lastAreaBiggerZero = false;
	
    local firstBaleMarker2 = getXMLFloat(xmlFile, "vehicle.baleTransporterAnimation#firstBaleMarker");
    if firstBaleMarker2 ~= nil then
		local baleAnimCurve2 = AnimCurve:new(linearInterpolatorN);
		local keyI2 = 0;
		while true do
            local key = string.format("vehicle.baleTransporterAnimation.key(%d)", keyI2);
            local t = getXMLFloat(xmlFile, key.."#time");
            local x,y,z = Utils.getVectorFromString(getXMLString(xmlFile, key.."#pos"));
            if x == nil or y == nil or z == nil then
                break;
            end;
            local rx, ry, rz = Utils.getVectorFromString(getXMLString(xmlFile, key.."#rot"));
            rx = math.rad(Utils.getNoNil(rx, 0));
            ry = math.rad(Utils.getNoNil(ry, 0));
            rz = math.rad(Utils.getNoNil(rz, 0));
            baleAnimCurve2:addKeyframe({ v={x, y, z, rx, ry, rz}, time = t});
            keyI2 = keyI2 +1;
        end;
        if keyI2 > 0 then
			self.baleAnimCurve2 = baleAnimCurve2;
            self.firstBaleMarker2 = firstBaleMarker2;
        end;
    end;
	
	self.baleTransporterAnimation = getXMLString(xmlFile, "vehicle.baleTransporter#animationName");	
	
	local baleTransporter = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.baleTransporter#index"));
	if baleTransporter ~= nil then
		self.baleTransporterNode = baleTransporter;
	end;

	self.baleTransporterActive = false;
	self.baleTransporterChainActive = false;
	self.baleTransporterVisibility = false;
	
	self.turnedOnState = self.isTurnedOn;
end;

function SipmaZ224:delete()
	if self.balerStopSound ~= nil then
        delete(self.balerStopSound);
		self.balerStopSound = nil;
    end;
	if self.balerStartSound ~= nil then
        delete(self.balerStartSound);
		self.balerStartSound = nil;
    end;
	for k, strawParticleSystem in pairs(self.strawParticleSystems) do
		Utils.deleteParticleSystem(strawParticleSystem.particleSystem);
	end;
	for k, grassParticleSystem in pairs(self.grassParticleSystems) do
		Utils.deleteParticleSystem(grassParticleSystem.particleSystem);
	end;
	if self.HUDSipma ~= nil then
		self.HUDSipma:delete();
	end
end;

function SipmaZ224:readStream(streamId, connection)
	self:setBackFlap(streamReadBool(streamId), true);
	self:resetBaleCounter(streamReadBool(streamId), true);

    self.TotalBalesCount = streamReadInt32(streamId);
    self.NoRopesBalesCount = streamReadInt32(streamId);
    self.CurrentBalesCount = streamReadInt32(streamId);
	
	self:setCounterweightPanel(streamReadBool(streamId), true);
    self:setMechanismPanel(streamReadBool(streamId), true);
	self:setRopePanel(streamReadBool(streamId), true);
    self:setHasRopes(streamReadBool(streamId), true);
	
    self:setBaleTransporterPosition(streamReadBool(streamId), true);
	self:setBaleTransporterVisibility(streamReadBool(streamId), true);
end;

function SipmaZ224:writeStream(streamId, connection)
	streamWriteBool(streamId, self.backFlap);
	streamWriteBool(streamId, self.doResetBaleCounter);

    streamWriteInt32(streamId, self.TotalBalesCount);
    streamWriteInt32(streamId, self.NoRopesBalesCount);
    streamWriteInt32(streamId, self.CurrentBalesCount);
	
	streamWriteBool(streamId, self.counterweightPanel);
    streamWriteBool(streamId, self.mechanismPanel);
	streamWriteBool(streamId, self.ropePanel);
    streamWriteBool(streamId, self.isLoaded);
	
	streamWriteBool(streamId, self.baleTransporterActive);
	streamWriteBool(streamId, self.baleTransporterVisibility);
end;

function SipmaZ224:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	local numBales = Utils.getNoNil(getXMLInt(xmlFile, key.."#numBales"),0);
	local TotalBalesCount = Utils.getNoNil(getXMLInt(xmlFile, key.."#totalBalesCount"),0);
	local NoRopesBalesCount = Utils.getNoNil(getXMLInt(xmlFile, key.."#noRopesBalesCount"),0);
	self.lastBaleCount = numBales;
	self.TotalBalesCount = TotalBalesCount;
	self.NoRopesBalesCount = NoRopesBalesCount;
	
	if not resetVehicles then
		if self.animationParts[6].isLoading and self.animationParts[6].inputTime > self.animationParts[6].startPosition or self.animationParts[6].currentPosition > 0 then
			self:setBackFlap(true);
		end;
		baleTransporterState = Utils.getNoNil(getXMLInt(xmlFile, key.."#baleTransporterState"),0);
		if baleTransporterState == 0 then
			self:setBaleTransporterVisibility(false);
		elseif baleTransporterState == 1 then
			self:setBaleTransporterVisibility(true);
		elseif baleTransporterState == 2 then
			self:setBaleTransporterVisibility(true);
			self:setBaleTransporterPosition(true);
		end;
	end;
	return BaseMission.VEHICLE_LOAD_OK;
end

function SipmaZ224:getSaveAttributesAndNodes(nodeIdent)
	if self.baleTransporterVisibility then
		if self.baleTransporterActive then
			baleTransporterState = 2;
		else
			baleTransporterState = 1;
		end;
	else
		baleTransporterState = 0;
	end;
	local TotalBalesCount = Utils.getNoNil(self.TotalBalesCount, 0);
	local NoRopesBalesCount = Utils.getNoNil(self.NoRopesBalesCount, 0);
	local attributes = 'totalBalesCount="'..string.format("%d",TotalBalesCount)..'" noRopesBalesCount="'..string.format("%d",NoRopesBalesCount)..'" baleTransporterState="'.. tostring(baleTransporterState) ..'"';
	return attributes, nodes;
end

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

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

function SipmaZ224:update(dt)
	if self.firstTimeStart then
		self.firstTimeStart = false;
	end;
	
	if self.animationParts[6].currentPosition == 0 then
		self.isTurnedOn = false;
	end;
	
	if self.isClient and not self:getIsActiveForInput(false) then
		if self:objectInRange(self.pickupNode) then
			if InputBinding.hasEvent(InputBinding.SIPMAZ224_LOWER_PICKUP) then
				if self.animationParts[4].clipEndTime then
					self:setAnimationTime(4, self.animationParts[4].startPosition);
				else
					self:setAnimationTime(4, self.animationParts[4].animDuration);
				end;
			end;
			if self.animationParts[4].clipEndTime then
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("SIPMAZ224_PICKUP_LIFT"), self.typeDesc), InputBinding.SIPMAZ224_LOWER_PICKUP);
			else
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("SIPMAZ224_PICKUP_LOWER"), self.typeDesc), InputBinding.SIPMAZ224_LOWER_PICKUP);
			end;
		end;
		if self:objectInRange(self.attacherNode) then
			if self.isTurnedOn == false then
				if InputBinding.hasEvent(InputBinding.SIPMAZ224_WORK_MODE) then
					if self.animationParts[5].clipEndTime then
						self:setAnimationTime(5, self.animationParts[5].startPosition);
					else
						self:setAnimationTime(5, self.animationParts[5].animDuration);
					end;
				end;
			end;
			if self.isTurnedOn then
				g_currentMission:addExtraPrintText(g_i18n:getText("SIPMAZ224_TURNOFF_TO_SET_TRANSPORT_MODE"));
			else
				if self.animationParts[5].clipEndTime then
					g_currentMission:addHelpButtonText(string.format(g_i18n:getText("SIPMAZ224_TRANSPORT_ON"), self.typeDesc), InputBinding.SIPMAZ224_WORK_MODE);
				else
					g_currentMission:addHelpButtonText(string.format(g_i18n:getText("SIPMAZ224_TRANSPORT_OFF"), self.typeDesc), InputBinding.SIPMAZ224_WORK_MODE);
				end;
			end;
		end;
		if self:objectInRange(self.backOptionsNode) then
			if self.baleTransporterActive == false then
				if InputBinding.hasEvent(InputBinding.SIPMAZ224_LOWER_PICKUP) then
					self:setBackFlap(not self.backFlap);
				end;
			end;
			local numAttachedTrailers = table.getn(self.attachedImplements);
			if numAttachedTrailers == 0 then
				if InputBinding.hasEvent(InputBinding.SIPMAZ224_ATTACHER_SLIDE) then
					if self.animationParts[7].clipEndTime then
						self:setAnimationTime(7, self.animationParts[7].startPosition);
					else
						self:setAnimationTime(7, self.animationParts[7].animDuration);
					end;
				end;
				if self.animationParts[7].clipEndTime then
				end;
			else
				g_currentMission:addExtraPrintText(g_i18n:getText("SIPMAZ224_DETACH_TRAILER_TO_OPERATE_BACK_ATTACHER"));
			end;
			
			if self.animationParts[6].clipEndTime then 
				local baleCountInBaler = table.getn(self.bales);
				if baleCountInBaler > 1 then
					g_currentMission:addHelpButtonText(g_i18n:getText("SIPMAZ224_REMOVE_BALES"), InputBinding.SIPMAZ224_MOVE_BALES);
					if InputBinding.hasEvent(InputBinding.SIPMAZ224_MOVE_BALES) then
						self:doMoveBalesOut(true);
					end;

					if InputBinding.hasEvent(InputBinding.SIPMAZ224_MOUNT_BALE_TRANSPORTER) then
						self:setBaleTransporterVisibility(not self.baleTransporterVisibility);
					end;
					if self.baleTransporterVisibility then
						g_currentMission:addHelpButtonText(string.format(g_i18n:getText("SIPMAZ224_BALETRANSPORTER_UNMOUNT"), self.typeDesc), InputBinding.SIPMAZ224_MOUNT_BALE_TRANSPORTER);
						if InputBinding.hasEvent(InputBinding.SIPMAZ224_LOWER_BALE_TRANSPORTER) then
							self:setBaleTransporterPosition(not self.baleTransporterActive);
						end;
						if self.baleTransporterActive then
						end;
					else
					end;
				end;
			else
				g_currentMission:addExtraPrintText(g_i18n:getText("SIPMAZ224_LOWER_FLAP_TO_OPERATE_BALETRANSPORTER"));
			end;
		end;
		if self:objectInRange(self.ropeDoor) then
			if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA3) then
				self:setRopePanel(not self.ropePanel);
			end;
			if not self.isLoaded then
				if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA2) then
					self:setHasRopes(true);
				end;
			end;
			if self.ropePanel then
			else
				if not self.isLoaded then
				end;
			end;
		end;
		if self:objectInRange(self.mechanismDoor) then
			if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA3) then
				self:setMechanismPanel(not self.mechanismPanel);
			end;
			if self.mechanismPanel then
			end;
		end;
		if self:objectInRange(self.counterweightDoor) then
			if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA3) then
				self:setCounterweightPanel(not self.counterweightPanel);
			end;
			if self.counterweightPanel then
			end;
		end;
	end;
	
	if self:getIsActiveForInput() then	
		if InputBinding.hasEvent(InputBinding.SIPMAZ224_HUD_ON) then
			self.HUD = not self.HUD;
		end;
		if InputBinding.hasEvent(InputBinding.SIPMAZ224_RESET_BALECOUNTER) then
			self:resetBaleCounter(true);
		end;
	end;
	
	if self.isServer then
		if self.NoRopesBalesCount >= self.ropesCapacity then
			self:setHasRopes(false);
		end;
	end;
end;

function SipmaZ224:allowPickingUp(superFunc, area)
	return self.isTurnedOn and self.animationParts[4].clipEndTime and self.animationParts[6].clipEndTime;
end;

function SipmaZ224:updateTick(dt)
	self.lastAreaBiggerZero = (self.lastFillLevel ~= self.fillLevel);
	
	if self.attacherVehicle ~= nil then
		self:setAnimationTime(3, self.animationParts[3].animDuration);
	else
		self:setAnimationTime(3, self.animationParts[3].startPosition);
	end;

	if self:getIsActive() then
		if self.animationParts[4].clipEndTime then
			rotate(self.pickupWheel, 2.5 * self.lastSpeedReal * self.movingDirection * dt ,0,0);
		end;
		if self.isTurnedOn then
			if self.CurrentBalesCount ~= 0 then
				if self.CurrentBalesCount % 2 == 0 then
					self:setAnimationTime(1, self.animationParts[1].startPosition, false);
				else
					self:setAnimationTime(1, self.animationParts[1].animDuration, false);
				end;
			end;
			
			if self:getIsActiveForSound() then		
				if self.time > self.soundOffset then
					if not self.balerSoundEnabled then
						playSample(self.balerSound, 0, self.balerSoundVolume, 0);
						self.balerSoundEnabled = true;
					end;
				else
					stopSample(self.balerSound);
					self.balerSoundEnabled = false;
				end;
			end;
		end;
	end;

	if self.backFlap == false then
		if self.moveBalesOutsideForTransport then
			self:setAnimationTime(6, self.animationParts[6].startPosition);
		else
			self:moveBalesOutForTransport(dt, self);
		end;
	else
		self:setAnimationTime(6, self.animationParts[6].animDuration);
		self.moveBalesOutsideForTransport = false;
	end;
	
	if self.doResetBaleCounter then
		self.TotalBalesCount = 0;
		self.doResetBaleCounter = false;
	end;
	
	if self.isTurnedOn and not self:getIsActiveForSound() then
		if self.balerAISound ~= nil then
			setVisibility(self.balerAISound, true);
		end;
	else
		if self.balerAISound ~= nil then
			setVisibility(self.balerAISound, false);
		end;		
	end;
	
	if self:getIsActive() then
		if self.isTurnedOn then
			if self.currentFillType == Fillable.FILLTYPE_GRASS_WINDROW or self.currentFillType == Fillable.FILLTYPE_DRYGRASS_WINDROW then
				for k, grassParticleSystem in pairs(self.grassParticleSystems) do
					Utils.setEmittingState(grassParticleSystem.particleSystem, self.lastAreaBiggerZero);
				end;
			else
				for k, strawParticleSystem in pairs(self.strawParticleSystems) do
					Utils.setEmittingState(strawParticleSystem.particleSystem, self.lastAreaBiggerZero);
				end;
			end;
		else
			for k, strawParticleSystem in pairs(self.strawParticleSystems) do
				Utils.setEmittingState(strawParticleSystem.particleSystem, false);
			end;
			for k, grassParticleSystem in pairs(self.grassParticleSystems) do
				Utils.setEmittingState(grassParticleSystem.particleSystem, false);
			end;
		end;
		
		local baleCountInBaler = table.getn(self.bales);
		if self.lastAreaBiggerZero and self.isTurnedOn and baleCountInBaler > 0 and self.baleStarNode ~= nil then
			rotate(self.baleStarNode, self.baleStarSpeed * self.lastSpeedReal * dt ,0,0);
		end;
		
		if self.isClient then
			if not self.isTurnedOn and self.balerSoundEnabled then
				stopSample(self.balerSound);
				self.balerSoundEnabled = false;
			end;
		end;

	end;
	
	if self.isTurnedOn then
		self:setAnimationTime(2, 1);
	else
		self:setAnimationTime(2, 0);
	end;
	
	setVisibility(self.baleTransporterNode, self.baleTransporterVisibility);

	if self.moveBalesOutside == false then
		self:moveBalesOut(dt, self);
	end;
	
	if self.doMoveBalesOutside then
		self:moveBalesOut(dt, self);
		self.doMoveBalesOutside = false;
	end;
	
	if table.getn(self.bales) > self.lastBaleCount then
		self.TotalBalesCount = self.TotalBalesCount + 1;
		self.NoRopesBalesCount = self.NoRopesBalesCount + 1;
		self.CurrentBalesCount = self.CurrentBalesCount + 1;
		self.lastBaleCount = self.lastBaleCount + 1;
	elseif table.getn(self.bales) < self.lastBaleCount then
		self.lastBaleCount = self.lastBaleCount - 1;
	end;
	
	self.lastFillLevel = self.fillLevel;
end;

function SipmaZ224:draw()
	if self.isClient then
		if self.animationParts[6].clipEndTime == false then
			g_currentMission:addExtraPrintText(g_i18n:getText("SIPMAZ224_LOWER_FLAP_TO_TURNON"));
		end;
		
		if self.HUD then
			self.HUDSipma:render();
			g_currentMission:addHelpButtonText(string.format(g_i18n:getText("SIPMAZ224_HUD_OFF"), self.typeDesc), InputBinding.SIPMAZ224_HUD_ON);
			setTextBold(true);
			totalBalesCountString = string.format("%d", self.TotalBalesCount);
			renderText(0.72, 0.951, 0.02, string.format(totalBalesCountString));
		else
			g_currentMission:addHelpButtonText(string.format(g_i18n:getText("SIPMAZ224_HUD_ON"), self.typeDesc), InputBinding.SIPMAZ224_HUD_ON);	
		end;
		g_currentMission:addHelpButtonText(string.format(g_i18n:getText("SIPMAZ224_RESET_COUNTER"), self.typeDesc), InputBinding.SIPMAZ224_RESET_BALECOUNTER);	
		if not self.isLoaded then
			g_currentMission:addWarning(g_i18n:getText("SIPMAZ224_NOROPE") .. "\n" .. g_i18n:getText("SIPMAZ224_NOROPE_WARNING"), 0.07+0.022, 0.019+0.029);	
		end;		
	end;
end;

function SipmaZ224:onDetach()
	if self.deactivateOnDetach then
		SipmaZ224.onDeactivate(self);
	end;
	
	self.turnedOnState = false;
	
	for k, strawParticleSystem in pairs(self.strawParticleSystems) do
		Utils.setEmittingState(strawParticleSystem.particleSystem, false);
	end;
	for k, grassParticleSystem in pairs(self.grassParticleSystems) do
		Utils.setEmittingState(grassParticleSystem.particleSystem, false);
	end;
	if self.balerStartSound ~= nil then
		stopSample(self.balerStartSound);
	end;
	if self.balerStopSound ~= nil then
		stopSample(self.balerStopSound);
	end;
end;

function SipmaZ224:onLeave()
	if self.deactivateOnLeave then
		SipmaZ224.onDeactivate(self);
	else
		SipmaZ224.onDeactivateSounds(self);
	end;

	for k, strawParticleSystem in pairs(self.strawParticleSystems) do
		Utils.setEmittingState(strawParticleSystem.particleSystem, false);
	end;
	for k, grassParticleSystem in pairs(self.grassParticleSystems) do
		Utils.setEmittingState(grassParticleSystem.particleSystem, false);
	end;
end;

function SipmaZ224:onDeactivate()
	SipmaZ224.onDeactivateSounds(self)
	if self.turnedOnState and self.attacherVehicle ~= nil then
		self.isTurnedOn = true;
		for _, part in pairs(self.balerUVScrollParts) do
			setShaderParameter(part.node, "uvScrollSpeed", part.speed[1], part.speed[2], 0, 0, false);
		end;
	end;
	for k, strawParticleSystem in pairs(self.strawParticleSystems) do
		Utils.setEmittingState(strawParticleSystem.particleSystem, false);
	end;
	for k, grassParticleSystem in pairs(self.grassParticleSystems) do
		Utils.setEmittingState(grassParticleSystem.particleSystem, false);
	end;
end;

function SipmaZ224:onDeactivateSounds()
	if self.balerStartSound ~= nil then
		stopSample(self.balerStartSound);
	end;
	if self.balerStopSound ~= nil then
		stopSample(self.balerStopSound);
	end;
end;

function SipmaZ224:setIsTurnedOn(isTurnedOn, noEventSend)
	self.turnedOnState = isTurnedOn;
	local soundOffset = 0;
	if not isTurnedOn then
		if self.balerAISound ~= nil then
			setVisibility(self.balerAISound, false);
		end;
		if self:getIsActive() then
			if self:getIsActiveForSound() then	
				if self.time < self.soundOffset then
					stopSample(self.balerStartSound);
				else
					if self.balerStopSound ~= nil then
						playSample(self.balerStopSound, 1, self.balerStopSoundVolume, 0);
						soundOffset = getSampleDuration(self.balerStopSound);
					end;
				end;
			end;
		end;
	else
		if self:getIsActive() then
			if self:getIsActiveForSound() and self.backFlap then					
				self.balerSoundEnabled = false;
				stopSample(self.balerSound);
				
				if self.time < self.soundOffset then
					stopSample(self.balerStopSound);
				end;
				playSample(self.balerStartSound, 1, self.balerStartSoundVolume, 0);
				soundOffset = getSampleDuration(self.balerStartSound);		
			end;
		end;
	end;
	self.soundOffset = self.time + soundOffset;
end;

function SipmaZ224:moveBalesOutForTransport(dt, self)
	local done = true;
	for k, bale in pairs(self.bales) do
		if bale.time > 0.5 then
			local sendTime = math.min(1, bale.time+dt/5000);
			self.setBaleTime(self, k, sendTime, true);
			done = false;
		end;
	end;
	self.moveBalesOutsideForTransport = done;
	return;
end;

function SipmaZ224:setBackFlap(isBackFlap, noEventSend)
	SetBackFlapEvent.sendEvent(self, isBackFlap, noEventSend);
	self.backFlap = isBackFlap;
	if self.backFlap == false then
		self:setIsTurnedOn(false);
	end;
end;

function SipmaZ224:resetBaleCounter(resetBaleCounter,noEventSend)
	ResetBaleCounterEvent.sendEvent(self, resetBaleCounter, noEventSend);
	self.doResetBaleCounter = resetBaleCounter;	
end;

function SipmaZ224:setRopePanel(isRopePanel,noEventSend)
	SetRopePanelEvent.sendEvent(self, isRopePanel, noEventSend);
	if isRopePanel then
		if self.ropePanelAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.ropePanelAnimation, -1, nil, true);
			self.ropePanel = true;
		end;
	else
		if self.ropePanelAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.ropePanelAnimation, 1, nil, true);
			self.ropePanel = false;
		end;
	end;
end;

function SipmaZ224:setMechanismPanel(isMechanismPanel,noEventSend)
	SetMechanismPanelEvent.sendEvent(self, isMechanismPanel, noEventSend);
	if isMechanismPanel then
		if self.mechanismPanelAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.mechanismPanelAnimation, -1, nil, true);
			self.mechanismPanel = true;
		end;
	else
		if self.mechanismPanelAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.mechanismPanelAnimation, 1, nil, true);
			self.mechanismPanel = false;
		end;
	end;
end;

function SipmaZ224:setCounterweightPanel(isCounterweightPanel,noEventSend)
	SetCounterweightPanelEvent.sendEvent(self, isCounterweightPanel, noEventSend);
	if isCounterweightPanel then
		if self.counterweightPanelAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.counterweightPanelAnimation, -1, nil, true);
			self.counterweightPanel = true;
		end;
	else
		if self.counterweightPanelAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.counterweightPanelAnimation, 1, nil, true);
			self.counterweightPanel = false;
		end;
	end;
end;

function SipmaZ224:setHasRopes(isLoaded,noEventSend)
	SetHasRopesEvent.sendEvent(self, isLoaded, noEventSend);
	self.isLoaded = isLoaded;
	if self.isLoaded then
		self.NoRopesBalesCount = 0;
		setVisibility(self.ropes, true);
	else
		setVisibility(self.ropes, false);	
		if self.isTurnedOn then
			self:setIsTurnedOn(false);
		end;
	end;
end;

function SipmaZ224:setBaleTransporterPosition(baleTransporterActive,noEventSend)
	SetBaleTransporterPositionEvent.sendEvent(self, baleTransporterActive, noEventSend);
	self.baleTransporterActive = baleTransporterActive;
	if baleTransporterActive then
		if self.baleTransporterAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.baleTransporterAnimation, 1, nil, true);
		end;
	else
		if self.baleTransporterAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.baleTransporterAnimation, -1, nil, true);
		end;
	end;
	if baleTransporterActive then
		self.baleAnimCurve = self.baleAnimCurve2
		self.firstBaleMarker = self.firstBaleMarker2;
	else
		self.baleAnimCurve = self.baleAnimCurveBackup;
		self.firstBaleMarker = self.firstBaleMarkerBackup;
	end;
	self:moveBales(0);
end;

function SipmaZ224:setBaleTransporterVisibility(baleTransporterVisibility,noEventSend)
	SetBaleTransporterVisibilityEvent.sendEvent(self, baleTransporterVisibility, noEventSend);
	self.baleTransporterVisibility = baleTransporterVisibility;
	if self.baleTransporterActive and self.firstTimeStart == false then
		self:setBaleTransporterPosition(false);
	end;
end;

function SipmaZ224:moveBalesOut(dt, self)
	local done = true;
	for k, bale in pairs(self.bales) do
		if bale.time > 0.15 then
			local sendTime = math.min(1, bale.time+dt/5000);
			self.setBaleTime(self, k, sendTime, true);
			done = false;
		end;
	end;
	self.moveBalesOutside = done;
	return;
end;

function SipmaZ224:doMoveBalesOut(moveBales, noEventSend)
	MoveBalesOutEvent.sendEvent(self, moveBales, noEventSend);
	self.doMoveBalesOutside = moveBales;
end;

function SipmaZ224:objectInRange(object)
	if g_currentMission.player ~= nil and object ~= nil then
		local nearestDistance = 1.5;
		local vx, vy, vz = getWorldTranslation(g_currentMission.player.rootNode);
		local px, py, pz = getWorldTranslation(object); 
		local distance = Utils.vector3Length(px-vx, py-vy, pz-vz);	
		if distance < nearestDistance then
			return true;
		else
			return false;
		end;
	else
		return false;
	end;
end;