source(Utils.getFilename("scripts/Mchale998StateEvent.lua", g_currentModDirectory))
source(Utils.getFilename("scripts/BaleFix.lua", g_currentModDirectory))
Mchale998 = {}
Mchale998.STATE_NONE = 0
Mchale998.STATE_MOVING_BALE_TO_WRAPPER = 1
Mchale998.STATE_MOVING_GRABBER_TO_WORK = 2
Mchale998.STATE_WRAPPER_WRAPPING_BALE = 3
Mchale998.STATE_WRAPPER_FINISHED = 4
Mchale998.STATE_WRAPPER_DROPPING_BALE = 5
Mchale998.STATE_WRAPPER_RESETTING_PLATFORM = 6
Mchale998.STATE_NUM_BITS = 3
Mchale998.CHANGE_GRAB_BALE = 1
Mchale998.CHANGE_DROP_BALE_AT_GRABBER = 2
Mchale998.CHANGE_WRAPPING_START = 3
Mchale998.CHANGE_WRAPPING_BALE_FINISHED = 4
Mchale998.CHANGE_WRAPPER_START_DROP_BALE = 5
Mchale998.CHANGE_WRAPPER_BALE_DROPPED = 6
Mchale998.CHANGE_WRAPPER_PLATFORM_RESET = 7
Mchale998.CHANGE_BUTTON_EMPTY = 8
function Mchale998.prerequisitesPresent(specializations)
  return SpecializationUtil.hasSpecialization(AnimatedVehicle, specializations)
end
function Mchale998:load(xmlFile)
  self.getIsFoldAllowed = Utils.overwrittenFunction(self.getIsFoldAllowed, Mchale998.getIsFoldAllowed)
  self.allowsGrabbingBale = Mchale998.allowsGrabbingBale
  self.updateWrappingState = Mchale998.updateWrappingState
  self.dropBaleFromWrapper = Mchale998.dropBaleFromWrapper
  self.moveBaleToWrapper = Mchale998.moveBaleToWrapper
  self.doStateChange = Mchale998.doStateChange
  self.updateWrapNodes = Mchale998.updateWrapNodes
  local wrapper = {}
  wrapper.baleNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.wrapper#baleIndex"))
  wrapper.wrapperNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.wrapper#index"))
  local wrappingAnimCurve = AnimCurve:new(linearInterpolatorN)
  local keyI = 0
  do
    local key = string.format("vehicle.wrapper.key(%d)", keyI)
    local t = getXMLFloat(xmlFile, key .. "#time")
    local baleX, baleY, baleZ = Utils.getVectorFromString(getXMLString(xmlFile, key .. "#baleRot"))
    while baleX ~= nil and baleY ~= nil do
      local key = string.format("vehicle.wrapper.key(%d)", keyI)
      local t = getXMLFloat(xmlFile, key .. "#time")
      local baleX, baleY, baleZ = Utils.getVectorFromString(getXMLString(xmlFile, key .. "#baleRot"))
      if baleZ == nil then
        break
      end
      baleX = math.rad(Utils.getNoNil(baleX, 0))
      baleY = math.rad(Utils.getNoNil(baleY, 0))
      baleZ = math.rad(Utils.getNoNil(baleZ, 0))
      local wrapperX, wrapperY, wrapperZ = Utils.getVectorFromString(getXMLString(xmlFile, key .. "#wrapperRot"))
      wrapperX = math.rad(Utils.getNoNil(wrapperX, 0))
      wrapperY = math.rad(Utils.getNoNil(wrapperY, 0))
      wrapperZ = math.rad(Utils.getNoNil(wrapperZ, 0))
      wrappingAnimCurve:addKeyframe({v = {baleX,baleY,baleZ,wrapperX,wrapperY,wrapperZ},time = t})
      keyI = keyI + 1
    end
  end
  wrapper.animCurve = wrappingAnimCurve
  wrapper.animTime = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.wrapper#wrappingTime"), 5) * 1000
  wrapper.currentTime = 0
  wrapper.currentBale = nil
  wrapper.foldMinLimit = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.wrapper#foldMinLimit"), 0)
  wrapper.foldMaxLimit = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.wrapper#foldMaxLimit"), 1)
  self.wrapper = wrapper
  self.showInvalidBaleWarning = false
  self.allowedBaleTypes = {}
  local i = 0
  while true do
    do
      local key = string.format("vehicle.wrapper.baleType(%d)", i)
      if not hasXMLProperty(xmlFile, key) then
        break
      end
      local wrapperBaleFilename = Utils.getFilename(getXMLString(xmlFile, key .. "#wrapperBaleFilename"), self.baseDirectory)
      local fillTypeStr = getXMLString(xmlFile, key .. "#fillType")
      if fillTypeStr ~= nil then
        local fillType = Fillable.fillTypeNameToInt[fillTypeStr]
        if wrapperBaleFilename ~= nil and fillType ~= nil then
          if self.allowedBaleTypes[fillType] == nil then
            self.allowedBaleTypes[fillType] = {}
          end
          table.insert(self.allowedBaleTypes[fillType], {wrapperBaleFilename = wrapperBaleFilename,fillType = fillType})
        end
      end
      i = i + 1
    end
  end
  local wrapAnimNodes = {}
  local wrapAnimNodeI = 0
  while true do
    do
      local wrapAnimNodeKey = string.format("vehicle.wrapper.wrapAnimNode(%d)", wrapAnimNodeI)
      if not hasXMLProperty(xmlFile, wrapAnimNodeKey) then
        break
      end
      local nodeId = Utils.indexToObject(self.components, getXMLString(xmlFile, wrapAnimNodeKey .. "#index"))
      if nodeId ~= nil then
        local animCurve = AnimCurve:new(linearInterpolatorN)
        local keyI = 0
        while true do
          do
            local key = string.format(wrapAnimNodeKey .. ".key(%d)", keyI)
            local wrapperRot = getXMLFloat(xmlFile, key .. "#wrapperRot")
            if wrapperRot == nil then
              break
            end
            local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, key .. "#trans"))
            local rx, ry, rz = Utils.getVectorFromString(getXMLString(xmlFile, key .. "#rot"))
            local sx, sy, sz = Utils.getVectorFromString(getXMLString(xmlFile, key .. "#scale"))
            x = Utils.getNoNil(x, 0)
            y = Utils.getNoNil(y, 0)
            z = Utils.getNoNil(z, 0)
            rx = math.rad(Utils.getNoNil(rx, 0))
            ry = math.rad(Utils.getNoNil(ry, 0))
            rz = math.rad(Utils.getNoNil(rz, 0))
            sx = Utils.getNoNil(sx, 1)
            sy = Utils.getNoNil(sy, 1)
            sz = Utils.getNoNil(sz, 1)
            animCurve:addKeyframe({v = {x,y,z,rx,ry,rz,sx,sy,sz},time = math.rad(wrapperRot)})
            keyI = keyI + 1
          end
        end
        if keyI > 0 then
          local repeatWrapperRot = Utils.getNoNil(getXMLBool(xmlFile, wrapAnimNodeKey .. "#repeatWrapperRot"), false)
          table.insert(wrapAnimNodes, {nodeId = nodeId,animCurve = animCurve,repeatWrapperRot = repeatWrapperRot })
        end
      end
      wrapAnimNodeI = wrapAnimNodeI + 1
    end
  end
  self.wrapAnimNodes = wrapAnimNodes
  local wrapNodes = {}
  local wrapNodeI = 0
  while true do
    do
      local wrapNodeKey = string.format("vehicle.wrapper.wrapNode(%d)", wrapNodeI)
      if not hasXMLProperty(xmlFile, wrapNodeKey) then
        break
      end
      local nodeId = Utils.indexToObject(self.components, getXMLString(xmlFile, wrapNodeKey .. "#index"))
      local wrapVisibility = Utils.getNoNil(getXMLBool(xmlFile, wrapNodeKey .. "#wrapVisibility"), false)
      local emptyVisibility = Utils.getNoNil(getXMLBool(xmlFile, wrapNodeKey .. "#emptyVisibility"), false)
      if nodeId ~= nil and (wrapVisibility or emptyVisibility) then
        local maxWrapperRot = getXMLFloat(xmlFile, wrapNodeKey .. "#maxWrapperRot")
        if maxWrapperRot == nil then
          maxWrapperRot = math.huge
        else
          maxWrapperRot = math.rad(maxWrapperRot)
        end
        table.insert(wrapNodes, {nodeId = nodeId,wrapVisibility = wrapVisibility,emptyVisibility = emptyVisibility,maxWrapperRot = maxWrapperRot})
      end
      wrapNodeI = wrapNodeI + 1
    end
  end
  self.wrapNodes = wrapNodes
  self:updateWrapNodes(false, true, 0)
  self.baleGrabber = {}
  self.baleGrabber.grabNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.baleGrabber#index"))
  self.baleGrabber.nearestDistance = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.baleGrabber#nearestDistance"), 3)
  if self.isClient then
    self.wrapperSound = {}
    Utils.loadSample(xmlFile, self.wrapperSound, "vehicle.wrapperSound", nil, self.baseDirectory)
    self.wrapperStartSound = {}
    Utils.loadSample(xmlFile, self.wrapperStartSound, "vehicle.wrapperStartSound", nil, self.baseDirectory)
    self.wrapperStopSound = {}
    Utils.loadSample(xmlFile, self.wrapperStopSound, "vehicle.wrapperStopSound", nil, self.baseDirectory)
  end
  self.baleToLoad = nil
  self.baleToMount = nil
  self.baleWrapperState = Mchale998.STATE_NONE
  self.grabberIsMoving = false
  self.hasMchale998 = true
  self.mchale998UVScrollParts = {}
  local i = 0
  while true do
    do
      local key = string.format("vehicle.mchale998UVScrollParts.mchale998UVScrollPart(%d)", i)
      if not hasXMLProperty(xmlFile, key) then
        break
      end
      local node = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#index"))
      local speed = Utils.getVectorNFromString(getXMLString(xmlFile, key .. "#speed"), 2)
      if node ~= nil and speed then
        table.insert(self.mchale998UVScrollParts, {node = node, speed = speed})
      end
      i = i + 1
    end
  end
  self.mchale9981UVScrollParts = {}
  local i = 0
  while true do
    do
      local key = string.format("vehicle.mchale9981UVScrollParts.mchale9981UVScrollPart(%d)", i)
      if not hasXMLProperty(xmlFile, key) then
        break
      end
      local node = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#index"))
      local speed = Utils.getVectorNFromString(getXMLString(xmlFile, key .. "#speed"), 2)
      if node ~= nil and speed then
        table.insert(self.mchale9981UVScrollParts, {node = node, speed = speed})
      end
      i = i + 1
    end
  end
  for i, jointDesc in pairs(self.componentJoints) do
	setJointFrame(self.componentJoints[i].jointIndex, 0, self.componentJoints[i].jointNode);
  end;
end
function Mchale998:delete()
  if self.isClient then
    Utils.deleteSample(self.wrapperSound)
    Utils.deleteSample(self.wrapperStartSound)
    Utils.deleteSample(self.wrapperStopSound)
  end
  local bale = networkGetObject(self.wrapper.currentBale)
  if bale ~= nil then
    bale:unmount()
  end 
  local grabberbale = networkGetObject(self.baleGrabber.currentBale)
  if grabberbale ~= nil then
	grabberbale:unmount()
  end
end;

function Mchale998:readStream(streamId, connection)
  if connection:getIsServer() then
    local wrapperState = streamReadUIntN(streamId, Mchale998.STATE_NUM_BITS)
    if wrapperState >= Mchale998.STATE_MOVING_BALE_TO_WRAPPER then
      local baleServerId
      if wrapperState ~= Mchale998.STATE_WRAPPER_RESETTING_PLATFORM then
        baleServerId = streamReadInt32(streamId)
      end
      if wrapperState == Mchale998.STATE_MOVING_BALE_TO_WRAPPER then
        self:doStateChange(Mchale998.CHANGE_GRAB_BALE, baleServerId)
        AnimatedVehicle.updateAnimations(self, 99999999)
      elseif wrapperState == Mchale998.STATE_MOVING_GRABBER_TO_WORK then
        self.baleGrabber.currentBale = baleServerId
        self:doStateChange(Mchale998.CHANGE_DROP_BALE_AT_GRABBER)
        AnimatedVehicle.updateAnimations(self, 99999999)
      elseif wrapperState ~= Mchale998.STATE_WRAPPER_RESETTING_PLATFORM then
        do
          local attachNode = self.wrapper.baleNode
          self.baleToMount = {serverId = baleServerId,linkNode = attachNode,trans = {0,0,0},rot = {0,0,0} }
          self:updateWrapNodes(true, false, 0)
          self.wrapper.currentBale = baleServerId
          if wrapperState == Mchale998.STATE_WRAPPER_WRAPPING_BALE then
            do
              local wrapperTime = streamReadFloat32(streamId)
              self.wrapper.currentTime = wrapperTime
              self:updateWrappingState(self.wrapper.currentTime / self.wrapper.animTime, true)
            end
          else
            self.wrapper.currentTime = self.wrapper.animTime
            self:updateWrappingState(1, true)
            self:doStateChange(Mchale998.CHANGE_WRAPPING_BALE_FINISHED)
            AnimatedVehicle.updateAnimations(self, 99999999)
            if wrapperState >= Mchale998.STATE_WRAPPER_DROPPING_BALE then
              self:doStateChange(Mchale998.CHANGE_WRAPPER_START_DROP_BALE)
              AnimatedVehicle.updateAnimations(self, 99999999)
            end
          end
        end
      else
        self.baleWrapperState = Mchale998.STATE_WRAPPER_RESETTING_PLATFORM
      end
    end
  end
end
function Mchale998:writeStream(streamId, connection)
  if not connection:getIsServer() then
    local wrapperState = self.baleWrapperState
    streamWriteUIntN(streamId, wrapperState, Mchale998.STATE_NUM_BITS)
    if wrapperState >= Mchale998.STATE_MOVING_BALE_TO_WRAPPER and wrapperState ~= Mchale998.STATE_WRAPPER_RESETTING_PLATFORM then
      if wrapperState == Mchale998.STATE_MOVING_BALE_TO_WRAPPER then
        streamWriteInt32(streamId, self.baleGrabber.currentBale)
      else
        streamWriteInt32(streamId, self.wrapper.currentBale)
      end
    end
    if wrapperState == Mchale998.STATE_WRAPPER_WRAPPING_BALE then
      streamWriteFloat32(streamId, self.wrapper.currentTime)
    end
  end
end

function Mchale998:mouseEvent(posX, posY, isDown, isUp, button)
end
function Mchale998:keyEvent(unicode, sym, modifier, isDown)
end
function Mchale998:update(dt)
  if self.firstTimeRun then
    if self.baleToLoad ~= nil then
      local v = self.baleToLoad
      self.baleToLoad = nil
      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)
      if baleObject.nodeId ~= nil and baleObject.nodeId ~= 0 then
        local wrapperState = math.min(v.wrapperTime / self.wrapper.animTime, 1)
        baleObject:setWrappingState(wrapperState)
        baleObject:mount(self, v.parentNode, x, y, z, rx, ry, rz)
        baleObject:register()
        self:doStateChange(Mchale998.CHANGE_WRAPPING_START)
        self.wrapper.currentBale = networkGetObjectId(baleObject)
        self.wrapper.currentTime = v.wrapperTime
        self:updateWrappingState(self.wrapper.currentTime / self.wrapper.animTime)
      end
    end
    if self.baleToMount ~= nil then
      local bale = networkGetObject(self.baleToMount.serverId)
      if bale ~= nil then
        local x, y, z = unpack(self.baleToMount.trans)
        local rx, ry, rz = unpack(self.baleToMount.rot)
        bale:mount(self, self.baleToMount.linkNode, x, y, z, rx, ry, rz)
        self.baleToMount = nil
      end
    end
  end
  if self:getIsActive() then
    if self:getIsActiveForInput() and self.baleWrapperState == Mchale998.STATE_WRAPPER_FINISHED and InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA3) then
      g_client:getServerConnection():sendEvent(Mchale998StateEvent:new(self, Mchale998.CHANGE_BUTTON_EMPTY))
    end
    if self:getIsActiveForInput() and self.baleWrapperState == Mchale998.STATE_NONE and InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA2) then
		  for _, part in pairs(self.mchale998UVScrollParts) do
            setShaderParameter(part.node, "uvScrollSpeed", 0, 0, 0, 0, false)
          end
    end
    if self.baleWrapperState == Mchale998.STATE_WRAPPER_WRAPPING_BALE then
      if self.isClient and self:getIsActiveForSound() and not self.wrapperSound.isPlaying and (self.wrapperStartSound.sample == nil or not isSamplePlaying(self.wrapperStartSound.sample) or getSamplePlayOffset(self.wrapperStartSound.sample) >= self.wrapperStartSound.duration - 1.8 * dt) then
        Utils.playSample(self.wrapperSound, 0, 0)
      end
      self.wrapper.currentTime = self.wrapper.currentTime + dt
      self:updateWrappingState(self.wrapper.currentTime / self.wrapper.animTime)
	  
    end
	local foldAnimTime = self.foldAnimTime


  end

  if self.baleWrapperState == Mchale998.STATE_MOVING_BALE_TO_WRAPPER then
	if not self:getIsAnimationPlaying("moveBaleToWrapper") then
		transportband = false
	end
  end
	
  if transportband == true then
      for _, part in pairs(self.mchale9981UVScrollParts) do
        setShaderParameter(part.node, "uvScrollSpeed", part.speed[1], part.speed[2], 0, 0, false)
      end
  else 
      for _, part in pairs(self.mchale9981UVScrollParts) do
        setShaderParameter(part.node, "uvScrollSpeed", 0, 0, 0, 0, false)
      end
  end
    for i, jointDesc in pairs(self.componentJoints) do
	setJointFrame(self.componentJoints[i].jointIndex, 0, self.componentJoints[i].jointNode);
    end;
end
function Mchale998:updateTick(dt)
  if self:getIsActive() then
    self.showInvalidBaleWarning = false
    if self:allowsGrabbingBale() and self.baleGrabber.grabNode ~= nil and self.baleGrabber.currentBale == nil then
      local nearestBale, nearestBaleType = Mchale998.getBaleInRange(self, self.baleGrabber.grabNode)
      if nearestBale ~= nil then
        if nearestBaleType == nil or roundbale == true or wrapstate == true then
          self.showInvalidBaleWarning = true
        elseif self.isServer then
          if nearestBale.i3dFilename ~= nearestBaleType.wrapperBaleFilename then
            local fillLevel = nearestBale.fillLevel
            nearestBale:delete()
            nearestBale = Bale:new(self.isServer, self.isClient)
            nearestBale:load(nearestBaleType.wrapperBaleFilename, 0, 0, 0, 0, 0, 0, fillLevel)
            nearestBale:register()
          end
          g_server:broadcastEvent(Mchale998StateEvent:new(self, Mchale998.CHANGE_GRAB_BALE, networkGetObjectId(nearestBale)), true, nil, self)
        end
      end
    end
    if self.isServer and self.baleWrapperState ~= Mchale998.STATE_NONE then
      if self.baleWrapperState == Mchale998.STATE_MOVING_BALE_TO_WRAPPER then
        if not self:getIsAnimationPlaying("moveBaleToWrapper") then
          g_server:broadcastEvent(Mchale998StateEvent:new(self, Mchale998.CHANGE_DROP_BALE_AT_GRABBER), true, nil, self)
        end
      elseif self.baleWrapperState == Mchale998.STATE_MOVING_GRABBER_TO_WORK then
        if not self:getIsAnimationPlaying("moveBaleToWrapper") then
          g_server:broadcastEvent(Mchale998StateEvent:new(self, Mchale998.CHANGE_WRAPPING_START), true, nil, self)
        end
      elseif self.baleWrapperState == Mchale998.STATE_WRAPPER_DROPPING_BALE then
        if not self:getIsAnimationPlaying("dropBaleFromWrapper") then
          g_server:broadcastEvent(Mchale998StateEvent:new(self, Mchale998.CHANGE_WRAPPER_BALE_DROPPED), true, nil, self)
        end
      elseif self.baleWrapperState == Mchale998.STATE_WRAPPER_RESETTING_PLATFORM and not self:getIsAnimationPlaying("resetWrapperAfterBaleDrop") then
        g_server:broadcastEvent(Mchale998StateEvent:new(self, Mchale998.CHANGE_WRAPPER_PLATFORM_RESET), true, nil, self)
      end
    end
end
 
end
function Mchale998:draw()
  if self.isClient then
    if self:getIsActiveForInput(true) and self.baleWrapperState == Mchale998.STATE_WRAPPER_FINISHED then
      g_currentMission:addHelpButtonText(g_i18n:getText("Mchale998_unload"), InputBinding.IMPLEMENT_EXTRA3)
    end
    if self.showInvalidBaleWarning then
      g_currentMission:addWarning(g_i18n:getText("InvalidBaleWarning"))
    end
  end
end
function Mchale998:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
  if not resetVehicles then
    local filename = getXMLString(xmlFile, key .. "#baleFileName")
    if filename ~= nil then
      filename = Utils.convertFromNetworkFilename(filename)
      local wrapperTime = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#wrapperTime"), 0)
      local fillLevel = getXMLFloat(xmlFile, key .. "#fillLevel")
      local translation = {0,0,0}
      local rotation = {0,0,0}
      local parentNode = self.wrapper.baleNode
      self.baleToLoad = {parentNode = parentNode,filename = filename,translation = translation,rotation = rotation,fillLevel = fillLevel,wrapperTime = wrapperTime}
    end
  end
  return BaseMission.VEHICLE_LOAD_OK
end
function Mchale998:getSaveAttributesAndNodes(nodeIdent)
  local attributes = ""
  local baleServerId = self.baleGrabber.currentBale
  if baleServerId == nil then
    baleServerId = self.wrapper.currentBale
  end
  if baleServerId ~= nil then
    local bale = networkGetObject(baleServerId)
    if bale ~= nil then
      local fillLevel = bale:getFillLevel()
      attributes = "baleFileName=\"" .. Utils.encodeToHTML(Utils.convertToNetworkFilename(bale.i3dFilename)) .. "\" fillLevel=\"" .. fillLevel .. "\" wrapperTime=\"" .. tostring(self.wrapper.currentTime) .. "\""
    end
  end
  return attributes, nil
end
function Mchale998:onDetach()
  if self.deactivateOnDetach then
    Mchale998.onDeactivate(self)
  else
    Mchale998.onDeactivateSounds(self)
  end
end
function Mchale998:onLeave()
  if self.deactivateOnLeave then
    Mchale998.onDeactivate(self)
  else
    Mchale998.onDeactivateSounds(self)
  end
end
function Mchale998:onDeactivate()
  Mchale998.onDeactivateSounds(self)
  self.showInvalidBaleWarning = false
  for _, part in pairs(self.mchale998UVScrollParts) do
    setShaderParameter(part.node, "uvScrollSpeed", 0, 0, 0, 0, false)
  end
  for _, part in pairs(self.mchale9981UVScrollParts) do
    setShaderParameter(part.node, "uvScrollSpeed", 0, 0, 0, 0, false)
  end
end
function Mchale998:onDeactivateSounds()
  if self.isClient then
    Utils.stopSample(self.wrapperStartSound)
    Utils.stopSample(self.wrapperStopSound)
    Utils.stopSample(self.wrapperSound)
  end
end
function Mchale998:allowsGrabbingBale()
  local foldAnimTime = self.foldAnimTime
  if foldAnimTime ~= nil and (foldAnimTime~= 1) then
    return false
  end
  for _, part in pairs(self.mchale998UVScrollParts) do
	setShaderParameter(part.node, "uvScrollSpeed", part.speed[1], part.speed[2], 0, 0, false)
  end
  return self.baleWrapperState == Mchale998.STATE_NONE
end

function Mchale998:updateWrapNodes(isWrapping, isEmpty, wrapperRot)
  for _, wrapNode in pairs(self.wrapNodes) do
    setVisibility(wrapNode.nodeId, (isWrapping and wrapNode.wrapVisibility or isEmpty and wrapNode.emptyVisibility) and wrapperRot < wrapNode.maxWrapperRot)
  end
  if isWrapping then
    local wrapperRotRepeat = wrapperRot % math.pi
    if wrapperRotRepeat < 0 then
      wrapperRotRepeat = wrapperRotRepeat + math.pi
    end
    for _, wrapAnimNode in pairs(self.wrapAnimNodes) do
      local rot = wrapperRot
      if wrapAnimNode.repeatWrapperRot then
        rot = wrapperRotRepeat
      end
      local v = wrapAnimNode.animCurve:get(rot)
      setTranslation(wrapAnimNode.nodeId, v[1], v[2], v[3])
      setRotation(wrapAnimNode.nodeId, v[4], v[5], v[6])
      setScale(wrapAnimNode.nodeId, v[7], v[8], v[9])
    end
  end
end
function Mchale998:updateWrappingState(t, noEventSend)
  t = math.min(t, 1)
  local wrapperRot = 0
  if self.wrapper.animCurve ~= nil then
    local v = self.wrapper.animCurve:get(t)
    setRotation(self.wrapper.baleNode, v[1] % (math.pi * 2), v[2] % (math.pi * 2), v[3] % (math.pi * 2))
    setRotation(self.wrapper.wrapperNode, v[4] % (math.pi * 2), v[5] % (math.pi * 2), v[6] % (math.pi * 2))
    wrapperRot = v[5]
    if self.wrapper.currentBale ~= nil and self.isServer then
      local bale = networkGetObject(self.wrapper.currentBale)
      if bale ~= nil then
        bale:setWrappingState(t)
      end
    end
  end
  self:updateWrapNodes(t > 0, false, wrapperRot)
  if t == 1 and self.isServer and self.baleWrapperState == Mchale998.STATE_WRAPPER_WRAPPING_BALE and not noEventSend then
    g_server:broadcastEvent(Mchale998StateEvent:new(self, Mchale998.CHANGE_WRAPPING_BALE_FINISHED), true, nil, self)
  end
end
function Mchale998:moveBaleToWrapper(bale)
  self:doStateChange(Mchale998.CHANGE_GRAB_BALE, networkGetObjectId(bale))
end
function Mchale998:doStateChange(id, nearestBaleServerId)
  if id == Mchale998.CHANGE_GRAB_BALE then
    do
      local bale = networkGetObject(nearestBaleServerId)
      self.baleGrabber.currentBale = nearestBaleServerId
      if bale ~= nil then
        bale:mount(self, self.baleGrabber.grabNode, 0, 0, 0, 0, 0, 0)
        self.baleToMount = nil
      else
        self.baleToMount = {serverId = nearestBaleServerId,linkNode = self.baleGrabber.grabNode,trans = {0,0,0},rot = {0,0,0}}
      end
      self.baleWrapperState = Mchale998.STATE_MOVING_BALE_TO_WRAPPER
      self:playAnimation("moveBaleToWrapper", 1, nil, true)
	  transportband = true
    end
  elseif id == Mchale998.CHANGE_DROP_BALE_AT_GRABBER then
    do
      local attachNode = self.wrapper.baleNode
      local bale = networkGetObject(self.baleGrabber.currentBale)
      if bale ~= nil then
        bale:mount(self, attachNode, 0, 0, 0, 0, 0, 0)
        self.baleToMount = nil
      else
        self.baleToMount = {serverId = self.baleGrabber.currentBale,linkNode = attachNode,trans = {0,0,0},rot = {0,0,0}}
      end
      self:updateWrapNodes(true, false, 0)
      self.wrapper.currentBale = self.baleGrabber.currentBale
      self.baleGrabber.currentBale = nil
      self.baleWrapperState = Mchale998.STATE_MOVING_GRABBER_TO_WORK
    end
	transportband = false
  elseif id == Mchale998.CHANGE_WRAPPING_START then
    self.baleWrapperState = Mchale998.STATE_WRAPPER_WRAPPING_BALE
    if self.isClient and self:getIsActiveForSound() then
      Utils.playSample(self.wrapperStartSound, 1, 0)
    end
  elseif id == Mchale998.CHANGE_WRAPPING_BALE_FINISHED then
    if self.isClient then
      Utils.stopSample(self.wrapperSound)
      if self.isClient and self:getIsActiveForSound() then
        Utils.playSample(self.wrapperStopSound, 1, 0)
      end
    end
    self:updateWrappingState(1, true)
    self.baleWrapperState = Mchale998.STATE_WRAPPER_FINISHED
	transportband = false
  elseif id == Mchale998.CHANGE_WRAPPER_START_DROP_BALE then
    self:updateWrapNodes(false, false, 0)
    self:playAnimation("dropBaleFromWrapper", 1, nil, true)
    self.baleWrapperState = Mchale998.STATE_WRAPPER_DROPPING_BALE
	transportband = true
  elseif id == Mchale998.CHANGE_WRAPPER_BALE_DROPPED then
    do
      local bale = networkGetObject(self.wrapper.currentBale)
      if bale ~= nil then
        bale:unmount()
      end
      self.wrapper.currentBale = nil
      self.wrapper.currentTime = 0
      self:playAnimation("resetWrapperAfterBaleDrop", 1, nil, true)
      self.baleWrapperState = Mchale998.STATE_WRAPPER_RESETTING_PLATFORM
    end
	transportband = false
  elseif id == Mchale998.CHANGE_WRAPPER_PLATFORM_RESET then
    self:updateWrappingState(0)
    self:updateWrapNodes(false, true, 0)
    self.baleWrapperState = Mchale998.STATE_NONE
  elseif id == Mchale998.CHANGE_BUTTON_EMPTY then
    assert(self.isServer)
    if self.baleWrapperState == Mchale998.STATE_WRAPPER_FINISHED then
      g_server:broadcastEvent(Mchale998StateEvent:new(self, Mchale998.CHANGE_WRAPPER_START_DROP_BALE), true, nil, self)
    end
  end

end
function Mchale998:setIsUnloadingBale(isUnloadingBale, noEventSend)
  if self.baleUnloadAnimationName ~= nil then
    if isUnloadingBale then
      if self.Mchale998UnloadingState ~= Mchale998.UNLOADING_OPENING then
        Mchale998SetIsUnloadingBaleEvent.sendEvent(self, isUnloadingBale, noEventSend)
        self.Mchale998UnloadingState = Mchale998.UNLOADING_OPENING
        self:playAnimation(self.baleUnloadAnimationName, self.baleUnloadAnimationSpeed, nil, true)
      end
    elseif self.Mchale998UnloadingState ~= Mchale998.UNLOADING_CLOSING then
      Mchale998SetIsUnloadingBaleEvent.sendEvent(self, isUnloadingBale, noEventSend)
      self.Mchale998UnloadingState = Mchale998.UNLOADING_CLOSING
      self:playAnimation(self.baleCloseAnimationName, self.baleCloseAnimationSpeed, nil, true)
    end
  end
end
function Mchale998:getBaleInRange(refNode)
  local nearestDistance = 3

  local px, py, pz = getWorldTranslation(refNode)

  local nearestBale, nearestBaleType
  for index, item in pairs(g_currentMission.itemsToSave) do
    local bale = item.item
    if bale:isa(Bale) then
      local vx, vy, vz = getWorldTranslation(bale.nodeId)
      local distance = Utils.vector3Length(px - vx, py - vy, pz - vz)
      if nearestDistance > distance then
    	    local g_object = nil
	        if g_server ~= nil then
		        g_object = g_server;
	        else
		        g_object = g_client;
	        end

	        if g_object ~= nil then	
		        for i=1, #g_object.objects do
			        if g_object.objects[i] ~= nil and g_object.objects[i].className == "Bale" then
				        itemNode = g_object.objects[i].nodeId;

				        local vx, vy, vz = getWorldTranslation(itemNode);
				        local distance = Utils.vector3Length(px-vx, py-vy, pz-vz);

				        if distance < nearestDistance then
					        if getUserAttribute(itemNode, "isRoundbale") == true then
                                roundbale = true;
					        else 
								roundbale = false;
					        end;
				        end
			        end;
		        end;
	        end;
        local foundBaleType
		if bale.wrappingState == 1 then
		    wrapstate = true;
		else 
			wrapstate = false;
		end;
        if not bale.supportsWrapping or bale.wrappingState < 0.99 or roundbale == false then


          local baleTypes = self.allowedBaleTypes[bale:getFillType()]
          if baleTypes ~= nil then
            for _, baleType in pairs(baleTypes) do
            foundBaleType = baleType
            break
            end
          end
        end
        if foundBaleType ~= nil or nearestBaleType == nil then
          if foundBaleType ~= nil then
            nearestDistance = distance
          end
          nearestBale = bale
          nearestBaleType = foundBaleType
        end
      end
    end
  end
  return nearestBale, nearestBaleType
end


function Mchale998:getIsFoldAllowed(superFunc)
  if self.baleWrapperState ~= Mchale998.STATE_NONE then
    return false
  end
  if superFunc ~= nil then
    return superFunc(self)
  end
  return true
end


