-- Skrypt: ZG
-- Wersja: 1.0
--31.10.2009
-- Autor: hannibal5 (na podstawie dostepnych skrytow)

---LOG---
-------------------------------------
--Wersja: 1.0 (31.10.2009)
-----Wykrywanie kontaktu z podlozem
-----Ustawianie maszyny przy podejsciu farmerem
-----Tryb transportu, zgrabiania, przetrzasania
-----Czasteczki
-----Dzwiek
-------------------------------------

ZG = {};
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ZG.MODE_TRANSPORT = 1; --Maszyna w pozycji transportowej								Machine in transport position
ZG.MODE_ZGRABIANIE = 2; --Maszyna w pozycji zgrabiania									The machine is in raking position
ZG.MODE_PRZETRZASANIE = 3; --Maszyna w pozycji przetrzasania							The machine is in position tedding
ZG.MODE_ODWRACANIE_POKOSOW = 4 --Maszyna w pozycji do odwracania pokosow				The machine is in position to reverse the cuts
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ZG.ODW_TRANSPORT = 5; --Aktywna animacja: zgrabianie <-> transport 						Active Loop Raking- Transport
ZG.ODW_PRZETRZASANIE = 6; --Aktywna animacja: zgrabianie <-> przetrzasanie				Active Loop: raking <-> tedding
ZG.ODW_ODWRACANIE_POKOSOW = 7; --Aktywna animacja: zgrabianie <-> odracanie pokosow		Active Loop: raking <-> reverse cuts
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

function ZG.prerequisitesPresent(specializations)

    return true;
	
end;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function ZG:load(xmlFile)

	self.farmerInRange = SpecializationUtil.callSpecializationsFunction("farmerInRange"); --Funkcja sprawdzajaca czy farmer jest w poblizu maszyny
	self.groundContactReport = SpecializationUtil.callSpecializationsFunction("groundContactReport"); --Funkcja sprawdzajaca kontak z ziemia
	
	-----Ustawienia startowe masy-----Aby odczepiona maszyna byla stabilna-----
	setMass(self.components[1].node, 0.5);
	setMass(self.components[2].node, 5);
	setMass(self.components[3].node, 5);
	setMass(self.components[4].node, 5);
	-----Ustawienia startowe masy-----Aby odczepiona maszyna byla stabilna-----
	
	-----Dane dla czesci obracajacych sie (gwiazdy)-----
    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;	
	-----Dane dla czesci obracajacych sie (gwiazdy)-----
	
	-----Dane dla elementow pobierajacych informacje o kontakcie z ziemia-----	
	self.contactReportNodes = {};
    local contactReportNodeFound = false;
    local i = 0;
    while true do
        local baseName = string.format("vehicle.contactReportNodes.contactReportNode(%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.hasGroundContact = false;

            self.contactReportNodes[node] = entry;
            contactReportNodeFound = true;
        end;
        i = i + 1;
    end;
    if not contactReportNodeFound then
        local entry = {};
        entry.node = self.components[1].node;
        entry.hasGroundContact = false;
        self.contactReportNodes[entry.node] = entry;
    end;

    self.groundReferenceThreshold = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.groundReferenceNode#threshold"), 0.2);
    self.groundReferenceNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.groundReferenceNode#index"));
	-----Dane dla elementow pobierajacych informacje o kontakcie z ziemia-----
	
	-----Dane dla aktualizacji obszaru po przejechaniu maszyny-----
	local numzgDropAreas = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.zgDropAreas#count"), 0);
	self.zgDropAreas = {}
    for i=1, numzgDropAreas do
        self.zgDropAreas[i] = {};
        local areanamei = string.format("vehicle.zgDropAreas.zgDropArea%d", i);
        self.zgDropAreas[i].start = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#startIndex"));
        self.zgDropAreas[i].width = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#widthIndex"));
        self.zgDropAreas[i].height = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#heightIndex"));
    end;
	-----Dane dla aktualizacji obszaru po przejechaniu maszyny-----
	
	-----Dane dla czasteczek-----
    self.grassParticleSystems = {};
    local i = 0;
    while true do
        local baseName = string.format("vehicle.grassParticleSystems.grassParticleSystem(%d)", i);

        local particleSystem = {};
        particleSystem.ps = {};
        local ps = Utils.loadParticleSystem(xmlFile, particleSystem.ps, baseName, self.components, false, nil, self.baseDirectory)
        if ps == nil then
            break;
        end;
        particleSystem.disableTime = 0;
        table.insert(self.grassParticleSystems, particleSystem);
        i = i + 1;
		self.psEnabled = false;
    end;
	-----Dane dla czasteczek-----
	
	-----Dane dla dzwięku-----
	local zgSound = getXMLString(xmlFile, "vehicle.zgSound#file");
    if zgSound ~= nil and zgSound ~= "" then
        zgSound = Utils.getFilename(zgSound, self.baseDirectory);
        self.zgSound = createSample("zgSound");
        self.zgSoundEnabled = false;
        loadSample(self.zgSound, zgSound, false);
        self.zgSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.zgSound#pitchOffset"), 1);
        self.zgSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.zgSound#volume"), 1.0);
    end;
	-----Dane dla dzwięku-----

    self.ZGContactReportsActive = false; --Aktywacja kontaktu z ziemia
	self.wasToFast = false; --Dla wyswietlenia informacji o limicie predkosci
	self.speedMaxTimer = 1500; --Czas jaki ma farmer na zwolnienie po wyswietleniu komunikaru o przekroczeniu predkosci
	self.speedTimer = self.speedMaxTimer; --Odlicza czas po pokazeniu komunikatu o przekroczeniu predkosci
	
	self.farmerNear = false; --Znacznik czy farmer jest w poblizu maszyny (zastosowany w ZGCol.lua)
	self.mode = ZG.MODE_ZGRABIANIE; --Pozycja startowa - zgrabianie
	self.activeMode = ZG.ODW_TRANSPORT; --Znacznik, ustala ktora animacja ma byc aktywna (zastosowany w ZGCol.lua)
	
	self.keyType = InputBinding.getButtonKeyName; --Odwolanie do klawiszy
	self.keyName = "Klawisz"; --Okreslenie dla przycisku

end;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function ZG:delete()

    ZG.removeContactReports(self);
	
	for k,v in pairs(self.grassParticleSystems) do
        Utils.deleteParticleSystem(v.ps);
    end;
	
	if self.zgSound ~= nil then
        delete(self.zgSound);
    end;

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

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

end;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function ZG:draw()

    if self.wasToFast then
		g_currentMission:addWarning(g_i18n:getText("Dont_drive_to_fast") .. "\n" .. string.format(g_i18n:getText("Cruise_control_levelN"), "2", InputBinding.getKeyNamesOfDigitalAction(InputBinding.SPEED_LEVEL2)), 0.07+0.022, 0.019+0.029);
	end;

end;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function ZG:update(dt)

	self.wasToFast = false;
--------------------------------------------------------------------------------------------------------
--------------------USTAWIENIE ZACZEPU I KONTAKTU Z ZIEMIA-----------------

	if self.attacherVehicle then
		-----Ustawienie maszyny po podczepieniu-----
		if self.fixAttacher then
			local implement = self.attacherVehicle:getImplementByObject(self);
			if implement ~= nil then
				local joint = self.attacherVehicle.attacherJoints[implement.jointDescIndex];
				self.saveJoint = self.attacherVehicle.attacherJoints[implement.jointDescIndex];
				self.maxRotJoint = joint.maxRotLimit;
				self.attacherJointIndex = implement.jointDescIndex;
				self.rotationCopy  = joint.minRot;
				joint.minRot = {Utils.degToRad(25),0,0}; --Obrót przy podniesionej maszynie			
				joint.maxRotLimit = self.maxRotJoint; --Obrót przy opuszczonej maszynie
				setJointRotationLimit(joint.jointIndex, 2, true, 0, 0);
			end;
			self.fixAttacher = false;
		end;
		-----Ustawienie maszyny po podczepieniu-----
		
		-----Odwolanie do funkcji sprawdzajacej odleglosc maszyny od farmera-----
		self:farmerInRange();	
		-----Odwolanie do funkcji sprawdzajacej odleglosc maszyny od farmera-----
	end;
	
	if self:getIsActive() then
		-----Sprawdzenie danych dla kontaktu z ziemia-----
        local hasGroundContact = false;
        for k, v in pairs(self.contactReportNodes) do
            if v.hasGroundContact then
                hasGroundContact = true;
                break;
            end;
        end;

        if not hasGroundContact then
            if self.groundReferenceNode ~= nil then
                local x,y,z = getWorldTranslation(self.groundReferenceNode);
                local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 0, z);
                if terrainHeight + self.groundReferenceThreshold >= y then
                    hasGroundContact = true;
                end;
            end;
        end;
		-----Sprawdzenie danych dla kontaktu z ziemia-----
		
--------------------USTAWIENIE ZACZEPU I KONTAKTU Z ZIEMIA-----------------
--------------------------------------------------------------------------------------------------------
	
-----------------------------------------------------------------	
--------------------KONTAKT Z ZIEMIA-----------------

		if hasGroundContact then
			
			-----Zgrabianie trawy-----
			if self.mode == ZG.MODE_ZGRABIANIE then --Zgrabianie
				local fruitTypeFix = false;
			
				local cuttingArea = self.cuttingAreas[1];
				local x,y,z = getWorldTranslation(cuttingArea.start);
                local x1,y1,z1 = getWorldTranslation(cuttingArea.width);
                local x2,y2,z2 = getWorldTranslation(cuttingArea.height);
				
				local ratio = g_currentMission.windrowCutLongRatio;
				
				if not fruitTypeFix then
                    fruitType = FruitUtil.FRUITTYPE_GRASS;
                end;
				
				local area = Utils.updateFruitCutLongArea(fruitType, x, z, x1, z1, x2, z2, 0)/ratio;
                area = area + Utils.updateFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2, 0);
                if area == 0 and not fruitTypeFix then
                    fruitType = FruitUtil.FRUITTYPE_DRYGRASS;
                    area = Utils.updateFruitCutLongArea(fruitType, x, z, x1, z1, x2, z2, 0)/ratio;
                    area = area + Utils.updateFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2, 0);
                end;
				
				if area > 0 then
					fruitTypeFix = true;
					
                    local dropArea = self.zgDropAreas[1];
                    local x,y,z = getWorldTranslation(dropArea.start);
                    local x1,y1,z1 = getWorldTranslation(dropArea.width);
                    local x2,y2,z2 = getWorldTranslation(dropArea.height);
                    local old, total = Utils.getFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2);
					
					area = area + old;
					
                    local value = area / total;
                    if value < 1 and value > 0.08 then
                        value = 1;
                    else
                        value = math.floor(value + 0.6);					
                    end;
                    if value >= 1 then
                        value = math.min(value, g_currentMission.maxWindrowValue);
                        Utils.updateFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2, value, true, false);
						self.psEnabled = true; --Zalaczenie czasteczek
                    end;
				elseif area <= 0 then
					self.psEnabled = false; --Wylaczenie czasteczek
                end;
			end;
			-----Zgrabianie trawy-----
			
			-----Odwracanie pokosow-----
			if self.mode == ZG.MODE_ODWRACANIE_POKOSOW then --Odwracanie pokosow
			
				local fruitTypeFix = false;
				
				for i = 3, 4 do
					local cuttingArea = self.cuttingAreas[i];
					local x,y,z = getWorldTranslation(cuttingArea.start);
					local x1,y1,z1 = getWorldTranslation(cuttingArea.width);
					local x2,y2,z2 = getWorldTranslation(cuttingArea.height);
				
					local ratio = g_currentMission.windrowCutLongRatio;
				
					if not fruitTypeFix then
						fruitType = FruitUtil.FRUITTYPE_GRASS;
					end;
				
					local area = Utils.updateFruitCutLongArea(fruitType, x, z, x1, z1, x2, z2, 0)/ratio;
					area = area + Utils.updateFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2, 0);
					if area == 0 and not fruitTypeFix then
						fruitType = FruitUtil.FRUITTYPE_DRYGRASS;
						area = Utils.updateFruitCutLongArea(fruitType, x, z, x1, z1, x2, z2, 0)/ratio;
						area = area + Utils.updateFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2, 0);
					end;
				
					if area > 0 then
						fruitTypeFix = true;
					
						local dropArea = self.zgDropAreas[i];
						local x,y,z = getWorldTranslation(dropArea.start);
						local x1,y1,z1 = getWorldTranslation(dropArea.width);
						local x2,y2,z2 = getWorldTranslation(dropArea.height);
						local old, total = Utils.getFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2);
					
						area = area + old;
					
						local value = area / total;
						if value < 1 and value > 0.08 then
							value = 1;
						else
							value = math.floor(value + 0.6);					
						end;
						if value >= 1 then
							value = math.min(value, g_currentMission.maxWindrowValue);
							Utils.updateFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2, value, true, false);
							self.psEnabled = true; --Zalaczenie czasteczek
						end;
					elseif area <= 0 then
						self.psEnabled = false; --Wylaczenie czasteczek
					end;
				end;
			end;
			-----Odwracanie pokosow-----			
			
			-----Przetrzasanie trawy-----
			if self.mode == ZG.MODE_PRZETRZASANIE then --Przetrzasanie
				local cuttingArea = self.cuttingAreas[2];
                local x,y,z = getWorldTranslation(cuttingArea.start);
                local x1,y1,z1 = getWorldTranslation(cuttingArea.width);
                local x2,y2,z2 = getWorldTranslation(cuttingArea.height);

                local ratio = g_currentMission.windrowCutLongRatio;
				
				local area = Utils.updateFruitCutLongArea(FruitUtil.FRUITTYPE_GRASS, x, z, x1, z1, x2, z2, 0);
                area = area + Utils.updateFruitCutLongArea(FruitUtil.FRUITTYPE_DRYGRASS, x, z, x1, z1, x2, z2, 0);
                area = area + Utils.updateFruitWindrowArea(FruitUtil.FRUITTYPE_GRASS, x, z, x1, z1, x2, z2, 0)*ratio;
                area = area + Utils.updateFruitWindrowArea(FruitUtil.FRUITTYPE_DRYGRASS, x, z, x1, z1, x2, z2, 0)*ratio;
				
				if area > 0 then
                    local dropArea = self.zgDropAreas[2];
                    local x,y,z = getWorldTranslation(dropArea.start);
                    local x1,y1,z1 = getWorldTranslation(dropArea.width);
                    local x2,y2,z2 = getWorldTranslation(dropArea.height);
                    local old, total = Utils.getFruitCutLongArea(FruitUtil.FRUITTYPE_DRYGRASS, x, z, x1, z1, x2, z2);
					
                    area = area + old;
					
                    local value = area / total;
                    if value < 1 and value > 0.1 then
                        value = 1;
                    else
                        value = math.floor(value + 0.6);
                    end;
					if value >= 1 then
                        value = math.min(value, g_currentMission.maxCutLongValue);
                        Utils.updateFruitCutLongArea(FruitUtil.FRUITTYPE_DRYGRASS, x, z, x1, z1, x2, z2, value, true, false);
						self.psEnabled = true; --Zalaczenie czasteczek
                    end;
				elseif area <= 0 then
					self.psEnabled = false; --Wylaczenie czasteczek
				end;
			end;
			-----Przetrzasanie trawy-----
			
			if self.mode ~= ZG.MODE_TRANSPORT then --Wszystkie ustawienia mszyny poza pozycja transportowa
				-----Obrot gwiazd-----
				for k,v in pairs(self.speedRotatingParts) do
					rotate(v.node, 0, 0, v.rotationSpeedScale * self.lastSpeedReal * self.movingDirection * dt);
				end;
				-----Obrot gwiazd-----
				
				-----Aktywacja czasteczek-----
				if self.psEnabled and self.lastSpeed * 3600 > 5 then
					for k,v in pairs(self.grassParticleSystems) do
						Utils.setEmittingState(v.ps, true);
					end;
				end;
				-----Aktywacja czasteczek-----
				
				-----Aktywacja dzwieku-----
				if not self.zgSoundEnabled and self.lastSpeed * 3600 > 5 then
					playSample(self.zgSound, 0, self.zgSoundVolume, 0);
					setSamplePitch(self.zgSound, self.zgSoundPitchOffset);
					self.zgSoundEnabled = true;
				end;
				-----Aktywacja dzwieku-----
			end;
			
			-----Odlaczenie maszyny po przekroczeniu limitu predkosci-----
			local toFast = self:doCheckSpeedLimit() and self.lastSpeed * 3600 > 25;
			self.wasToFast = toFast;
			
			if self.wasToFast then
				self.speedTimer = self.speedTimer - dt;
				if self.speedTimer < 0 then				
					if self.attacherVehicle then	
						self.attacherVehicle:detachImplementByObject(self);
					end;
				end;
			else
				self.speedTimer = self.speedMaxTimer;
			end;
			-----Odlaczenie maszyny po przekroczeniu limitu predkosci-----				
		end;
			
--------------------KONTAKT Z ZIEMIA-----------------
-----------------------------------------------------------------

---------------------------------------------------------------------------
--------------------BRAK KONTAKTU Z ZIEMIA-----------------
		
		-----Deaktywacja czasteczek-----
		if not hasGroundContact or not self.psEnabled or self.lastSpeed * 3600 < 5 then
			for k,v in pairs(self.grassParticleSystems) do
				Utils.setEmittingState(v.ps, false);
			end;
		end;
		-----Deaktywacja czasteczek-----
		
		-----Deaktywacja dzwieku-----
		if not hasGroundContact or self.lastSpeed * 3600 < 5 then
			if self.zgSoundEnabled then
				stopSample(self.zgSound);
				self.zgSoundEnabled = false;
			end;
		end;
		-----Deaktywacja dzwieku-----	
	end;

--------------------BRAK KONTAKTU Z ZIEMIA-----------------
---------------------------------------------------------------------------
	
end;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function ZG:farmerInRange(dt)

    local nearestDistance = 4.0; --MAX odleglosc farmera od maszyny, aby funkcjazwrocila wartosc true
	
	local px, py, pz = getWorldTranslation(self.rootNode); --Pozycja maszyny
	local vx, vy, vz = getWorldTranslation(g_currentMission.player.rootNode); --Pozycja farmera
	local distance = Utils.vector3Length(px-vx, py-vy, pz-vz); --Odleglosc maszyny od farmera
	
	if distance < nearestDistance then
		self.farmerNear = true;
		-----Zmiana pozycji z transportowej na zgrabianie-----
		if self.mode == ZG.MODE_TRANSPORT then
			--g_currentMission:addExtraPrintText(self.keyName.. " " ..self.keyType(InputBinding.Transport).. ": " ..g_i18n:getText("Zgrabianie"));
			g_currentMission:addHelpButtonText(string.format(g_i18n:getText("UnTransport"), self.typeDesc), InputBinding.Transport);
			if InputBinding.hasEvent(InputBinding.Transport) then
				self.activeMode = ZG.ODW_TRANSPORT;
				self.rotTransport = not self.rotTransport;
				self.mode = ZG.MODE_ZGRABIANIE;
			end;
		-----Zmiana pozycji z transportowej na zgrabianie-----
		-----Zmiana pozycji ze zgrabiania na transportowa lub przetrzasanie-----
		elseif self.mode == ZG.MODE_ZGRABIANIE then
		--	g_currentMission:addExtraPrintText(self.keyName.. " " ..self.keyType(InputBinding.Transport).. ": " ..g_i18n:getText("Transport"));
			g_currentMission:addHelpButtonText(string.format(g_i18n:getText("Transport"), self.typeDesc), InputBinding.Transport);
		--	g_currentMission:addExtraPrintText(self.keyName.. " " ..self.keyType(InputBinding.Przetrzasanie).. ": " ..g_i18n:getText("Przetrzasanie"));
			g_currentMission:addHelpButtonText(string.format(g_i18n:getText("Przetrzasanie"), self.typeDesc), InputBinding.Przetrzasanie);
		--	g_currentMission:addExtraPrintText(self.keyName.. " " ..self.keyType(InputBinding.Odwracanie).. ": " ..g_i18n:getText("Odwracanie"));
			g_currentMission:addHelpButtonText(string.format(g_i18n:getText("Odwracanie"), self.typeDesc), InputBinding.Odwracanie);
			if InputBinding.hasEvent(InputBinding.Transport) then
				self.activeMode = ZG.ODW_TRANSPORT;
				self.rotTransport = not self.rotTransport;
				self.mode = ZG.MODE_TRANSPORT;				
			elseif InputBinding.hasEvent(InputBinding.Przetrzasanie) then
				self.activeMode = ZG.ODW_PRZETRZASANIE;
				self.rotPrzetrzasanie = not self.rotPrzetrzasanie;
				self.mode = ZG.MODE_ODWRACANIE_POKOSOW;	
			elseif InputBinding.hasEvent(InputBinding.Odwracanie) then
				self.activeMode = ZG.ODW_ODWRACANIE_POKOSOW;
				self.rotOdwracanie = not self.rotOdwracanie;
				self.mode = ZG.MODE_PRZETRZASANIE;				
			end;
		-----Zmiana pozycji ze zgrabiania na transportowa lub przetrzasanie-----
		-----Zmiana pozycji z przetrzasania na zgrabianie-----		
		elseif self.mode == ZG.MODE_PRZETRZASANIE then
			--g_currentMission:addExtraPrintText(self.keyName.. " " ..self.keyType(InputBinding.Przetrzasanie).. ": " ..g_i18n:getText("Zgrabianie"));
			g_currentMission:addHelpButtonText(string.format(g_i18n:getText("Zgrabianie"), self.typeDesc), InputBinding.Odwracanie);
			if InputBinding.hasEvent(InputBinding.Odwracanie) then
				self.activeMode = ZG.ODW_ODWRACANIE_POKOSOW;
				self.rotOdwracanie = not self.rotOdwracanie;
				self.mode = ZG.MODE_ZGRABIANIE;
			end;
		-----Zmiana pozycji z przetrzasania na zgrabianie-----
		-----Zmiana pozycji z odwracania pokosow na zgrabianie-----		
		elseif self.mode == ZG.MODE_ODWRACANIE_POKOSOW then
			--g_currentMission:addExtraPrintText(self.keyName.. " " ..self.keyType(InputBinding.Odwracanie).. ": " ..g_i18n:getText("Zgrabianie"));
			g_currentMission:addHelpButtonText(string.format(g_i18n:getText("Przetrzasanie"), self.typeDesc), InputBinding.Przetrzasanie);
			if InputBinding.hasEvent(InputBinding.Przetrzasanie) then
				self.activeMode = ZG.ODW_PRZETRZASANIE;
				self.rotPrzetrzasanie = not self.rotPrzetrzasanie;
				self.mode = ZG.MODE_ZGRABIANIE;
			end;
		end;
		-----Zmiana pozycji z odwracania pokosow na zgrabianie-----			
	else
		self.farmerNear = false;			
	end;

end;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function ZG:onAttach()

	self.fixAttacher = true;
	
	setMass(self.components[1].node, 0.058);
	setMass(self.components[2].node, 0.006);
	setMass(self.components[3].node, 0.029);
	setMass(self.components[4].node, 0.029);
	
	ZG.onActivate(self);
	
	ZG.addContactReports(self);
	
end; 	
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function ZG:onDetach()

    if self.deactivateOnDetach then
		local joint = self.saveJoint; 
		joint.minRot = self.rotationCopy;
		joint.maxRotLimit = self.maxRotJoint;
		
        ZG.onDeactivate(self);
        ZG.removeContactReports(self);
		
		setMass(self.components[1].node, 0.5);
		setMass(self.components[2].node, 5);
		setMass(self.components[3].node, 5);
		setMass(self.components[4].node, 5);
    else
		local joint = self.saveJoint; 
		joint.minRot = self.rotationCopy;
		joint.maxRotLimit = self.maxRotJoint;
		
		setMass(self.components[1].node, 0.5);
		setMass(self.components[2].node, 5);
		setMass(self.components[3].node, 5);
		setMass(self.components[4].node, 5);		
    end;		

end;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function ZG:onLeave()

    if self.deactivateOnLeave then
        ZG.onDeactivate(self);
    end;
	
end;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function ZG:onActivate()

end;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function ZG:onDeactivate()

	self.speedTimer = self.speedMaxTimer;
	
	for k,v in pairs(self.grassParticleSystems) do
		Utils.setEmittingState(v.ps, false);
	end;
	
	self.psEnabled = false;

	if self.zgSoundEnabled then
		stopSample(self.zgSound);
		self.zgSoundEnabled = false;
	end;

end;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function ZG:addContactReports()

    if not self.ZGContactReportsActive then
        for k, v in pairs(self.contactReportNodes) do
            addContactReport(v.node, 0.0001, "groundContactReport", self);
        end;
        self.ZGContactReportsActive = true;
    end;
	
end;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function ZG:removeContactReports()

    if self.ZGContactReportsActive then
        for k, v in pairs(self.contactReportNodes) do
            removeContactReport(v.node);
            v.hasGroundContact = false;
        end;
        self.ZGContactReportsActive = false;
    end;
	
end;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function ZG:groundContactReport(objectId, otherObjectId, isStart, normalForce, tangentialForce)

    if otherObjectId == g_currentMission.terrainRootNode then
        local entry = self.contactReportNodes[objectId];
        if entry ~= nil then
            entry.hasGroundContact = isStart or normalForce > 0 or tangentialForce > 0;
        end;
    end;

end;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------