
UAL = {};

function UAL.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Mountable, specializations);
end;

function UAL:load(savegame)

    self.state = 1;
    
    self.moveTriggerUp = getXMLString(self.xmlFile, "vehicle.moveTriggerUp#animationName");
    self.moveTriggerDn = getXMLString(self.xmlFile, "vehicle.moveTriggerDn#animationName");
    
    self.FiHeBa= SpecializationUtil.callSpecializationsFunction("FiHeBa");
    self.MPCode = SpecializationUtil.callSpecializationsFunction("MPCode");    
    
    self.balesJoint = Utils.indexToObject(self.components,getXMLString(self.xmlFile,"vehicle.balesJoint#index"));
    self.roundsJoint = Utils.indexToObject(self.components,getXMLString(self.xmlFile,"vehicle.balesJoint#rounds"));
    self.centerJoint = Utils.indexToObject(self.components,getXMLString(self.xmlFile,"vehicle.balesJoint#center"));
    self.woolJoint = Utils.indexToObject(self.components,getXMLString(self.xmlFile,"vehicle.balesJoint#wool"));
    self.ultimaJoint = Utils.indexToObject(self.components,getXMLString(self.xmlFile,"vehicle.balesJoint#ultima"));
    self.ultima4Joint = Utils.indexToObject(self.components,getXMLString(self.xmlFile,"vehicle.balesJoint#ultima4"));
    self.hdbalesJoint = Utils.indexToObject(self.components,getXMLString(self.xmlFile,"vehicle.balesJoint#hdbales"));
    self.objectCallbackUAL = SpecializationUtil.callSpecializationsFunction("objectCallbackUAL"); 
    
    self.searcher = {};
    local trigger = Utils.indexToObject( self.components, getXMLString(self.xmlFile, string.format("vehicle.balesJoint#search")) );
    local trigger2 = Utils.indexToObject( self.components, getXMLString(self.xmlFile, string.format("vehicle.balesJoint#search2")) );
    if trigger == nil then
        print("[Error::UAL] node is OK, but trigger could not be located. Check line "..tostring(i+1).." in your vehicle.xml");
    end;
    if trigger2 == nil then
        print("[Error::UAL] node is OK, but trigger2 could not be located. Check line "..tostring(i+1).." in your vehicle.xml");
    end;
    self.searcher.trigger = trigger;
    self.searcher.trigger2 = trigger2;
    addTrigger( trigger, "objectCallbackUAL", self );
    addTrigger( trigger2, "objectCallbackUAL", self );
    self:playAnimation(self.moveTriggerDn, 1, nil, true);    
    
    self.balesToLoad = {};
    self.rbalesToLoad = {};
    self.woolToLoad = {};
    self.ultimaToLoad = {};
    self.ultima4ToLoad = {};
    self.hdbalesToLoad = {};
    self.balesToMount = {};
    self.rbalesToMount = {};
    self.woolToMount = {};
    self.ultimaToMount = {};
    self.ultima4ToMount = {};
    self.hdbalesToMount = {};
    
    self.baleTypes = {};
    local i = 0;
    while true do
        local key = string.format("vehicle.baleTypes.bale(%d)", i);
        if not hasXMLProperty(self.xmlFile, key) then
            break;
        end;
        local filename = getXMLString(self.xmlFile, key.."#type");
        if filename ~= nil then
            table.insert(self.baleTypes, filename);
        end;
        i = i + 1;
    end;

    self.hayBales = {};
    local i = 0;
    while true do
        local key = string.format("vehicle.hayBales.bale(%d)", i);
        if not hasXMLProperty(self.xmlFile, key) then
            break;
        end;
        local entry = {};
        local index = Utils.indexToObject(self.components,getXMLString(self.xmlFile, key.."#index"));
        if index ~= nil then
            entry.node = index;
            entry.baleId = nil;
            table.insert(self.hayBales, entry);
        end;
        i = i + 1;
    end;
    self.numMaxSquare = i;
    
    self.hayRounds = {};
    local i = 0;
    while true do
        local key = string.format("vehicle.hayRounds.bale(%d)", i);
        if not hasXMLProperty(self.xmlFile, key) then
            break;
        end;
        local entry = {};
        local index = Utils.indexToObject(self.components,getXMLString(self.xmlFile, key.."#index"));
        if index ~= nil then
            entry.node = index;
            entry.baleId = nil;
            table.insert(self.hayRounds, entry);
        end;
        i = i + 1;
    end;
    self.numMaxRound = i;
    
    self.wool = {};
    local i = 0;
    while true do
        local key = string.format("vehicle.wool.place(%d)", i);
        if not hasXMLProperty(self.xmlFile, key) then
            break;
        end;
        local entry = {};
        local index = Utils.indexToObject(self.components,getXMLString(self.xmlFile, key.."#index"));
        if index ~= nil then
            entry.node = index;
            entry.baleId = nil;
            table.insert(self.wool, entry);
        end;
        i = i + 1;
    end;
    self.numMaxWool = i;
    
    self.ultima = {};
    local i = 0;
    while true do
        local key = string.format("vehicle.ultima.place(%d)", i);
        if not hasXMLProperty(self.xmlFile, key) then
            break;
        end;
        local entry = {};
        local index = Utils.indexToObject(self.components,getXMLString(self.xmlFile, key.."#index"));
        if index ~= nil then
            entry.node = index;
            entry.baleId = nil;
            table.insert(self.ultima, entry);
        end;
        i = i + 1;
    end;
    self.numMaxUltima = i;
    
    self.ultima4 = {};
    local i = 0;
    while true do
        local key = string.format("vehicle.ultima4.place(%d)", i);
        if not hasXMLProperty(self.xmlFile, key) then
            break;
        end;
        local entry = {};
        local index = Utils.indexToObject(self.components,getXMLString(self.xmlFile, key.."#index"));
        if index ~= nil then
            entry.node = index;
            entry.baleId = nil;
            table.insert(self.ultima4, entry);
        end;
        i = i + 1;
    end;
    self.numMaxUltima4 = i;
    
    self.hdbales = {};
    local i = 0;
    while true do
        local key = string.format("vehicle.hdbales.place(%d)", i);
        if not hasXMLProperty(self.xmlFile, key) then
            break;
        end;
        local entry = {};
        local index = Utils.indexToObject(self.components,getXMLString(self.xmlFile, key.."#index"));
        if index ~= nil then
            entry.node = index;
            entry.baleId = nil;
            table.insert(self.hdbales, entry);
        end;
        i = i + 1;
    end;
    self.numMaxhdbales = i;
    
    self.i = {};
    self.workMode = false;
    
    self.counter = 0;
    self.foundIt = false;
    self.baleId = nil;
    
    self.firstTime = true;
    
    self.bales = {};
    
    self.fillLevel = 0;
    self.fillLevelMax = self.numMaxSquare;
    
    self.marker = Utils.indexToObject(self.components,getXMLString(self.xmlFile, "vehicle.marker#index"));
    setVisibility(self.marker, false);
    self.mLeft = Utils.indexToObject(self.components,getXMLString(self.xmlFile, "vehicle.marker#left"));
    self.mRight = Utils.indexToObject(self.components,getXMLString(self.xmlFile, "vehicle.marker#right"));
    self.mBack = Utils.indexToObject(self.components,getXMLString(self.xmlFile, "vehicle.marker#back"));
    self.unloadPos = 0;
    
    self.loadTypes = {}
    local loadType = g_i18n:getText("squarebales");    
    if loadType == nil then
        loadType = "squarebales"
    end;
    local entry = {};
    entry.text = loadType;
    table.insert(self.loadTypes, entry);
    
    local loadType = g_i18n:getText("roundbales");    
    if loadType == nil then
        loadType = "roundbales"
    end;
    local entry = {};
    entry.text = loadType;
    table.insert(self.loadTypes, entry);
    
    local loadType = g_i18n:getText("ultima4");    
    if loadType == nil then
        loadType = "ultima4"
    end;
    local entry = {};
    entry.text = loadType;
    table.insert(self.loadTypes, entry);
    
    local loadType = g_i18n:getText("ultima");    
    if loadType == nil then
        loadType = "ultima"
    end;
    local entry = {};
    entry.text = loadType;
    table.insert(self.loadTypes, entry);
    
    local loadType = g_i18n:getText("hdbales");    
    if loadType == nil then
        loadType = "hdbales"
    end;
    local entry = {};
    entry.text = loadType;
    table.insert(self.loadTypes, entry);

    local loadType = g_i18n:getText("woolpallet");    
    if loadType == nil then
        loadType = "woolpallet"
    end;
    local entry = {};
    entry.text = loadType;
    table.insert(self.loadTypes, entry);
    
    self.varbodyIDX = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.balesJoint#varBodyIndex"),0);
    
end;

function UAL:delete()
    for i, balePlace in pairs(self.hayBales) do
        if balePlace.baleId ~= nil then
            local bale = networkGetObject(balePlace.baleId);
            if bale ~= nil then
                bale:unmount();
            end;
        end;
    end;
    for i, balePlace in pairs(self.hayRounds) do
        if balePlace.baleId ~= nil then
            local bale = networkGetObject(balePlace.baleId);
            if bale ~= nil then
                bale:unmount();
            end;
        end;
    end;
    for i, balePlace in pairs(self.wool) do
        if balePlace.baleId ~= nil then
            local bale = networkGetObject(balePlace.baleId);
            if bale ~= nil then
                bale:unmount();
            end;
        end;
    end;
    for i, balePlace in pairs(self.ultima) do
        if balePlace.baleId ~= nil then
            local bale = networkGetObject(balePlace.baleId);
            if bale ~= nil then
                bale:unmount();
            end;
        end;
    end;
    for i, balePlace in pairs(self.ultima4) do
        if balePlace.baleId ~= nil then
            local bale = networkGetObject(balePlace.baleId);
            if bale ~= nil then
                bale:unmount();
            end;
        end;
    end;
    for i, balePlace in pairs(self.hdbales) do
        if balePlace.baleId ~= nil then
            local bale = networkGetObject(balePlace.baleId);
            if bale ~= nil then
                bale:unmount();
            end;
        end;
    end;
    
    if self.searcher.trigger ~= nil then
        removeTrigger(self.searcher.trigger);
    end;
    if self.searcher.trigger2 ~= nil then
        removeTrigger(self.searcher.trigger2);
    end;
end;

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

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

function UAL:update(dt)
    if self.varbodyIDX ~= 0 and self.varBody ~= nil then
        self.varBodyactIdx = Utils.getNoNil(self.varBody.activeIdx,0);
    else
        self.varBodyactIdx = 0;
    end
    
    if self.firstTime then
        self.firstTime = false;
        for k,v in pairs(self.balesToLoad) do
            local baleObject = Bale:new(self.isServer, self.isClient);
            local x,y,z = unpack(v.translation);
            local rx,ry,rz = unpack(v.rotation);
            baleObject:load(v.filename, x,y,z,rx,ry,rz, v.fillLevel);
            baleObject:mount(self, self.hayBales[k].node, x,y,z, rx,ry,rz);
            if v.baleValueScale ~= nil then
                baleObject.baleValueScale = v.baleValueScale;
            end
            if v.wrappingState ~= nil and baleObject.setWrappingState ~= nil then
                baleObject:setWrappingState(v.wrappingState);
            end
            baleObject:register();
            v.baleId = networkGetObjectId(baleObject);
            self.balesToLoad[k] = nil;
            self.hayBales[k].baleId = v.baleId;
        end;
        for k,v in pairs(self.rbalesToLoad) do
            local baleObject = Bale:new(self.isServer, self.isClient);
            local x,y,z = unpack(v.translation);
            local rx,ry,rz = unpack(v.rotation);
            baleObject:load(v.filename, x,y,z,rx,ry,rz, v.fillLevel);
            baleObject:mount(self, self.hayRounds[k].node, x,y,z, rx,ry,rz);
            if v.baleValueScale ~= nil then
                baleObject.baleValueScale = v.baleValueScale;
            end
            if v.wrappingState ~= nil and baleObject.setWrappingState ~= nil then
                baleObject:setWrappingState(v.wrappingState);
            end
            baleObject:register();
            v.baleId = networkGetObjectId(baleObject);
            self.rbalesToLoad[k] = nil;
            self.hayRounds[k].baleId = v.baleId;
        end;
        for k,v in pairs(self.woolToLoad) do
            local baleObject = FillablePallet:new(self.isServer, self.isClient);
            local x,y,z = unpack(v.translation);
            local rx,ry,rz = unpack(v.rotation);
            baleObject:load(v.filename, x,y,z,rx,ry,rz);
            baleObject:setFillLevel(v.fillLevel, false)
            baleObject:mount(self, self.wool[k].node, x,y,z, rx,ry,rz);
            if v.baleValueScale ~= nil then
                baleObject.fillablePalletValueScale = v.baleValueScale;
            end
            baleObject:register();
            v.baleId = networkGetObjectId(baleObject);
            self.woolToLoad[k] = nil;
            self.wool[k].baleId = v.baleId;
        end;
        for k,v in pairs(self.ultimaToLoad) do
            local baleObject = Bale:new(self.isServer, self.isClient);
            local x,y,z = unpack(v.translation);
            local rx,ry,rz = unpack(v.rotation);
            baleObject:load(v.filename, x,y,z,rx,ry,rz);
            baleObject:setFillLevel(v.fillLevel, false)
            baleObject:mount(self, self.ultima[k].node, x,y,z, rx,ry,rz);
            if v.baleValueScale ~= nil then
                baleObject.fillablePalletValueScale = v.baleValueScale;
            end
            baleObject:register();
            v.baleId = networkGetObjectId(baleObject);
            self.ultimaToLoad[k] = nil;
            self.ultima[k].baleId = v.baleId;
        end;
        for k,v in pairs(self.ultima4ToLoad) do
            local baleObject = Bale:new(self.isServer, self.isClient);
            local x,y,z = unpack(v.translation);
            local rx,ry,rz = unpack(v.rotation);
            baleObject:load(v.filename, x,y,z,rx,ry,rz);
            baleObject:setFillLevel(v.fillLevel, false)
            baleObject:mount(self, self.ultima4[k].node, x,y,z, rx,ry,rz);
            if v.baleValueScale ~= nil then
                baleObject.fillablePalletValueScale = v.baleValueScale;
            end
            baleObject:register();
            v.baleId = networkGetObjectId(baleObject);
            self.ultima4ToLoad[k] = nil;
            self.ultima4[k].baleId = v.baleId;
        end;
        for k,v in pairs(self.hdbalesToLoad) do
            local baleObject = Bale:new(self.isServer, self.isClient);
            local x,y,z = unpack(v.translation);
            local rx,ry,rz = unpack(v.rotation);
            baleObject:load(v.filename, x,y,z,rx,ry,rz);
            baleObject:setFillLevel(v.fillLevel, false)
            baleObject:mount(self, self.hdbales[k].node, x,y,z, rx,ry,rz);
            if v.baleValueScale ~= nil then
                baleObject.fillablePalletValueScale = v.baleValueScale;
            end
            baleObject:register();
            v.baleId = networkGetObjectId(baleObject);
            self.hdbalesToLoad[k] = nil;
            self.hdbales[k].baleId = v.baleId;
        end;
        
        for k, baleToMount in pairs(self.balesToMount) do
            local bale = networkGetObject(baleToMount.serverId);
            if bale ~= nil then
                local x,y,z = unpack(baleToMount.trans);
                local rx,ry,rz = unpack(baleToMount.rot);
                bale:mount(self, baleToMount.linkNode, x,y,z, rx,ry,rz);
                self.balesToMount[k] = nil;
            end;
        end;
        for k, baleToMount in pairs(self.rbalesToMount) do
            local bale = networkGetObject(baleToMount.serverId);
            if bale ~= nil then
                local x,y,z = unpack(baleToMount.trans);
                local rx,ry,rz = unpack(baleToMount.rot);
                bale:mount(self, baleToMount.linkNode, x,y,z, rx,ry,rz);
                self.rbalesToMount[k] = nil;
            end;
        end;
        for k, baleToMount in pairs(self.woolToMount) do
            local bale = networkGetObject(baleToMount.serverId);
            if bale ~= nil then
                local x,y,z = unpack(baleToMount.trans);
                local rx,ry,rz = unpack(baleToMount.rot);
                bale:mount(self, baleToMount.linkNode, x,y,z, rx,ry,rz);
                self.woolToMount[k] = nil;
            end;
        end;
        for k, baleToMount in pairs(self.ultimaToMount) do
            local bale = networkGetObject(baleToMount.serverId);
            if bale ~= nil then
                local x,y,z = unpack(baleToMount.trans);
                local rx,ry,rz = unpack(baleToMount.rot);
                bale:mount(self, baleToMount.linkNode, x,y,z, rx,ry,rz);
                self.ultimaToMount[k] = nil;
            end;
        end;
        for k, baleToMount in pairs(self.ultima4ToMount) do
            local bale = networkGetObject(baleToMount.serverId);
            if bale ~= nil then
                local x,y,z = unpack(baleToMount.trans);
                local rx,ry,rz = unpack(baleToMount.rot);
                bale:mount(self, baleToMount.linkNode, x,y,z, rx,ry,rz);
                self.ultima4ToMount[k] = nil;
            end;
        end;
        for k, baleToMount in pairs(self.hdbalesToMount) do
            local bale = networkGetObject(baleToMount.serverId);
            if bale ~= nil then
                local x,y,z = unpack(baleToMount.trans);
                local rx,ry,rz = unpack(baleToMount.rot);
                bale:mount(self, baleToMount.linkNode, x,y,z, rx,ry,rz);
                self.hdbalesToMount[k] = nil;
            end;
        end;
    end;

    if self:getIsActiveForInput() and self:getIsActive() and self.varBodyactIdx == self.varbodyIDX then
        if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA2) then
            if self.counter ~= self.fillLevelMax then
                setVisibility(self.marker, false);
                self.unloadPos = 0;
                self:MPCode(99, not self.workMode, 0, 0, 0, false);
            end;
        end;
    
        if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA4) then
            if self.counter == 0 and not self.workMode then
                self.state = self.state + 1;
                if self.state > 6 then
                    self.state = 1;
                end
                self:MPCode(98, false, self.state, 0, 0, false);
            end
        end
        
        if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then
            if self.counter >= 1 and not self.workMode then
                self.unloadPos = self.unloadPos + 1;
                if self.unloadPos > 3 then
                    self.unloadPos = 0;
                end

                if self.unloadPos == 0 then
                    setVisibility(self.marker, false);
                    local x,y,z = getTranslation(self.centerJoint)
                    setTranslation(self.marker, x,y,z)
                elseif  self.unloadPos == 1 then
                    setVisibility(self.marker, true);
                    local x,y,z = getTranslation(self.mLeft)
                    setTranslation(self.marker, x,y,z)
                elseif  self.unloadPos == 2 then
                    setVisibility(self.marker, true);
                    local x,y,z = getTranslation(self.mRight)
                    setTranslation(self.marker, x,y,z)
                elseif  self.unloadPos == 3 then
                    setVisibility(self.marker, true);
                    local x,y,z = getTranslation(self.mBack)
                    setTranslation(self.marker, x,y,z)
                end;
            end;
        end
    
        if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA3) then
            if self.counter >= 1 and not self.workMode then
                self:MPCode(24, false, self.unloadPos, 0, 0, false);
            end;
        end;
    end;
    
    if self.isServer then
        if self.workMode then
            if self.foundIt then
                --self:MPCode(21, false, self.state, self.baleId, 0, false);
            else
                --self:FiHeBa(self.balesJoint);
            end;
        end;
    end;
    if self.varBodyactIdx ~= self.varbodyIDX and self.workMode then
        self:MPCode(99, false, 0, 0, 0, false);
    end;
    if self.counter == self.fillLevelMax then
        --self:MPCode(99, false, 0, 0, 0, false);
    end;
end;

function UAL:draw()
    if self.varBodyactIdx == self.varbodyIDX then

        if self.counter < self.fillLevelMax then
            if not self.workMode then
                g_currentMission:addHelpButtonText(string.format(g_i18n:getText("WORKMODE_on"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA2);
            else
                g_currentMission:addHelpButtonText(string.format(g_i18n:getText("WORKMODE_off"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA2);
            end;
        end;
        
        if self.counter >= 1 and not self.workMode then
            g_currentMission:addHelpButtonText(string.format(g_i18n:getText("UNLOAD"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA3);
            if self.unloadPos == 0 then
                g_currentMission:addHelpButtonText(string.format(g_i18n:getText("UNLOAD_C"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA);
            elseif self.unloadPos == 1 then
                g_currentMission:addHelpButtonText(string.format(g_i18n:getText("UNLOAD_L"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA);
            elseif self.unloadPos == 2 then
                g_currentMission:addHelpButtonText(string.format(g_i18n:getText("UNLOAD_R"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA);
            elseif self.unloadPos == 3 then
                g_currentMission:addHelpButtonText(string.format(g_i18n:getText("UNLOAD_B"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA);
            end;
        end;
    
        if self.counter == 0 and not self.workMode then
            g_currentMission:addHelpButtonText(self.loadTypes[self.state].text, InputBinding.IMPLEMENT_EXTRA4);
        end;
    end;
end;

function UAL:MPCode(mode, bool, state, dif, olddif, noEventSend)
    MPEvent.sendEvent(self, mode, bool, state, dif, olddif, noEventSend);
    if mode == 21 then    
        
        self.baleId = dif;
        local object = networkGetObject(self.baleId);
        if object == nil then
            return;
        end;
        self.counter = self.counter + 1;        
        self.fillLevel = self.counter;

        if state==1 then
            object:mount(self, self.hayBales[self.counter].node, 0,0,0, 0,0,0);
            self.hayBales[self.counter].baleId = self.baleId;
        elseif state==2 then
            object:mount(self, self.hayRounds[self.counter].node, 0,0,0, 0,0,0);
            self.hayRounds[self.counter].baleId = self.baleId;
        elseif state==3 then
            object:mount(self, self.ultima4[self.counter].node, 0,0,0, 0,0,0);
            self.ultima4[self.counter].baleId = self.baleId;
        elseif state==4 then
            object:mount(self, self.ultima[self.counter].node, 0,0,0, 0,0,0);
            self.ultima[self.counter].baleId = self.baleId;
        elseif state==5 then
            object:mount(self, self.hdbales[self.counter].node, 0,0,0, 0,0,0);
            self.hdbales[self.counter].baleId = self.baleId;
        elseif state==6 then
            --print("Mount: " .. self.counter .. " / " .. self.baleId)
            object:mount(self, self.wool[self.counter].node, 0,0,0, 0,0,0);
            self.wool[self.counter].baleId = self.baleId;
        end;
        
        self.fillLevelMax = self.numMaxSquare;
        if state == 2 then
            self.fillLevelMax = self.numMaxRound;
        end
        if state == 3 then
            self.fillLevelMax = self.numMaxUltima4;
        end
        if state == 4 then
            self.fillLevelMax = self.numMaxUltima;
        end
        if state == 5 then
            self.fillLevelMax = self.numMaxhdbales;
        end
        if state == 6 then
            self.fillLevelMax = self.numMaxWool;
        end
        self.capacity = self.fillLevelMax;
        
        self.foundIt = false;
        self.baleId = nil;

    elseif mode == 24 then
        
        if state == 0 then
            local x,y,z = getTranslation(self.centerJoint)
            setTranslation(self.balesJoint, x,y,z)
            setTranslation(self.roundsJoint, x,y,z)
            setTranslation(self.woolJoint, x,y,z)
            setTranslation(self.ultimaJoint, x,y,z)
            setTranslation(self.ultima4Joint, x,y,z)
            setTranslation(self.hdbalesJoint, x,y,z)
        elseif state == 1 then
            local x,y,z = getTranslation(self.mLeft)
            setTranslation(self.balesJoint, x,y-1.1,z)
            setTranslation(self.roundsJoint, x,y-1.1,z)
            setTranslation(self.woolJoint, x,y-1.1,z)
            setTranslation(self.ultimaJoint, x,y-1.1,z)
            setTranslation(self.ultima4Joint, x,y-1.1,z)
            setTranslation(self.hdbalesJoint, x,y-1.1,z)
        elseif state == 2 then
            local x,y,z = getTranslation(self.mRight)
            setTranslation(self.balesJoint, x,y-1.1,z)
            setTranslation(self.roundsJoint, x,y-1.1,z)
            setTranslation(self.woolJoint, x,y-1.1,z)
            setTranslation(self.ultimaJoint, x,y-1.1,z)
            setTranslation(self.ultima4Joint, x,y-1.1,z)
            setTranslation(self.hdbalesJoint, x,y-1.1,z)
        elseif state == 3 then
            local x,y,z = getTranslation(self.mBack)
            setTranslation(self.balesJoint, x,y-1.1,z)
            setTranslation(self.roundsJoint, x,y-1.1,z)
            setTranslation(self.woolJoint, x,y-1.1,z)
            setTranslation(self.ultimaJoint, x,y-1.1,z)
            setTranslation(self.ultima4Joint, x,y-1.1,z)
            setTranslation(self.hdbalesJoint, x,y-1.1,z)
        end
        
        for _, balePlace in pairs(self.hayBales) do
            if balePlace.baleId ~= nil then
                local baleServerId = balePlace.baleId
                local bale = networkGetObject(baleServerId);
                if bale ~= nil then
                    bale:unmount();
                end;
                balePlace.baleId = nil;
            end;
        end;
    
        for _, balePlace in pairs(self.hayRounds) do
            if balePlace.baleId ~= nil then
                local baleServerId = balePlace.baleId
                local bale = networkGetObject(baleServerId);
                if bale ~= nil then
                    bale:unmount();
                end;
                balePlace.baleId = nil;
            end;
        end;
        for _, balePlace in pairs(self.wool) do
            if balePlace.baleId ~= nil then
                local baleServerId = balePlace.baleId
                local bale = networkGetObject(baleServerId);
                if bale ~= nil then
                    --print("Unmount: " .. _ .. " / " .. baleServerId);
                    bale:unmount();
                end;
                balePlace.baleId = nil;
            end;
        end;
        for _, balePlace in pairs(self.ultima) do
            if balePlace.baleId ~= nil then
                local baleServerId = balePlace.baleId
                local bale = networkGetObject(baleServerId);
                if bale ~= nil then
                    bale:unmount();
                end;
                balePlace.baleId = nil;
            end;
        end;
        for _, balePlace in pairs(self.ultima4) do
            if balePlace.baleId ~= nil then
                local baleServerId = balePlace.baleId
                local bale = networkGetObject(baleServerId);
                if bale ~= nil then
                    bale:unmount();
                end;
                balePlace.baleId = nil;
            end;
        end;
        for _, balePlace in pairs(self.hdbales) do
            if balePlace.baleId ~= nil then
                local baleServerId = balePlace.baleId
                local bale = networkGetObject(baleServerId);
                if bale ~= nil then
                    bale:unmount();
                end;
                balePlace.baleId = nil;
            end;
        end;
    
        self.counter = 0;
        self.fillLevel = 0;

        setVisibility(self.marker, false);
        local x,y,z = getTranslation(self.centerJoint)
        setTranslation(self.marker, x,y,z)
        self.unloadPos = 0;
        local x,y,z = getTranslation(self.centerJoint)
        setTranslation(self.balesJoint, x,y,z)
        setTranslation(self.roundsJoint, x,y,z)
        setTranslation(self.woolJoint, x,y,z)
        setTranslation(self.ultimaJoint, x,y,z)
        setTranslation(self.ultima4Joint, x,y,z)
        setTranslation(self.hdbalesJoint, x,y,z)
        
    elseif mode == 98 then
        self.state = state;
        
    elseif mode == 99 then
        self.workMode = bool;
        if self.workMode then
            self:playAnimation(self.moveTriggerUp, 1, nil, true);
        else
            self:playAnimation(self.moveTriggerDn, 1, nil, true);
        end
    end;
end;

function UAL:updateTick(dt)
end;

function UAL:FiHeBa(objectX, noEventSend)
    self.foundIt = false;
    local baleDiameter = tonumber(getUserAttribute(objectX.nodeId, "baleDiameter"));
    local isRoundbale = Utils.getNoNil(getUserAttribute(objectX.nodeId, "isRoundbale"), false);
    local isHDbale = Utils.getNoNil(getUserAttribute(objectX.nodeId, "isHDbale"), false);
    if baleDiameter == nil then
        local baleDiameter = 0;
    end
    
    self.baleId = nil;
    if (self.state == 1 and not isRoundbale and (objectX:isa(Bale))) or
     (self.state == 2 and isRoundbale and baleDiameter <= 1.3) or
     (self.state == 3 and isRoundbale and baleDiameter > 1.3 and baleDiameter <= 1.4) or
     (self.state == 4 and isRoundbale and baleDiameter > 1.4 and baleDiameter <= 1.5) or
     (self.state == 5 and isHDbale) or           
     (self.state == 6 and objectX:isa(FillablePallet)) then
        self.foundIt = true;
        self.baleId = networkGetObjectId(objectX);
        self:MPCode(21, false, self.state, self.baleId, 0, false);
        if self.counter == self.fillLevelMax then
            self:MPCode(99, false, 0, 0, 0, false);
        end;
    end;
end;

function UAL:postLoad(savegame)
    if savegame == nil then
        return
    end
    
    local key = savegame.key
    self.counter = Utils.getNoNil(getXMLInt(savegame.xmlFile, key.."#numBales"),0);
    self.state = Utils.getNoNil(getXMLInt(savegame.xmlFile, key.."#baleMode"),0);
    self.fillLevel = self.counter;
    self.capacity = self.numMaxSquare;
    if self.state == 2 then
        self.capacity = self.numMaxRound;
    end
    if self.state == 3 then
        self.capacity = self.numMaxUltima4;
    end
    if self.state == 4 then
        self.capacity = self.numMaxUltima;
    end
    if self.state == 5 then
        self.capacity = self.numMaxhdbales;
    end
    if self.state == 6 then
        self.capacity = self.numMaxWool;
    end
    if self.varbodyIDX ~= 0 and self.varBody ~= nil then
        self.varBodyactIdx = Utils.getNoNil(self.varBody.activeIdx,0);
    else
        self.varBodyactIdx = 0;
    end
    if self.varbodyIDX ~= self.varBodyactIdx then
        self.capacity = self.varBody.nodes[self.varBodyactIdx].capacity;
    end
    self.fillLevelMax = self.capacity;
        
    local i=0;
    while true do
        local baleKey = key..string.format(".bale(%d)", i);
        if not hasXMLProperty(savegame.xmlFile, baleKey) then
            break;
        end;
        local filename = getXMLString(savegame.xmlFile, baleKey.."#filename");
        if filename ~= nil then
            filename = Utils.convertFromNetworkFilename(filename);
            local x,y,z = Utils.getVectorFromString(getXMLString(savegame.xmlFile, baleKey.."#position"));
            local xRot,yRot,zRot = Utils.getVectorFromString(getXMLString(savegame.xmlFile, baleKey.."#rotation"));
            local fillLevel = getXMLFloat(savegame.xmlFile, baleKey.."#fillLevel");
            local balePlace = getXMLInt(savegame.xmlFile, baleKey.."#balePlace");
            local helper = getXMLInt(savegame.xmlFile, baleKey.."#helper");
            if balePlace == nil or (balePlace > 0 and (x == nil or y == nil or z == nil or xRot == nil or yRot == nil or zRot == nil)) or (balePlace < 1 and helper == nil) then
                print("Warning: Corrupt savegame, bale "..filename.." could not be loaded");
            else
                local translation;
                local rotation;
                if balePlace > 0 then
                    translation = {x,y,z};
                    rotation={xRot, yRot, zRot};
                else
                    translation = {0,0,0};
                    rotation={0,0,0};
                end;
                local parentNode = nil;
                local bales = nil;
                if balePlace < 1 then
                    
                elseif balePlace <= table.getn(self.hayBales) then
                    parentNode = self.hayBales[balePlace].node;
                    bales = self.hayBales[balePlace].baleId;
                end;
                if parentNode ~= nil then
                    local baleValueScale = getXMLFloat(savegame.xmlFile, baleKey.."#baleValueScale");
                    local wrappingState = getXMLFloat(savegame.xmlFile, baleKey.."#wrappingState");
                    table.insert(self.balesToLoad, {parentNode=parentNode, filename=filename, bales=bales, translation=translation, rotation=rotation, fillLevel=fillLevel, baleValueScale=baleValueScale, wrappingState=wrappingState});
                end;
            end;
        end;
        i = i +1;
    end;
        
    local i=0;
    while true do
        local baleKey = key..string.format(".rbale(%d)", i);
        if not hasXMLProperty(savegame.xmlFile, baleKey) then
            break;
        end;
        local filename = getXMLString(savegame.xmlFile, baleKey.."#filename");
        if filename ~= nil then
            filename = Utils.convertFromNetworkFilename(filename);
            local x,y,z = Utils.getVectorFromString(getXMLString(savegame.xmlFile, baleKey.."#position"));
            local xRot,yRot,zRot = Utils.getVectorFromString(getXMLString(savegame.xmlFile, baleKey.."#rotation"));
            local fillLevel = getXMLFloat(savegame.xmlFile, baleKey.."#fillLevel");
            local balePlace = getXMLInt(savegame.xmlFile, baleKey.."#balePlace");
            local helper = getXMLInt(savegame.xmlFile, baleKey.."#helper");
            if balePlace == nil or (balePlace > 0 and (x == nil or y == nil or z == nil or xRot == nil or yRot == nil or zRot == nil)) or (balePlace < 1 and helper == nil) then
                print("Warning: Corrupt savegame, rbale "..filename.." could not be loaded");
            else
                local translation;
                local rotation;
                if balePlace > 0 then
                    translation = {x,y,z};
                    rotation={xRot, yRot, zRot};
                else
                    translation = {0,0,0};
                    rotation={0,0,0};
                end;
                local parentNode = nil;
                local bales = nil;
                if balePlace < 1 then
                    
                elseif balePlace <= table.getn(self.hayRounds) then
                    parentNode = self.hayRounds[balePlace].node;
                    bales = self.hayRounds[balePlace].baleId;
                end;
                if parentNode ~= nil then
                    local baleValueScale = getXMLFloat(savegame.xmlFile, baleKey.."#baleValueScale");
                    local wrappingState = getXMLFloat(savegame.xmlFile, baleKey.."#wrappingState");
                    table.insert(self.rbalesToLoad, {parentNode=parentNode, filename=filename, bales=bales, translation=translation, rotation=rotation, fillLevel=fillLevel, baleValueScale=baleValueScale, wrappingState=wrappingState});
                end;
            end;
        end;
        i = i +1;
    end;
    
    local i=0;
    while true do
        local baleKey = key..string.format(".wool(%d)", i);
        if not hasXMLProperty(savegame.xmlFile, baleKey) then
            break;
        end;
        local filename = getXMLString(savegame.xmlFile, baleKey.."#filename");
        if filename ~= nil then
            filename = Utils.convertFromNetworkFilename(filename);
            local x,y,z = Utils.getVectorFromString(getXMLString(savegame.xmlFile, baleKey.."#position"));
            local xRot,yRot,zRot = Utils.getVectorFromString(getXMLString(savegame.xmlFile, baleKey.."#rotation"));
            local fillLevel = getXMLFloat(savegame.xmlFile, baleKey.."#fillLevel");
            local balePlace = getXMLInt(savegame.xmlFile, baleKey.."#balePlace");
            local helper = getXMLInt(savegame.xmlFile, baleKey.."#helper");
            if balePlace == nil or (balePlace > 0 and (x == nil or y == nil or z == nil or xRot == nil or yRot == nil or zRot == nil)) or (balePlace < 1 and helper == nil) then
                print("Warning: Corrupt savegame, wool "..filename.." could not be loaded");
            else
                local translation;
                local rotation;
                if balePlace > 0 then
                    translation = {x,y,z};
                    rotation={xRot, yRot, zRot};
                else
                    translation = {0,0,0};
                    rotation={0,0,0};
                end;
                local parentNode = nil;
                local bales = nil;
                if balePlace < 1 then
                    
                elseif balePlace <= table.getn(self.wool) then
                    parentNode = self.wool[balePlace].node;
                    bales = self.wool[balePlace].baleId;
                end;
                if parentNode ~= nil then
                    local baleValueScale = getXMLFloat(savegame.xmlFile, baleKey.."#baleValueScale");
                    local wrappingState = getXMLFloat(savegame.xmlFile, baleKey.."#wrappingState");
                    table.insert(self.woolToLoad, {parentNode=parentNode, filename=filename, bales=bales, translation=translation, rotation=rotation, fillLevel=fillLevel, baleValueScale=baleValueScale, wrappingState=wrappingState});
                end;
            end;
        end;
        i = i +1;
    end;

    local i=0;
    while true do
        local baleKey = key..string.format(".ultima(%d)", i);
        if not hasXMLProperty(savegame.xmlFile, baleKey) then
            break;
        end;
        local filename = getXMLString(savegame.xmlFile, baleKey.."#filename");
        if filename ~= nil then
            filename = Utils.convertFromNetworkFilename(filename);
            local x,y,z = Utils.getVectorFromString(getXMLString(savegame.xmlFile, baleKey.."#position"));
            local xRot,yRot,zRot = Utils.getVectorFromString(getXMLString(savegame.xmlFile, baleKey.."#rotation"));
            local fillLevel = getXMLFloat(savegame.xmlFile, baleKey.."#fillLevel");
            local balePlace = getXMLInt(savegame.xmlFile, baleKey.."#balePlace");
            local helper = getXMLInt(savegame.xmlFile, baleKey.."#helper");
            if balePlace == nil or (balePlace > 0 and (x == nil or y == nil or z == nil or xRot == nil or yRot == nil or zRot == nil)) or (balePlace < 1 and helper == nil) then
                print("Warning: Corrupt savegame, ultima "..filename.." could not be loaded");
            else
                local translation;
                local rotation;
                if balePlace > 0 then
                    translation = {x,y,z};
                    rotation={xRot, yRot, zRot};
                else
                    translation = {0,0,0};
                    rotation={0,0,0};
                end;
                local parentNode = nil;
                local bales = nil;
                if balePlace < 1 then
                    
                elseif balePlace <= table.getn(self.ultima) then
                    parentNode = self.ultima[balePlace].node;
                    bales = self.ultima[balePlace].baleId;
                end;
                if parentNode ~= nil then
                    local baleValueScale = getXMLFloat(savegame.xmlFile, baleKey.."#baleValueScale");
                    local wrappingState = getXMLFloat(savegame.xmlFile, baleKey.."#wrappingState");
                    table.insert(self.ultimaToLoad, {parentNode=parentNode, filename=filename, bales=bales, translation=translation, rotation=rotation, fillLevel=fillLevel, baleValueScale=baleValueScale, wrappingState=wrappingState});
                end;
            end;
        end;
        i = i +1;
    end;

    local i=0;
    while true do
        local baleKey = key..string.format(".ultima4(%d)", i);
        if not hasXMLProperty(savegame.xmlFile, baleKey) then
            break;
        end;
        local filename = getXMLString(savegame.xmlFile, baleKey.."#filename");
        if filename ~= nil then
            filename = Utils.convertFromNetworkFilename(filename);
            local x,y,z = Utils.getVectorFromString(getXMLString(savegame.xmlFile, baleKey.."#position"));
            local xRot,yRot,zRot = Utils.getVectorFromString(getXMLString(savegame.xmlFile, baleKey.."#rotation"));
            local fillLevel = getXMLFloat(savegame.xmlFile, baleKey.."#fillLevel");
            local balePlace = getXMLInt(savegame.xmlFile, baleKey.."#balePlace");
            local helper = getXMLInt(savegame.xmlFile, baleKey.."#helper");
            if balePlace == nil or (balePlace > 0 and (x == nil or y == nil or z == nil or xRot == nil or yRot == nil or zRot == nil)) or (balePlace < 1 and helper == nil) then
                print("Warning: Corrupt savegame, ultima4 "..filename.." could not be loaded");
            else
                local translation;
                local rotation;
                if balePlace > 0 then
                    translation = {x,y,z};
                    rotation={xRot, yRot, zRot};
                else
                    translation = {0,0,0};
                    rotation={0,0,0};
                end;
                local parentNode = nil;
                local bales = nil;
                if balePlace < 1 then
                    
                elseif balePlace <= table.getn(self.ultima4) then
                    parentNode = self.ultima4[balePlace].node;
                    bales = self.ultima4[balePlace].baleId;
                end;
                if parentNode ~= nil then
                    local baleValueScale = getXMLFloat(savegame.xmlFile, baleKey.."#baleValueScale");
                    local wrappingState = getXMLFloat(savegame.xmlFile, baleKey.."#wrappingState");
                    table.insert(self.ultima4ToLoad, {parentNode=parentNode, filename=filename, bales=bales, translation=translation, rotation=rotation, fillLevel=fillLevel, baleValueScale=baleValueScale, wrappingState=wrappingState});
                end;
            end;
        end;
        i = i +1;
    end;

    local i=0;
    while true do
        local baleKey = key..string.format(".hdbales(%d)", i);
        if not hasXMLProperty(savegame.xmlFile, baleKey) then
            break;
        end;
        local filename = getXMLString(savegame.xmlFile, baleKey.."#filename");
        if filename ~= nil then
            filename = Utils.convertFromNetworkFilename(filename);
            local x,y,z = Utils.getVectorFromString(getXMLString(savegame.xmlFile, baleKey.."#position"));
            local xRot,yRot,zRot = Utils.getVectorFromString(getXMLString(savegame.xmlFile, baleKey.."#rotation"));
            local fillLevel = getXMLFloat(savegame.xmlFile, baleKey.."#fillLevel");
            local balePlace = getXMLInt(savegame.xmlFile, baleKey.."#balePlace");
            local helper = getXMLInt(savegame.xmlFile, baleKey.."#helper");
            if balePlace == nil or (balePlace > 0 and (x == nil or y == nil or z == nil or xRot == nil or yRot == nil or zRot == nil)) or (balePlace < 1 and helper == nil) then
                print("Warning: Corrupt savegame, hdbales "..filename.." could not be loaded");
            else
                local translation;
                local rotation;
                if balePlace > 0 then
                    translation = {x,y,z};
                    rotation={xRot, yRot, zRot};
                else
                    translation = {0,0,0};
                    rotation={0,0,0};
                end;
                local parentNode = nil;
                local bales = nil;
                if balePlace < 1 then
                    
                elseif balePlace <= table.getn(self.hdbales) then
                    parentNode = self.hdbales[balePlace].node;
                    bales = self.hdbales[balePlace].baleId;
                end;
                if parentNode ~= nil then
                    local baleValueScale = getXMLFloat(savegame.xmlFile, baleKey.."#baleValueScale");
                    local wrappingState = getXMLFloat(savegame.xmlFile, baleKey.."#wrappingState");
                    table.insert(self.hdbalesToLoad, {parentNode=parentNode, filename=filename, bales=bales, translation=translation, rotation=rotation, fillLevel=fillLevel, baleValueScale=baleValueScale, wrappingState=wrappingState});
                end;
            end;
        end;
        i = i +1;
    end;
    
    return BaseMission.VEHICLE_LOAD_OK;
end;

function UAL:getSaveAttributesAndNodes(nodeIdent)
    local attributes = 'numBales="'..tostring(self.counter)..'"'..' baleMode="'..tostring(self.state)..'"';
    local nodes = "";
    local baleNum = 0;
    
    for i, balePlace in pairs(self.hayBales) do
        if balePlace.baleId ~= nil then
            local bale = networkGetObject(balePlace.baleId);
            if bale ~= nil then
                local nodeId = bale.nodeId;
                local x,y,z = getTranslation(nodeId);
                local rx,ry,rz = getRotation(nodeId);
                if baleNum>0 then
                    nodes = nodes.."\n";
                end;
                local wrappingState = Utils.getNoNil(bale.wrappingState, 0);
                local baleValueScale = Utils.getNoNil(bale.baleValueScale, 1);
                nodes = nodes..nodeIdent..'<bale filename="'..Utils.encodeToHTML(Utils.convertToNetworkFilename(bale.i3dFilename))..'" fillLevel="'..bale:getFillLevel()..'" position="'..x..' '..y..' '..z..'" rotation="'..rx..' '..ry..' '..rz..'" wrappingState="'..wrappingState..'" baleValueScale="'..baleValueScale..'" balePlace="'..i..'" />';
                baleNum = baleNum+1;
            end;
        end;
    end;
    
    local baleNum = 0;
    for i, balePlace in pairs(self.hayRounds) do
        if balePlace.baleId ~= nil then
            local bale = networkGetObject(balePlace.baleId);
            if bale ~= nil then
                local nodeId = bale.nodeId;
                local x,y,z = getTranslation(nodeId);
                local rx,ry,rz = getRotation(nodeId);
                if baleNum>0 then
                    nodes = nodes.."\n";
                end;
                local wrappingState = Utils.getNoNil(bale.wrappingState, 0);
                local baleValueScale = Utils.getNoNil(bale.baleValueScale, 1);
                nodes = nodes..nodeIdent..'<rbale filename="'..Utils.encodeToHTML(Utils.convertToNetworkFilename(bale.i3dFilename))..'" fillLevel="'..bale:getFillLevel()..'" position="'..x..' '..y..' '..z..'" rotation="'..rx..' '..ry..' '..rz..'" wrappingState="'..wrappingState..'" baleValueScale="'..baleValueScale..'" balePlace="'..i..'" />';
                baleNum = baleNum+1;
            end;
        end;
    end;
    
    local baleNum = 0;
    for i, balePlace in pairs(self.wool) do
        if balePlace.baleId ~= nil then
            local bale = networkGetObject(balePlace.baleId);
            if bale ~= nil then
                local nodeId = bale.nodeId;
                local x,y,z = getTranslation(nodeId);
                local rx,ry,rz = getRotation(nodeId);
                if baleNum>0 then
                    nodes = nodes.."\n";
                end;
                local wrappingState = Utils.getNoNil(bale.wrappingState, 0);
                local baleValueScale = Utils.getNoNil(bale.baleValueScale, 1);
                nodes = nodes..nodeIdent..'<wool filename="'..Utils.encodeToHTML(Utils.convertToNetworkFilename(bale.i3dFilename))..'" fillLevel="'..bale:getFillLevel()..'" position="'..x..' '..y..' '..z..'" rotation="'..rx..' '..ry..' '..rz..'" wrappingState="'..wrappingState..'" baleValueScale="'..baleValueScale..'" balePlace="'..i..'" />';
                baleNum = baleNum+1;
            end;
        end;
    end;

    local baleNum = 0;
    for i, balePlace in pairs(self.ultima) do
        if balePlace.baleId ~= nil then
            local bale = networkGetObject(balePlace.baleId);
            if bale ~= nil then
                local nodeId = bale.nodeId;
                local x,y,z = getTranslation(nodeId);
                local rx,ry,rz = getRotation(nodeId);
                if baleNum>0 then
                    nodes = nodes.."\n";
                end;
                local wrappingState = Utils.getNoNil(bale.wrappingState, 0);
                local baleValueScale = Utils.getNoNil(bale.baleValueScale, 1);
                nodes = nodes..nodeIdent..'<ultima filename="'..Utils.encodeToHTML(Utils.convertToNetworkFilename(bale.i3dFilename))..'" fillLevel="'..bale:getFillLevel()..'" position="'..x..' '..y..' '..z..'" rotation="'..rx..' '..ry..' '..rz..'" wrappingState="'..wrappingState..'" baleValueScale="'..baleValueScale..'" balePlace="'..i..'" />';
                baleNum = baleNum+1;
            end;
        end;
    end;
    
    local baleNum = 0;
    for i, balePlace in pairs(self.ultima4) do
        if balePlace.baleId ~= nil then
            local bale = networkGetObject(balePlace.baleId);
            if bale ~= nil then
                local nodeId = bale.nodeId;
                local x,y,z = getTranslation(nodeId);
                local rx,ry,rz = getRotation(nodeId);
                if baleNum>0 then
                    nodes = nodes.."\n";
                end;
                local wrappingState = Utils.getNoNil(bale.wrappingState, 0);
                local baleValueScale = Utils.getNoNil(bale.baleValueScale, 1);
                nodes = nodes..nodeIdent..'<ultima4 filename="'..Utils.encodeToHTML(Utils.convertToNetworkFilename(bale.i3dFilename))..'" fillLevel="'..bale:getFillLevel()..'" position="'..x..' '..y..' '..z..'" rotation="'..rx..' '..ry..' '..rz..'" wrappingState="'..wrappingState..'" baleValueScale="'..baleValueScale..'" balePlace="'..i..'" />';
                baleNum = baleNum+1;
            end;
        end;
    end;
    
    local baleNum = 0;
    for i, balePlace in pairs(self.hdbales) do
        if balePlace.baleId ~= nil then
            local bale = networkGetObject(balePlace.baleId);
            if bale ~= nil then
                local nodeId = bale.nodeId;
                local x,y,z = getTranslation(nodeId);
                local rx,ry,rz = getRotation(nodeId);
                if baleNum>0 then
                    nodes = nodes.."\n";
                end;
                local wrappingState = Utils.getNoNil(bale.wrappingState, 0);
                local baleValueScale = Utils.getNoNil(bale.baleValueScale, 1);
                nodes = nodes..nodeIdent..'<hdbales filename="'..Utils.encodeToHTML(Utils.convertToNetworkFilename(bale.i3dFilename))..'" fillLevel="'..bale:getFillLevel()..'" position="'..x..' '..y..' '..z..'" rotation="'..rx..' '..ry..' '..rz..'" wrappingState="'..wrappingState..'" baleValueScale="'..baleValueScale..'" balePlace="'..i..'" />';
                baleNum = baleNum+1;
            end;
        end;
    end;

    return attributes,nodes;
end;

function UAL:readStream(streamId, connection)
    self.workMode = streamReadBool(streamId);
    self.counter = streamReadInt32(streamId);
    
    self.fillLevel = streamReadFloat32(streamId);
    self.state = streamReadInt32(streamId);
    
    for i=1, table.getn(self.hayBales) do
        local baleServerId = streamReadFloat32(streamId);
        if baleServerId == 4711 then
            baleServerId = nil;
        end
        self.hayBales[i].baleId = baleServerId;
        if baleServerId ~= nil then
            self.balesToMount[baleServerId] = {serverId=baleServerId, linkNode=self.hayBales[i].node, trans={ 0,0,0}, rot={0,0,0} };
        end
    end;
    for i=1, table.getn(self.hayRounds) do
        local baleServerId = streamReadFloat32(streamId);
        if baleServerId == 4711 then
            baleServerId = nil;
        end
        self.hayRounds[i].baleId = baleServerId;
        if baleServerId ~= nil then
            self.rbalesToMount[baleServerId] = {serverId=baleServerId, linkNode=self.hayRounds[i].node, trans={ 0,0,0}, rot={0,0,0} };
        end
    end;
    for i=1, table.getn(self.wool) do
        local baleServerId = streamReadFloat32(streamId);
        if baleServerId == 4711 then
            baleServerId = nil;
        end
        self.wool[i].baleId = baleServerId;
        if baleServerId ~= nil then
            self.woolToMount[baleServerId] = {serverId=baleServerId, linkNode=self.wool[i].node, trans={ 0,0,0}, rot={0,0,0} };
        end
    end;
    for i=1, table.getn(self.ultima) do
        local baleServerId = streamReadFloat32(streamId);
        if baleServerId == 4711 then
            baleServerId = nil;
        end
        self.ultima[i].baleId = baleServerId;
        if baleServerId ~= nil then
            self.ultimaToMount[baleServerId] = {serverId=baleServerId, linkNode=self.ultima[i].node, trans={ 0,0,0}, rot={0,0,0} };
        end
    end;
    for i=1, table.getn(self.ultima4) do
        local baleServerId = streamReadFloat32(streamId);
        if baleServerId == 4711 then
            baleServerId = nil;
        end
        self.ultima4[i].baleId = baleServerId;
        if baleServerId ~= nil then
            self.ultima4ToMount[baleServerId] = {serverId=baleServerId, linkNode=self.ultima4[i].node, trans={ 0,0,0}, rot={0,0,0} };
        end
    end;
    for i=1, table.getn(self.hdbales) do
        local baleServerId = streamReadFloat32(streamId);
        if baleServerId == 4711 then
            baleServerId = nil;
        end
        self.hdbales[i].baleId = baleServerId;
        if baleServerId ~= nil then
            self.hdbalesToMount[baleServerId] = {serverId=baleServerId, linkNode=self.hdbales[i].node, trans={ 0,0,0}, rot={0,0,0} };
        end
    end;
end;

function UAL:writeStream(streamId, connection)

    streamWriteBool(streamId, self.workMode);
    streamWriteInt32(streamId, self.counter);

    streamWriteFloat32(streamId, self.fillLevel);
    streamWriteInt32(streamId, self.state);
    
    for i=1, table.getn(self.hayBales) do
        local baleServerId = Utils.getNoNil(self.hayBales[i].baleId, 4711);
        streamWriteFloat32(streamId, baleServerId);
    end;
    for i=1, table.getn(self.hayRounds) do
        local baleServerId = Utils.getNoNil(self.hayRounds[i].baleId, 4711);
        streamWriteFloat32(streamId, baleServerId);
    end;
    for i=1, table.getn(self.wool) do
        local baleServerId = Utils.getNoNil(self.wool[i].baleId, 4711);
        streamWriteFloat32(streamId, baleServerId);
    end;
    for i=1, table.getn(self.ultima) do
        local baleServerId = Utils.getNoNil(self.ultima[i].baleId, 4711);
        streamWriteFloat32(streamId, baleServerId);
    end;
    for i=1, table.getn(self.ultima4) do
        local baleServerId = Utils.getNoNil(self.ultima4[i].baleId, 4711);
        streamWriteFloat32(streamId, baleServerId);
    end;
    for i=1, table.getn(self.hdbales) do
        local baleServerId = Utils.getNoNil(self.hdbales[i].baleId, 4711);
        streamWriteFloat32(streamId, baleServerId);
    end;
end;
function UAL:objectCallbackUAL(triggerId, otherId, onEnter, onLeave, onStay)
    
    if onEnter and self.workMode then
        local object = g_currentMission:getNodeObject(otherId);
        if object == nil or object.mountObject ~= nil then
            return
        end
        if self.isServer and (object:isa(Bale) or object:isa(FillablePallet)) then
            --self:FiHeBa(object);
            self.foundIt = false;
            local baleDiameter = tonumber(getUserAttribute(object.nodeId, "baleDiameter"));
            local isRoundbale = Utils.getNoNil(getUserAttribute(object.nodeId, "isRoundbale"), false);
            local isHDbale = Utils.getNoNil(getUserAttribute(object.nodeId, "isHDbale"), false);
            if baleDiameter == nil then
                local baleDiameter = 0;
            end
    
            self.baleId = nil;
            if (self.state == 1 and not isRoundbale and not isHDbale and (object:isa(Bale))) or
            (self.state == 2 and isRoundbale and baleDiameter <= 1.3) or
            (self.state == 3 and isRoundbale and baleDiameter > 1.3 and baleDiameter <= 1.4) or
            (self.state == 4 and isRoundbale and baleDiameter > 1.4 and baleDiameter <= 1.5) or
            (self.state == 5 and isHDbale) or           
            (self.state == 6 and object:isa(FillablePallet)) then
                self.foundIt = true;
                self.baleId = networkGetObjectId(object);
                self:MPCode(21, false, self.state, self.baleId, 0, false);
                if self.counter == self.fillLevelMax then
                    self:MPCode(99, false, 0, 0, 0, false);
                end;
            end;
            --
            --print(self.counter .. " / " .. self.fillLevelMax .. " / " .. otherId)
        end
    end;
end;