diff --git a/gui/debugSettingsPage.xml b/gui/debugSettingsPage.xml index 3347de24..b61bd3cb 100644 --- a/gui/debugSettingsPage.xml +++ b/gui/debugSettingsPage.xml @@ -9,7 +9,7 @@ - + @@ -17,7 +17,7 @@ - + @@ -25,7 +25,7 @@ - + @@ -33,7 +33,7 @@ - + @@ -41,7 +41,7 @@ - + @@ -49,7 +49,7 @@ - + @@ -57,7 +57,7 @@ - + @@ -65,7 +65,7 @@ - + @@ -73,7 +73,7 @@ - + @@ -81,7 +81,7 @@ - + @@ -89,15 +89,15 @@ - - - - - - - - - + + + + + + + + + diff --git a/gui/environmentSettingsPage.xml b/gui/environmentSettingsPage.xml index 8a78060c..21b55501 100644 --- a/gui/environmentSettingsPage.xml +++ b/gui/environmentSettingsPage.xml @@ -9,7 +9,7 @@ - + @@ -43,6 +43,14 @@ + + + + + + + + diff --git a/gui/experimentalFeaturesSettingsPage.xml b/gui/experimentalFeaturesSettingsPage.xml index b2c1db41..33addfd5 100644 --- a/gui/experimentalFeaturesSettingsPage.xml +++ b/gui/experimentalFeaturesSettingsPage.xml @@ -8,7 +8,7 @@ - + diff --git a/gui/guiProfiles.xml b/gui/guiProfiles.xml index 6049a2b9..68d942be 100644 --- a/gui/guiProfiles.xml +++ b/gui/guiProfiles.xml @@ -14,7 +14,8 @@ - + + diff --git a/modDesc.xml b/modDesc.xml index 5a51d3c0..f6c2aa4c 100644 --- a/modDesc.xml +++ b/modDesc.xml @@ -32,7 +32,7 @@ Différents modes d'utilisation ont été ajoutés depuis les premières version - 2.0.0.5 + 2.0.0.6 icon.dds diff --git a/scripts/AutoDrive.lua b/scripts/AutoDrive.lua index 0c495240..2496da3d 100644 --- a/scripts/AutoDrive.lua +++ b/scripts/AutoDrive.lua @@ -1,5 +1,5 @@ AutoDrive = {} -AutoDrive.version = "2.0.0.5" +AutoDrive.version = "2.0.0.6" AutoDrive.directory = g_currentModDirectory @@ -15,6 +15,7 @@ AutoDrive.experimentalFeatures.detectGrasField = true AutoDrive.experimentalFeatures.colorAssignmentMode = false AutoDrive.experimentalFeatures.UTurn = true AutoDrive.experimentalFeatures.FoldImplements = true +AutoDrive.experimentalFeatures.RefuelOnlyAtValidStations = true AutoDrive.dynamicChaseDistance = true AutoDrive.smootherDriving = true @@ -86,6 +87,10 @@ AutoDrive.FLAG_SUBPRIO = 1 AutoDrive.FLAG_TRAFFIC_SYSTEM = 2 AutoDrive.FLAG_TRAFFIC_SYSTEM_CONNECTION = 4 +-- add this to measured size of vehicles +AutoDrive.DIMENSION_ADDITION = 0.2 + + AutoDrive.colors = { ad_color_singleConnection = {0, 1, 0, 1}, ad_color_dualConnection = {0, 0, 1, 1}, @@ -116,8 +121,7 @@ AutoDrive.fuelFillTypes = { } AutoDrive.nonFillableFillTypes = { -- these fillTypes should not be transported - "AIR", - "SILAGE_ADDITIVE" + "AIR" } AutoDrive.seedFillTypes = { @@ -194,12 +198,13 @@ function AutoDrive:loadMap(name) AutoDrive.readLocalSettingsFromXML() ADUserDataManager:load() + + AutoDrive.Hud = AutoDriveHud:new() + if g_server ~= nil then ADUserDataManager:loadFromXml() end - AutoDrive.Hud = AutoDriveHud:new() - AutoDrive.Hud:loadHud() -- Save Configuration when saving savegame @@ -454,7 +459,6 @@ function AutoDrive:init() else ADGraphManager:checkYPositionIntegrity() end - AutoDrive.updateDestinationsMapHotspots() AutoDrive:registerDestinationListener(AutoDrive, AutoDrive.updateDestinationsMapHotspots) diff --git a/scripts/ExternalInterface.lua b/scripts/ExternalInterface.lua index 9f491023..78cc1dfc 100644 --- a/scripts/ExternalInterface.lua +++ b/scripts/ExternalInterface.lua @@ -425,6 +425,168 @@ function AutoDrive:getIsCPTurning(vehicle) end +-- CP event handler +function AutoDrive:onCpFinished() + AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpFinished start... enableParkAtJobFinished %s", AutoDrive.getSetting("enableParkAtJobFinished", self)) + if self.isServer then + if self.ad and self.ad.stateModule and self.startAutoDrive and AutoDrive.getSetting("enableParkAtJobFinished", self) then + self.ad.onRouteToRefuel = false + self.ad.onRouteToRepair = false + self.ad.restartCP = false + self.ad.stateModule:setStartCP_AIVE(false) + local parkDestinationAtJobFinished = self.ad.stateModule:getParkDestinationAtJobFinished() + + if parkDestinationAtJobFinished >= 1 then + local trailers, _ = AutoDrive.getAllUnits(self) + local fillLevel, _, _ = AutoDrive.getAllFillLevels(trailers) + if self.ad.stateModule:getMode() == AutoDrive.MODE_PICKUPANDDELIVER and fillLevel > 0 then + AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpFinished fillLevel > 0 %s", tostring(fillLevel)) + -- unload before going to park + AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpFinished unload before going to park - fillLevel %s", tostring(fillLevel)) + self.ad.stateModule:setMode(AutoDrive.MODE_DELIVERTO) + self.ad.stateModule:setFirstMarker(self.ad.stateModule:getSecondMarkerId()) + else + AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpFinished drive to park position") + self.ad.onRouteToPark = true + self.ad.stateModule:setMode(AutoDrive.MODE_DRIVETO) + self.ad.stateModule:setFirstMarker(parkDestinationAtJobFinished) + end + self.ad.stateModule:getCurrentMode():start() + else + AutoDriveMessageEvent.sendMessageOrNotification(self, ADMessagesManager.messageTypes.ERROR, "$l10n_AD_Driver_of; %s $l10n_AD_parkVehicle_noPosSet;", 5000, self.ad.stateModule:getName()) + -- stop vehicle movement + self.ad.trailerModule:handleTrailerReversing(false) + AutoDrive.driveInDirection(self, 16, 30, 0, 0.2, 20, false, false, 0, 0, 0, 1) + self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_OFF) + if self.stopMotor ~= nil then + self:stopMotor() + end + end + end + else + Logging.devError("AutoDrive:onCpFinished() must be called only on the server.") + end + AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpFinished end") +end + +function AutoDrive:handleCPFieldWorker(vehicle) + AutoDrive.debugPrint(vehicle, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:handleCPFieldWorker start...") + if vehicle.isServer then + if vehicle.ad and vehicle.ad.stateModule and vehicle.startAutoDrive then + -- restart CP + vehicle.ad.restartCP = true + if not vehicle.ad.stateModule:isActive() then + if vehicle.ad.stateModule:getStartCP_AIVE() and vehicle.ad.stateModule:getUseCP_AIVE() then + -- CP button active + if table.contains(AutoDrive.modesToStartFromCP, vehicle.ad.stateModule:getMode()) then + -- mode allowed to activate + AutoDrive.debugPrint(vehicle, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:handleCPFieldWorker start AD") + vehicle.ad.stateModule:getCurrentMode():start() + else + -- deactivate CP button + AutoDriveMessageEvent.sendMessageOrNotification(vehicle, ADMessagesManager.messageTypes.ERROR, "$l10n_AD_Driver_of; %s: $l10n_AD_Wrong_Mode_takeover_from_CP;", 5000, vehicle.ad.stateModule:getName()) + vehicle.ad.restartCP = false -- do not continue CP course + vehicle.ad.stateModule:setStartCP_AIVE(false) + end + end + else + AutoDrive.debugPrint(vehicle, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:handleCPFieldWorker - AD already active, should not happen") + end + end + else + Logging.devError("AutoDrive:handleCPFieldWorker() must be called only on the server.") + end + AutoDrive.debugPrint(vehicle, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:handleCPFieldWorker end") +end + +function AutoDrive:onCpEmpty() + AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpEmpty start...") + AutoDrive:handleCPFieldWorker(self) +end + +function AutoDrive:onCpFull() + AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpFull start...") + AutoDrive:handleCPFieldWorker(self) +end + +function AutoDrive:onCpFuelEmpty() + AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpFuelEmpty start... autoRefuel %s", AutoDrive.getSetting("autoRefuel", self)) + if self.isServer then + if self.ad and self.ad.stateModule and self.startAutoDrive and AutoDrive.getSetting("autoRefuel", self) then + + local refuelDestination = ADTriggerManager.getClosestRefuelDestination(self, true) + AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpFuelEmpty refuelDestination %s", tostring(refuelDestination)) + + if refuelDestination ~= nil and refuelDestination >= 1 then + if not self.ad.stateModule:isActive() then + AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpFuelEmpty getCurrentMode() start %s", tostring(self.ad.stateModule:getCurrentMode())) + self.ad.onRouteToRefuel = true + self.ad.restartCP = true + self.ad.stateModule:getCurrentMode():start() + else + AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpFuelEmpty - AD already active, should not happen") + end + else + local refuelFillTypes = AutoDrive.getRequiredRefuels(self, true) + AutoDriveMessageEvent.sendMessageOrNotification(self, ADMessagesManager.messageTypes.ERROR, "$l10n_AD_Driver_of; %s $l10n_AD_No_Refuel_Station;", 5000, self.ad.stateModule:getName()) + end + end + else + Logging.devError("AutoDrive:onCpFuelEmpty() must be called only on the server.") + end + AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpFuelEmpty end") +end + +function AutoDrive:onCpBroken() + AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpBroken start... autoRepair %s", tostring(AutoDrive.getSetting("autoRepair", self))) + + if self.isServer then + if self.ad and self.ad.stateModule and self.startAutoDrive and AutoDrive.getSetting("autoRepair", self) then + local repairDestinationMarkerNodeID = AutoDrive:getClosestRepairTrigger(self) + AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO,"AutoDrive:onCpBroken repairDestinationMarkerNodeID %s", tostring(repairDestinationMarkerNodeID)) + if repairDestinationMarkerNodeID ~= nil then + if not self.ad.stateModule:isActive() then + AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpBroken getCurrentMode() start %s", tostring(self.ad.stateModule:getCurrentMode())) + self.ad.onRouteToRepair = true + self.ad.restartCP = true + self.ad.stateModule:getCurrentMode():start() + else + AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpBroken - AD already active, should not happen") + end + else + AutoDriveMessageEvent.sendMessageOrNotification(self, ADMessagesManager.messageTypes.ERROR, "$l10n_AD_Driver_of; %s $l10n_AD_No_Repair_Station;", 5000, self.ad.stateModule:getName()) + end + end + else + Logging.devError("AutoDrive:onCpBroken() must be called only on the server.") + end + AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpBroken end") +end + +--- Disables click to switch, if the user clicks on the hud or the editor mode is active. +function AutoDrive:enterVehicleRaycastClickToSwitch(superFunc, x, y) + + if AutoDrive.isEditorModeEnabled() then + return + end + + --- Checks if the mouse is over a hud element. + if AutoDriveHud:isMouseOverHud(x, y) then + return + end + + superFunc(self, x, y) +end + +function AutoDrive:getCanAdTakeControl() + if self.isServer then + if self.ad and self.ad.stateModule and not self.ad.stateModule:isActive() then + return self.ad.stateModule:getStartCP_AIVE() and self.ad.stateModule:getUseCP_AIVE() + end + end + return false +end + -- Autoloader --[[ APalletAutoLoader: @@ -433,7 +595,7 @@ function AutoDrive:hasAL(object) if object == nil then return false end - return object.spec_aPalletAutoLoader ~= nil + return object.spec_aPalletAutoLoader ~= nil and object.spec_aPalletAutoLoader.loadArea ~= nil and object.spec_aPalletAutoLoader.loadArea["baseNode"] ~= nil end --[[ @@ -442,7 +604,7 @@ end ]] function AutoDrive:setALOn(object) - if object == nil then + if not AutoDrive:hasAL(object) then return false end local spec = object.spec_aPalletAutoLoader @@ -454,7 +616,7 @@ function AutoDrive:setALOn(object) end function AutoDrive:setALOff(object) - if object == nil then + if not AutoDrive:hasAL(object) then return false end @@ -493,9 +655,9 @@ end --[[ APalletAutoLoaderTipsides = { LEFT = 1, - RIGHT = 2 - MIDDLE = 3 - + RIGHT = 2, + MIDDLE = 3, + BACK = 4 } values = {0, 1, 2, 3, 4}, texts = {"gui_ad_AL_off", "gui_ad_AL_center", "gui_ad_AL_left", "gui_ad_AL_behind", "gui_ad_AL_right"}, @@ -511,7 +673,7 @@ function AutoDrive:unloadAL(object) local unloadPositions = { 3, 1, - 0, + 4, 2 } @@ -568,7 +730,7 @@ function AutoDrive:getALObjectFillLevels(object) -- used by getIsFillUnitEmpty, local fillLevel = 0 local fillFreeCapacity = 0 local spec = object.spec_aPalletAutoLoader - if spec and object.getFillUnitCapacity and object.getFillUnitFillLevel and object.getFillUnitFreeCapacity then + if spec and AutoDrive:hasAL(object) and object.getFillUnitCapacity and object.getFillUnitFillLevel and object.getFillUnitFreeCapacity then fillCapacity = object:getFillUnitCapacity() fillLevel = object:getFillUnitFillLevel() fillFreeCapacity = object:getFillUnitFreeCapacity() @@ -585,7 +747,7 @@ function AutoDrive:getALFillTypes(object) -- used by PullDownList, getSupportedF local fillTypes = {} local spec = object.spec_aPalletAutoLoader - if spec and object.GetAutoloadTypes then + if spec and AutoDrive:hasAL(object) and object.GetAutoloadTypes then local autoLoadTypes = object:GetAutoloadTypes() if autoLoadTypes and table.count(autoLoadTypes) > 0 then for i = 1, table.count(autoLoadTypes) do @@ -605,7 +767,7 @@ function AutoDrive:getALCurrentFillType(object) -- used by onEnterVehicle, onPos end local spec = object.spec_aPalletAutoLoader - if spec and spec.currentautoLoadTypeIndex then + if spec and AutoDrive:hasAL(object) and spec.currentautoLoadTypeIndex then return spec.currentautoLoadTypeIndex end return nil @@ -621,7 +783,7 @@ function AutoDrive:setALFillType(vehicle, fillType) -- used by PullDownList for i=1, trailerCount do local object = trailers[i] local spec = object.spec_aPalletAutoLoader - if spec and object.SetLoadingState and object.SetAutoloadType then + if spec and AutoDrive:hasAL(object) and object.SetLoadingState and object.SetAutoloadType then AutoDrive.debugPrint(vehicle, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:setALFillType fillType %s", tostring(fillType)) -- set loading state off object:SetLoadingState(1) diff --git a/scripts/Gui/DebugSettingsPage.lua b/scripts/Gui/DebugSettingsPage.lua index ad6ee1fe..6d778656 100644 --- a/scripts/Gui/DebugSettingsPage.lua +++ b/scripts/Gui/DebugSettingsPage.lua @@ -10,7 +10,7 @@ ADDebugSettingsPage = {} local ADDebugSettingsPage_mt = Class(ADDebugSettingsPage, TabbedMenuFrameElement) -- ADDebugSettingsPage.CONTROLS = {"settingsContainer", "headerIcon", "headerText"} -ADDebugSettingsPage.CONTROLS = {"settingsContainer", "headerIcon"} +ADDebugSettingsPage.CONTROLS = {"settingsContainer", "headerIcon", "boxLayout"} function ADDebugSettingsPage:new(target) local element = TabbedMenuFrameElement.new(target, ADDebugSettingsPage_mt) @@ -28,9 +28,10 @@ end function ADDebugSettingsPage:onFrameOpen() ADDebugSettingsPage:superClass().onFrameOpen(self) - FocusManager:unsetHighlight(FocusManager.currentFocusData.highlightElement) - FocusManager:unsetFocus(FocusManager.currentFocusData.focusElement) + -- FocusManager:unsetHighlight(FocusManager.currentFocusData.highlightElement) + -- FocusManager:unsetFocus(FocusManager.currentFocusData.focusElement) self:updateDebugElements() + FocusManager:setFocus(self.boxLayout) end function ADDebugSettingsPage:onFrameClose() diff --git a/scripts/Gui/EnterGroupNameGUI.lua b/scripts/Gui/EnterGroupNameGUI.lua index 488f7b50..b6eca8d3 100644 --- a/scripts/Gui/EnterGroupNameGUI.lua +++ b/scripts/Gui/EnterGroupNameGUI.lua @@ -30,7 +30,10 @@ function ADEnterGroupNameGui:onClickOk() if self.textInputElement.text ~= ADGraphManager.debugGroupName then -- do not allow user to create debug group - ADGraphManager:addGroup(self.textInputElement.text) + local groupName = self.textInputElement.text + groupName = string.gsub(groupName, ",", "_") -- remove separation characters + groupName = string.gsub(groupName, ";", "_") + ADGraphManager:addGroup(groupName) end self:onClickBack() diff --git a/scripts/Gui/ExperimentalFeaturesSettingsPage.lua b/scripts/Gui/ExperimentalFeaturesSettingsPage.lua index 9679249f..f55037e2 100644 --- a/scripts/Gui/ExperimentalFeaturesSettingsPage.lua +++ b/scripts/Gui/ExperimentalFeaturesSettingsPage.lua @@ -9,7 +9,7 @@ ADExperimentalFeaturesSettingsPage = {} local ADExperimentalFeaturesSettingsPage_mt = Class(ADExperimentalFeaturesSettingsPage, TabbedMenuFrameElement) -ADExperimentalFeaturesSettingsPage.CONTROLS = {"settingsContainer", "headerIcon", "cloneElement", "headerText"} +ADExperimentalFeaturesSettingsPage.CONTROLS = {"settingsContainer", "headerIcon", "cloneElement", "headerText", "boxLayout"} function ADExperimentalFeaturesSettingsPage:new(target) local element = TabbedMenuFrameElement.new(target, ADExperimentalFeaturesSettingsPage_mt) @@ -40,6 +40,8 @@ function ADExperimentalFeaturesSettingsPage:onCreate() stateNumber = 2 end cloned:setState(stateNumber) + -- focusId has to be unique, but is copied by clone element, so generate and assign a new unique focusId + cloned.focusId = "adFocus_" .. featureName table.insert(self.experimentalFeaturesElements, cloned) end self.cloneElement:delete() @@ -47,14 +49,18 @@ function ADExperimentalFeaturesSettingsPage:onCreate() end function ADExperimentalFeaturesSettingsPage:onCreateElement(element) - table.insert(self.experimentalFeaturesElements, element) + -- table.insert(self.experimentalFeaturesElements, element) end function ADExperimentalFeaturesSettingsPage:onFrameOpen() ADExperimentalFeaturesSettingsPage:superClass().onFrameOpen(self) - FocusManager:unsetHighlight(FocusManager.currentFocusData.highlightElement) - FocusManager:unsetFocus(FocusManager.currentFocusData.focusElement) + -- FocusManager:unsetHighlight(FocusManager.currentFocusData.highlightElement) + -- FocusManager:unsetFocus(FocusManager.currentFocusData.focusElement) self:updateElementsState() + for _, child in pairs(self.boxLayout.elements) do + FocusManager:loadElementFromCustomValues(child, child.focusId, child.focusChangeData, child.focusActive, child.isAlwaysFocusedOnOpen) + end + FocusManager:setFocus(self.boxLayout) end function ADExperimentalFeaturesSettingsPage:onFrameClose() diff --git a/scripts/Gui/SettingsPage.lua b/scripts/Gui/SettingsPage.lua index 15d40cbd..e576ff78 100644 --- a/scripts/Gui/SettingsPage.lua +++ b/scripts/Gui/SettingsPage.lua @@ -10,7 +10,7 @@ ADSettingsPage = {} local ADSettingsPage_mt = Class(ADSettingsPage, TabbedMenuFrameElement) -- ADSettingsPage.CONTROLS = {"settingsContainer", "ingameMenuHelpBox", "headerIcon", "headerText"} -ADSettingsPage.CONTROLS = {"settingsContainer", "ingameMenuHelpBox"} +ADSettingsPage.CONTROLS = {"settingsContainer", "ingameMenuHelpBox", "boxLayout"} function ADSettingsPage:new(target) local element = TabbedMenuFrameElement.new(target, ADSettingsPage_mt) @@ -22,11 +22,12 @@ end function ADSettingsPage:onFrameOpen() ADSettingsPage:superClass().onFrameOpen(self) - FocusManager:unsetHighlight(FocusManager.currentFocusData.highlightElement) - FocusManager:unsetFocus(FocusManager.currentFocusData.focusElement) + -- FocusManager:unsetHighlight(FocusManager.currentFocusData.highlightElement) + -- FocusManager:unsetFocus(FocusManager.currentFocusData.focusElement) if not self:hasChanges() then self:loadGUISettings() end + FocusManager:setFocus(self.boxLayout) end function ADSettingsPage:onFrameClose() diff --git a/scripts/Hud/PullDownList.lua b/scripts/Hud/PullDownList.lua index e76ed11a..a46cff23 100644 --- a/scripts/Hud/PullDownList.lua +++ b/scripts/Hud/PullDownList.lua @@ -486,33 +486,19 @@ function ADPullDownList:createSelection_FillType() local vehicle = AutoDrive.getADFocusVehicle() if vehicle ~= nil then + local hasAL = false local trailers, _ = AutoDrive.getAllUnits(vehicle) - for trailerIndex, trailer in ipairs(trailers) do - supportedFillTypes = {} - if AutoDrive:hasAL(trailer) then - -- AutoLoad + for _, trailer in ipairs(trailers) do + hasAL = hasAL or AutoDrive:hasAL(trailer) + end + supportedFillTypes = {} + if hasAL then + -- AutoLoad + for _, trailer in ipairs(trailers) do self.autoLoadFillTypes = AutoDrive:getALFillTypes(trailer) - else - if trailer.getFillUnits ~= nil then - for fillUnitIndex, _ in pairs(trailer:getFillUnits()) do - if trailer.getFillUnitSupportedFillTypes ~= nil then - for fillType, supported in pairs(trailer:getFillUnitSupportedFillTypes(fillUnitIndex)) do - - if trailerIndex == 1 then -- hide fuel types for 1st vehicle - local fillTypeName = g_fillTypeManager:getFillTypeNameByIndex(fillType) - if table.contains(AutoDrive.fuelFillTypes, fillTypeName) then - supported = false - end - end - if supported then - local fillTypeName = g_fillTypeManager:getFillTypeNameByIndex(fillType) - table.insert(supportedFillTypes, fillType) - end - end - end - end - end end + else + supportedFillTypes = AutoDrive.getValidSupportedFillTypes(vehicle) end end @@ -595,7 +581,7 @@ function ADPullDownList:getNewState_FillType(vehicle) self.text = self.autoLoadFillTypes[vehicle.ad.stateModule:getFillType()] -- AutoDrive.debugMsg(vehicle, "ADPullDownList:getNewState_FillType 1 vehicle.ad.stateModule:getFillType() %s self.text %s", tostring(vehicle.ad.stateModule:getFillType()), tostring(self.text)) else - self.text = self.autoLoadFillTypes[1] + self.text = "" -- AutoDrive.debugMsg(vehicle, "ADPullDownList:getNewState_FillType 2 self.text %s", tostring(self.text)) end else diff --git a/scripts/Manager/GraphManager.lua b/scripts/Manager/GraphManager.lua index fadd61f0..5100cfb1 100644 --- a/scripts/Manager/GraphManager.lua +++ b/scripts/Manager/GraphManager.lua @@ -697,14 +697,12 @@ function ADGraphManager:recordWayPoint(x, y, z, connectPrevious, dual, isReverse end function ADGraphManager:isDualRoad(start, target) - if start == nil or target == nil or start.incoming == nil or target.id == nil then + if start == nil or target == nil or start.incoming == nil or target.incoming == nil or start.id == nil or target.id == nil then return false end - for _, incoming in pairs(start.incoming) do - if incoming == target.id then - return true - end - end + if table.contains(start.incoming, target.id) and table.contains(target.incoming, start.id) then + return true + end return false end @@ -956,8 +954,46 @@ function ADGraphManager:prepareWayPoints() end end end - end - self.preparedWayPoints = true + end + self.preparedWayPoints = true +end + +-- this looks simlar to prepareWayPoints, but is separated to not disturb this calculation +-- here also additional checks may be implemented +function ADGraphManager:getNetworkErrors() + local network = self:getWayPoints() + for id, wp in ipairs(network) do + wp.errorMapping = {} + + if #wp.incoming > 0 then + for outIndex, outId in ipairs(wp.out) do + wp.errorMapping[outId] = true -- assume no path + end + + for inIndex, inId in ipairs(wp.incoming) do + local inPoint = network[inId] + for outIndex, outId in ipairs(wp.out) do + if inId ~= outId then + local outPoint = network[outId] + local angle = math.abs(AutoDrive.angleBetween({x = outPoint.x - wp.x, z = outPoint.z - wp.z}, {x = wp.x - inPoint.x, z = wp.z - inPoint.z})) + if angle <= 90 then + wp.errorMapping[outId] = false + else + local isReverseStart = not table.contains(outPoint.incoming, wp.id) + local isReverseEnd = table.contains(outPoint.incoming, wp.id) and not table.contains(wp.incoming, inPoint.id) + if isReverseStart or isReverseEnd then + wp.errorMapping[outId] = false + end + end + end + if inId == outId and #wp.incoming == 1 then + -- only 1 dual connection + wp.errorMapping[outId] = false + end + end + end + end + end end function ADGraphManager:checkResetVehicleDestinations(destination) @@ -1017,6 +1053,7 @@ function ADGraphManager:createDebugMarkers(updateMap) if overallnumberWP < 3 then return end + ADGraphManager:getNetworkErrors() local network = self:getWayPoints() local shouldUpdateMap = updateMap @@ -1038,8 +1075,10 @@ function ADGraphManager:createDebugMarkers(updateMap) local count2 = 1 local count3 = 1 local count4 = 1 + local count9 = 1 local mapMarkerCounter = #self:getMapMarkers() + 1 for i, wp in pairs(network) do + wp.foundError = false -- mark wayPoint without outgoing connection if #wp.out == 0 then if wp ~= nil then @@ -1054,13 +1093,14 @@ function ADGraphManager:createDebugMarkers(updateMap) mapMarker.isADDebug = true self:setMapMarker(mapMarker) + wp.foundError = true count1 = count1 + 1 mapMarkerCounter = mapMarkerCounter + 1 end end -- mark reverse wayPoint with less angle to be reverse -> wrong connection in network - if wp.incoming ~= nil then + if not wp.foundError and wp.incoming ~= nil then for _, wp_in in pairs(wp.incoming) do if wp.out ~= nil then for _, wp_out in pairs(wp.out) do @@ -1079,6 +1119,7 @@ function ADGraphManager:createDebugMarkers(updateMap) mapMarker.isADDebug = true self:setMapMarker(mapMarker) + wp.foundError = true count2 = count2 + 1 mapMarkerCounter = mapMarkerCounter + 1 end @@ -1088,7 +1129,7 @@ function ADGraphManager:createDebugMarkers(updateMap) end -- mark wayPoint without incoming connection - if wp.out ~= nil then + if not wp.foundError and wp.out ~= nil then for _, wp_out in pairs(wp.out) do local missingIncoming = self:checkForMissingIncoming(wp, self:getWayPointById(wp_out)) if missingIncoming then @@ -1103,6 +1144,7 @@ function ADGraphManager:createDebugMarkers(updateMap) mapMarker.isADDebug = true self:setMapMarker(mapMarker) + wp.foundError = true count3 = count3 + 1 mapMarkerCounter = mapMarkerCounter + 1 end @@ -1110,7 +1152,7 @@ function ADGraphManager:createDebugMarkers(updateMap) end -- mark dual wayPoint with death end - if wp.out ~= nil then + if not wp.foundError and wp.out ~= nil then for _, wp_out in pairs(wp.out) do local missingIncoming = self:checkForMissingDualConnection(wp) if missingIncoming then @@ -1125,11 +1167,33 @@ function ADGraphManager:createDebugMarkers(updateMap) mapMarker.isADDebug = true self:setMapMarker(mapMarker) + wp.foundError = true count4 = count4 + 1 mapMarkerCounter = mapMarkerCounter + 1 end end end + + -- possible other errors + if not wp.foundError then + local wrongAngle, count1, count2 = self:checkForOtherErrors(wp) + if wrongAngle then + local debugMapMarkerName = "9_" .. tostring(count9) + + -- create the mapMarker + local mapMarker = {} + mapMarker.name = debugMapMarkerName + mapMarker.group = ADGraphManager.debugGroupName + mapMarker.markerIndex = mapMarkerCounter + mapMarker.id = wp.id + mapMarker.isADDebug = true + self:setMapMarker(mapMarker) + + wp.foundError = true + count9 = count9 + 1 + mapMarkerCounter = mapMarkerCounter + 1 + end + end end end if shouldUpdateMap == true then @@ -1192,8 +1256,13 @@ function ADGraphManager:checkForMissingDualConnection(wp_current) if wp_current.incoming ~= nil and wp_current.out ~= nil and #wp_current.incoming == 1 and #wp_current.out == 1 then if wp_current.incoming[1] ~= nil and wp_current.out[1] ~= nil and wp_current.incoming[1] == wp_current.out[1] then - -- dual waypoint with reverse in connection - ret = true + + local mapMarker = ADGraphManager:getMapMarkerByWayPointId(wp_current.id) + -- only dual waypoint without Marker is an error + if mapMarker == nil then + -- dual waypoint + ret = true + end -- search for a possible reverse connection for _, wp in pairs(self.wayPoints) do @@ -1208,6 +1277,23 @@ function ADGraphManager:checkForMissingDualConnection(wp_current) return ret end + +function ADGraphManager:checkForOtherErrors(wp) + local ret = false + + if wp == nil then + return true + end +-- TODO + + local network = self:getWayPoints() + + for outIndex, outId in ipairs(wp.out) do + ret = ret or wp.errorMapping[outId] + end + return ret +end + function ADGraphManager:toggleWayPointAsSubPrio(wayPointId) local wayPoint = self:getWayPointById(wayPointId) if wayPoint ~= nil then diff --git a/scripts/Manager/InputManager.lua b/scripts/Manager/InputManager.lua index 94ccdfb2..576bf888 100644 --- a/scripts/Manager/InputManager.lua +++ b/scripts/Manager/InputManager.lua @@ -372,7 +372,7 @@ function ADInputManager:input_nextTarget(vehicle) local currentTarget = vehicle.ad.stateModule:getFirstMarkerId() local nextTarget = ADGraphManager:getNextTargetAlphabetically(currentTarget) vehicle.ad.stateModule:setFirstMarker(nextTarget) - if not (self.vehicle.spec_combine or AutoDrive.getIsBufferCombine(self.vehicle) or self.vehicle.ad.isCombine ~= nil) then + if not (vehicle.spec_combine or AutoDrive.getIsBufferCombine(vehicle) or vehicle.ad.isCombine ~= nil) then -- not stop / change CP for harvesters AutoDrive:StopCP(vehicle) end @@ -384,7 +384,7 @@ function ADInputManager:input_previousTarget(vehicle) local currentTarget = vehicle.ad.stateModule:getFirstMarkerId() local previousTarget = ADGraphManager:getPreviousTargetAlphabetically(currentTarget) vehicle.ad.stateModule:setFirstMarker(previousTarget) - if not (self.vehicle.spec_combine or AutoDrive.getIsBufferCombine(self.vehicle) or self.vehicle.ad.isCombine ~= nil) then + if not (vehicle.spec_combine or AutoDrive.getIsBufferCombine(vehicle) or vehicle.ad.isCombine ~= nil) then -- not stop / change CP for harvesters AutoDrive:StopCP(vehicle) end @@ -440,7 +440,7 @@ function ADInputManager:input_parkVehicle(vehicle) vehicle.ad.onRouteToPark = true else vehicle.ad.onRouteToPark = false - AutoDriveMessageEvent.sendMessage(vehicle, ADMessagesManager.messageTypes.ERROR, "$l10n_AD_parkVehicle_noPosSet;", 5000) + AutoDriveMessageEvent.sendMessage(vehicle, ADMessagesManager.messageTypes.ERROR, "$l10n_AD_Driver_of; %s $l10n_AD_parkVehicle_noPosSet;", 5000, vehicle.ad.stateModule:getName()) end end @@ -448,7 +448,7 @@ function ADInputManager:input_swapTargets(vehicle) local currentFirstMarker = vehicle.ad.stateModule:getFirstMarkerId() vehicle.ad.stateModule:setFirstMarker(vehicle.ad.stateModule:getSecondMarkerId()) vehicle.ad.stateModule:setSecondMarker(currentFirstMarker) - if not (self.vehicle.spec_combine or AutoDrive.getIsBufferCombine(self.vehicle) or self.vehicle.ad.isCombine ~= nil) then + if not (vehicle.spec_combine or AutoDrive.getIsBufferCombine(vehicle) or vehicle.ad.isCombine ~= nil) then -- not stop / change CP for harvesters AutoDrive:StopCP(vehicle) end diff --git a/scripts/Manager/TriggerManager.lua b/scripts/Manager/TriggerManager.lua index fc0344d4..a19bdd94 100644 --- a/scripts/Manager/TriggerManager.lua +++ b/scripts/Manager/TriggerManager.lua @@ -280,7 +280,7 @@ function ADTriggerManager.getRepairTriggers() return ADTriggerManager.repairTriggers end --- returns only suitable fuel triggers according to used fuel types +-- returns only suitable fuel triggers according to required fuel types function ADTriggerManager.getRefuelTriggers(vehicle, ignoreFillLevel) @@ -310,9 +310,19 @@ function ADTriggerManager.getRefuelTriggers(vehicle, ignoreFillLevel) if #refuelFillTypes > 0 then for _, refuelFillType in pairs(refuelFillTypes) do - local hasCapacity = (fillLevels[refuelFillType] ~= nil and fillLevels[refuelFillType] > 0) or (gcFillLevels[refuelFillType] ~= nil and gcFillLevels[refuelFillType] > 0) + local hasFill = (fillLevels[refuelFillType] ~= nil and fillLevels[refuelFillType] > 0) or (gcFillLevels[refuelFillType] ~= nil and gcFillLevels[refuelFillType] > 0) + + local isVehicleTrigger = true + if AutoDrive.experimentalFeatures.RefuelOnlyAtValidStations == true then + isVehicleTrigger = trigger.triggerNode and CollisionFlag.getHasFlagSet(trigger.triggerNode, CollisionFlag.TRIGGER_VEHICLE) + AutoDrive.debugPrint(vehicle, AutoDrive.DC_VEHICLEINFO, "ADTriggerManager.getRefuelTriggers hasFill %s isVehicleTrigger %s", tostring(hasFill), tostring(isVehicleTrigger)) + if isVehicleTrigger then + local triggerX, _, triggerZ = ADTriggerManager.getTriggerPos(trigger) + AutoDrive.debugPrint(vehicle, AutoDrive.DC_VEHICLEINFO, "ADTriggerManager.getRefuelTriggers Pos: %s,%s", tostring(triggerX), tostring(triggerZ)) + end + end - if hasCapacity and not table.contains(refuelTriggers, trigger) then + if isVehicleTrigger and hasFill and not table.contains(refuelTriggers, trigger) then table.insert(refuelTriggers, trigger) end end diff --git a/scripts/Manager/UserDataManager.lua b/scripts/Manager/UserDataManager.lua index 0beba3f8..108c3bd0 100644 --- a/scripts/Manager/UserDataManager.lua +++ b/scripts/Manager/UserDataManager.lua @@ -1,6 +1,7 @@ ADUserDataManager = {} ADUserDataManager.users = {} +ADUserDataManager.SinglePlayer = "SinglePlayer" function ADUserDataManager:getUserByConnection(connection) return g_currentMission.userManager:getUserByConnection(connection) @@ -54,6 +55,17 @@ function ADUserDataManager:loadFromXml() end uIndex = uIndex + 1 end + + if g_currentMission.userManager.getUserByConnection then + local user = g_currentMission.userManager:getUserByConnection(connection) + if user == nil then + -- no client, use a single player user + local uniqueId = ADUserDataManager.SinglePlayer + if self.users[uniqueId] ~= nil then + self:applyUserSettings((self.users[uniqueId].hudX or 0.5), (self.users[uniqueId].hudY or 0.5), self.users[uniqueId].settings) + end + end + end Logging.info("[AD] ADUserDataManager: loaded data for %d users", userCount) end delete(xmlFile) @@ -77,6 +89,25 @@ end function ADUserDataManager:saveToXml() local file = g_currentMission.missionInfo.savegameDirectory .. "/AutoDriveUsersData.xml" local xmlFile = createXMLFile("AutoDriveUsersData_XML_temp", file, "AutoDriveUsersData") + + if g_currentMission.userManager.getUserByConnection then + local user = g_currentMission.userManager:getUserByConnection(connection) + if user == nil then + -- no client, create a single player user + local uniqueId = ADUserDataManager.SinglePlayer + if self.users[uniqueId] == nil then + -- single player user data not loaded before, so use the current data + self.users[uniqueId] = {} + self.users[uniqueId].hudX = AutoDrive.HudX or 0.5 + self.users[uniqueId].hudY = AutoDrive.HudY or 0.5 + self.users[uniqueId].settings = {} + for _, sn in pairs(self.userSettingNames) do + self.users[uniqueId].settings[sn] = AutoDrive.getSettingState(sn) + end + end + end + end + local uIndex = 0 for uniqueId, userData in pairs(self.users) do local uKey = string.format("AutoDriveUsersData.users.user(%d)", uIndex) diff --git a/scripts/Modes/CombineUnloaderMode.lua b/scripts/Modes/CombineUnloaderMode.lua index 614f1a8e..d60c5a4e 100644 --- a/scripts/Modes/CombineUnloaderMode.lua +++ b/scripts/Modes/CombineUnloaderMode.lua @@ -38,7 +38,7 @@ function CombineUnloaderMode:reset() self.trailers, self.trailerCount = AutoDrive.getAllUnits(self.vehicle) self.tractorTrainLength = AutoDrive.getTractorTrainLength(self.vehicle, true, false) self.vehicle.ad.trailerModule:reset() - self.fillUnits = AutoDrive.getAllNonFuelFillUnits(self.vehicle, true) -- force initialisation + self.fillUnits = AutoDrive.getAllDischargeableUnits(self.vehicle, true) -- force initialisation end function CombineUnloaderMode:start() @@ -492,7 +492,7 @@ function CombineUnloaderMode:getSideChaseOffsetX() local headerExtra = math.max((AutoDrive.getFrontToolWidth(self.combine) - self.combine.size.width) / 2, 0) local sideChaseTermPipeIn = self.combine.size.width / 2 + unloaderWidest / 2 + headerExtra - local sideChaseTermPipeOut = self.combine.size.width / 2 + (AutoDrive.getPipeLength(self.combine)) + local sideChaseTermPipeOut = AutoDrive.getPipeLength(self.combine) -- Some combines fold up their pipe so tight that targeting it could cause a collision. -- So, choose the max between the two to avoid a collison local sideChaseTermX = math.max(sideChaseTermPipeIn, sideChaseTermPipeOut) @@ -520,7 +520,6 @@ function CombineUnloaderMode:getSideChaseOffsetX_new() local headerExtra = math.max((AutoDrive.getFrontToolWidth(self.combine) - self.combine.size.width) / 2, 0) local sideChaseTermPipeIn = self.combine.size.width / 2 + unloaderWidest / 2 + headerExtra - local sideChaseTermPipeOut = self.combine.size.width / 2 + (AutoDrive.getPipeLength(self.combine)) -- Some combines fold up their pipe so tight that targeting it could cause a collision. -- So, choose the max between the two to avoid a collison local sideChaseTermX = 0 @@ -672,7 +671,7 @@ function CombineUnloaderMode:getPipeChasePosition(planningPhase) end self.pipeSide = AutoDrive.getPipeSide(self.combine) - self.targetFillUnit, self.targetFillNode = AutoDrive.getNextFreeNonFuelFillUnit(self.vehicle) + self.targetFillUnit, self.targetFillNode = AutoDrive.getNextFreeDischargeableUnit(self.vehicle) local sideChaseTermX = self:getSideChaseOffsetX() local sideChaseTermZ = self:getSideChaseOffsetZ(AutoDrive.dynamicChaseDistance or not AutoDrive.getIsBufferCombine(self.combine)) @@ -737,7 +736,7 @@ function CombineUnloaderMode:getPipeChasePosition(planningPhase) ( ( self:isUnloaderOnCorrectSide(self.pipeSide) - and math.abs(angleToSideChaseSide) < math.abs(angleToRearChaseSide) + -- and math.abs(angleToSideChaseSide) < math.abs(angleToRearChaseSide) ) or (planningPhase == true) ) diff --git a/scripts/Modules/StateModule.lua b/scripts/Modules/StateModule.lua index 074ebf89..ce92f4e2 100644 --- a/scripts/Modules/StateModule.lua +++ b/scripts/Modules/StateModule.lua @@ -29,7 +29,7 @@ function ADStateModule:reset() self.secondMarker = ADGraphManager:getMapMarkerById(1) self.creationMode = ADStateModule.CREATE_OFF - self.fillType = 1 + self.fillType = FillType.UNKNOWN self.loopCounter = 0 self.loopsDone = 0 @@ -61,7 +61,6 @@ function ADStateModule:reset() end self.remainingDriveTime = 0 self.calculateRemainingDriveTimeInterval = 0 - self.refuelFillType = 0 self.activeBeforeSave = false self.AIVEActiveBeforeSave = false self.bunkerUnloadType = ADStateModule.BUNKER_UNLOAD_TRIGGER @@ -101,9 +100,6 @@ function ADStateModule:readFromXMLFile(xmlFile, key) local fillType = xmlFile:getValue(key .. "#fillType") if fillType ~= nil then - if g_fillTypeManager:getFillTypeByIndex(fillType) == nil then - fillType = 1 -- use fillType 1 UNKNOWN as default - end self.fillType = fillType end @@ -184,7 +180,7 @@ function ADStateModule:writeStream(streamId) streamWriteUIntN(streamId, self:getFirstMarkerId() + 1, 17) streamWriteUIntN(streamId, self:getSecondMarkerId() + 1, 17) streamWriteUIntN(streamId, self.creationMode, 3) - streamWriteUIntN(streamId, self.fillType, 8) + streamWriteUIntN(streamId, self.fillType, 10) streamWriteUIntN(streamId, self.loopCounter, 4) streamWriteUIntN(streamId, self.loopsDone, 4) streamWriteUIntN(streamId, self.speedLimit, 8) @@ -199,7 +195,6 @@ function ADStateModule:writeStream(streamId) streamWriteBool(streamId, self.useCP) streamWriteString(streamId, self.driverName) streamWriteUInt16(streamId, self.remainingDriveTime) - streamWriteUIntN(streamId, self.refuelFillType, 8) streamWriteUIntN(streamId, self.bunkerUnloadType, 3) streamWriteBool(streamId, self.automaticUnloadTarget) streamWriteBool(streamId, self.automaticPickupTarget) @@ -213,7 +208,7 @@ function ADStateModule:readStream(streamId) self.firstMarker = ADGraphManager:getMapMarkerById(streamReadUIntN(streamId, 17) - 1) self.secondMarker = ADGraphManager:getMapMarkerById(streamReadUIntN(streamId, 17) - 1) self.creationMode = streamReadUIntN(streamId, 3) - self.fillType = streamReadUIntN(streamId, 8) + self.fillType = streamReadUIntN(streamId, 10) self.loopCounter = streamReadUIntN(streamId, 4) self.loopsDone = streamReadUIntN(streamId, 4) self.speedLimit = streamReadUIntN(streamId, 8) @@ -228,7 +223,6 @@ function ADStateModule:readStream(streamId) self.useCP = streamReadBool(streamId) self.driverName = streamReadString(streamId) self.remainingDriveTime = streamReadUInt16(streamId) - self.refuelFillType = streamReadUIntN(streamId, 8) self.bunkerUnloadType = streamReadUIntN(streamId, 3) self.automaticUnloadTarget = streamReadBool(streamId) self.automaticPickupTarget = streamReadBool(streamId) @@ -244,7 +238,7 @@ function ADStateModule:writeUpdateStream(streamId) streamWriteUIntN(streamId, self:getFirstMarkerId() + 1, 17) streamWriteUIntN(streamId, self:getSecondMarkerId() + 1, 17) streamWriteUIntN(streamId, self.creationMode, 3) - streamWriteUIntN(streamId, self.fillType, 8) + streamWriteUIntN(streamId, self.fillType, 10) streamWriteUIntN(streamId, self.loopCounter, 4) streamWriteUIntN(streamId, self.loopsDone, 4) streamWriteUIntN(streamId, self.speedLimit, 8) @@ -259,7 +253,6 @@ function ADStateModule:writeUpdateStream(streamId) streamWriteBool(streamId, self.useCP) streamWriteString(streamId, self.driverName) streamWriteUInt16(streamId, self.remainingDriveTime) - streamWriteUIntN(streamId, self.refuelFillType, 8) streamWriteUIntN(streamId, self.bunkerUnloadType, 3) streamWriteBool(streamId, self.automaticUnloadTarget) streamWriteBool(streamId, self.automaticPickupTarget) @@ -273,7 +266,7 @@ function ADStateModule:readUpdateStream(streamId) self.firstMarker = ADGraphManager:getMapMarkerById(streamReadUIntN(streamId, 17) - 1) self.secondMarker = ADGraphManager:getMapMarkerById(streamReadUIntN(streamId, 17) - 1) self.creationMode = streamReadUIntN(streamId, 3) - self.fillType = streamReadUIntN(streamId, 8) + self.fillType = streamReadUIntN(streamId, 10) self.loopCounter = streamReadUIntN(streamId, 4) self.loopsDone = streamReadUIntN(streamId, 4) self.speedLimit = streamReadUIntN(streamId, 8) @@ -288,7 +281,6 @@ function ADStateModule:readUpdateStream(streamId) self.useCP = streamReadBool(streamId) self.driverName = streamReadString(streamId) self.remainingDriveTime = streamReadUInt16(streamId) - self.refuelFillType = streamReadUIntN(streamId, 8) self.bunkerUnloadType = streamReadUIntN(streamId, 3) self.automaticUnloadTarget = streamReadBool(streamId) self.automaticPickupTarget = streamReadBool(streamId) @@ -363,7 +355,6 @@ function ADStateModule:update(dt) debug.useCP = self.useCP debug.driverName = self.driverName debug.remainingDriveTime = self.remainingDriveTime - debug.refuelFillType = self.refuelFillType if self.vehicle.ad.modes[AutoDrive.MODE_UNLOAD].combine ~= nil then debug.combine = self.vehicle.ad.modes[AutoDrive.MODE_UNLOAD].combine:getName() else @@ -777,11 +768,10 @@ function ADStateModule:getFillType() end function ADStateModule:setFillType(fillType) - if g_fillTypeManager:getFillTypeByIndex(fillType) == nil then - fillType = 1 -- fillType 1 is UNKNOWN + if self.fillType ~= fillType then + self.fillType = fillType + self:raiseDirtyFlag() end - self.fillType = fillType - self:raiseDirtyFlag() end function ADStateModule:nextFillType() @@ -1013,15 +1003,6 @@ function ADStateModule:getRemainingDriveTime() return self.remainingDriveTime end -function ADStateModule:getRefuelFillType() - return self.refuelFillType -end - -function ADStateModule:setRefuelFillType(refuelFillType) - self.refuelFillType = refuelFillType - self:raiseDirtyFlag() -end - function ADStateModule:nextBunkerUnloadType() if self.bunkerUnloadType < ADStateModule.BUNKER_UNLOAD_TRAILER then self.bunkerUnloadType = self.bunkerUnloadType + 1 diff --git a/scripts/Modules/TaskModule.lua b/scripts/Modules/TaskModule.lua index 94e0c1cf..ed53a686 100644 --- a/scripts/Modules/TaskModule.lua +++ b/scripts/Modules/TaskModule.lua @@ -110,16 +110,14 @@ function ADTaskModule:update(dt) end function ADTaskModule:hasToRefuel() - if not AutoDrive.getSetting("autoRefuel", self.vehicle) then - return false - end - local refuelFillTypes = AutoDrive.getRequiredRefuels(self.vehicle, self.vehicle.ad.onRouteToRefuel) - if #refuelFillTypes > 0 then - self.vehicle.ad.stateModule:setRefuelFillType(refuelFillTypes[1]) - return true - else - return false + local ret = false + if AutoDrive.getSetting("autoRefuel", self.vehicle) or self.vehicle.ad.onRouteToRefuel then + local refuelFillTypes = AutoDrive.getRequiredRefuels(self.vehicle, self.vehicle.ad.onRouteToRefuel) + if #refuelFillTypes > 0 then + ret = true + end end + return ret end function ADTaskModule:RefuelIfNeeded() @@ -131,24 +129,22 @@ function ADTaskModule:RefuelIfNeeded() else self.vehicle.ad.isStoppingWithError = true self.vehicle:stopAutoDrive() - local fillType = self.vehicle.ad.stateModule:getRefuelFillType() - local refuelFillTypeTitle = g_fillTypeManager:getFillTypeByIndex(fillType).title - AutoDriveMessageEvent.sendMessageOrNotification(self.vehicle, ADMessagesManager.messageTypes.ERROR, "$l10n_AD_Driver_of; %s $l10n_AD_No_Refuel_Station; %s", 5000, self.vehicle.ad.stateModule:getName(), refuelFillTypeTitle) + AutoDriveMessageEvent.sendMessageOrNotification(self.vehicle, ADMessagesManager.messageTypes.ERROR, "$l10n_AD_Driver_of; %s $l10n_AD_No_Refuel_Station;", 5000, self.vehicle.ad.stateModule:getName()) end end end function ADTaskModule:hasToRepair() + local repairNeeded = false if self.vehicle.ad.onRouteToRepair then + -- repair is forced by user or CP, so send vehicle to workshop independent of damage level return true end - if not AutoDrive.getSetting("autoRepair", self.vehicle) then - return false - end - local repairNeeded = false - local attachedObjects = AutoDrive.getAllImplements(self.vehicle, true) - for _, attachedObject in pairs(attachedObjects) do - repairNeeded = repairNeeded or (attachedObject.spec_wearable ~= nil and attachedObject.spec_wearable.damage > 0.6) + if AutoDrive.getSetting("autoRepair", self.vehicle) then + local attachedObjects = AutoDrive.getAllImplements(self.vehicle, true) + for _, attachedObject in pairs(attachedObjects) do + repairNeeded = repairNeeded or (attachedObject.spec_wearable ~= nil and attachedObject.spec_wearable.damage > 0.6) + end end return repairNeeded diff --git a/scripts/Modules/TrailerModule.lua b/scripts/Modules/TrailerModule.lua index 0cdb17bd..b99a6da3 100644 --- a/scripts/Modules/TrailerModule.lua +++ b/scripts/Modules/TrailerModule.lua @@ -242,6 +242,11 @@ function ADTrailerModule:handleTrailerReversing(blockTrailers) return end for i, trailer in ipairs(self.trailers) do + local specAttachable = trailer.spec_attachable + if specAttachable and blockTrailers and specAttachable.steeringAxleAngle and specAttachable.steeringAxleAngle ~= 0 then + specAttachable.steeringAxleAngle = 0 + end + if i > 1 and #trailer.components > 1 then -- ignore trailing vehicle if #trailer.componentJoints >= 1 then @@ -316,7 +321,7 @@ function ADTrailerModule:updateLoad(dt) if pair.hasFill then -- initiate load only if fill is available - AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_TRAILERINFO, "ADTrailerModule:updateLoad Try loading at trigger now index %s", tostring(index)) + AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_TRAILERINFO, "ADTrailerModule:updateLoad Try loading at trigger now pair.fillUnitIndex %s", tostring(pair.fillUnitIndex)) fillFound = true -- start loading self:tryLoadingAtTrigger(pair.trailer, pair.trigger, pair.fillUnitIndex) @@ -488,7 +493,7 @@ function ADTrailerModule:updateUnload(dt) local fillUnitEmpty = AutoDrive.getIsFillUnitEmpty(self.isUnloadingWithTrailer, self.isUnloadingWithFillUnit) local allTrailersClosed = self:areAllTrailersClosed(dt) self.unloadDelayTimer:timer(self.isUnloading, 250, dt) - self.stuckInBunkerTimer:timer((self.vehicle.lastSpeedReal * 3600 < 1), 2000, dt) + self.stuckInBunkerTimer:timer((self.vehicle.lastSpeedReal * 3600 < 1), 500, dt) if self.unloadDelayTimer:done() then AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_TRAILERINFO, "ADTrailerModule:updateUnload Monitor unloading unloadDelayTimer:done areAllTrailersClosed %s", tostring(allTrailersClosed)) self.unloadRetryTimer:timer(self.isUnloading, ADTrailerModule.UNLOAD_RETRY_TIME, dt) @@ -544,7 +549,7 @@ end function ADTrailerModule:startLoadingCorrectFillTypeAtTrigger(trailer, trigger, fillUnitIndex) AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_TRAILERINFO, "ADTrailerModule:startLoadingCorrectFillTypeAtTrigger start") - if not AutoDrive.fillTypesMatch(self.vehicle, trigger, trailer) then + if not AutoDrive.fillTypesMatch(self.vehicle, trigger, trailer, nil, fillUnitIndex) then local storedFillType = self.vehicle.ad.stateModule:getFillType() local toCheck = {'SEEDS','FERTILIZER','LIQUIDFERTILIZER'} @@ -567,7 +572,7 @@ function ADTrailerModule:startLoadingCorrectFillTypeAtTrigger(trailer, trigger, end function ADTrailerModule:startLoadingAtTrigger(trigger, fillType, fillUnitIndex, trailer) - AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_TRAILERINFO, "ADTrailerModule:startLoadingAtTrigger start trigger %s", tostring(trigger)) + AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_TRAILERINFO, "ADTrailerModule:startLoadingAtTrigger start trigger %s fillUnitIndex %s", tostring(trigger), tostring(fillUnitIndex)) trigger.autoStart = true trigger.selectedFillType = fillType trigger:onFillTypeSelection(fillType) diff --git a/scripts/Settings.lua b/scripts/Settings.lua index 08cf2e76..944334ac 100644 --- a/scripts/Settings.lua +++ b/scripts/Settings.lua @@ -39,8 +39,8 @@ AutoDrive.settings.blinkValue = { "150", "160" }, - default = 0, - current = 0, + default = 1, + current = 1, text = "gui_ad_blinkValue", tooltip = "gui_ad_blinkValue_tooltip", translate = false, @@ -946,12 +946,10 @@ AutoDrive.settings.autoTrailerCover = { } AutoDrive.settings.ALUnload = { - -- values = {0, 1, 2, 3, 4}, - values = {0, 1, 2, 4}, - -- texts = {"gui_ad_AL_off", "gui_ad_AL_center", "gui_ad_AL_left", "gui_ad_AL_behind", "gui_ad_AL_right"}, - texts = {"gui_ad_AL_off", "gui_ad_AL_center", "gui_ad_AL_left", "gui_ad_AL_right"}, - default = 0, - current = 0, + values = {0, 1, 2, 3, 4}, + texts = {"gui_ad_AL_off", "gui_ad_AL_center", "gui_ad_AL_left", "gui_ad_AL_behind", "gui_ad_AL_right"}, + default = 1, + current = 1, text = "gui_ad_ALUnload", tooltip = "gui_ad_ALUnload_tooltip", translate = true, @@ -1002,6 +1000,17 @@ AutoDrive.settings.useWorkLightsSilo = { isVehicleSpecific = true } +AutoDrive.settings.useHazardLightReverse = { + values = {false, true}, + texts = {"gui_ad_no", "gui_ad_yes"}, + default = 2, + current = 2, + text = "gui_ad_hazardLightReverse", + tooltip = "gui_ad_hazardLightReverse_tooltip", + translate = true, + isVehicleSpecific = true +} + function AutoDrive.getSetting(settingName, vehicle) if AutoDrive.settings[settingName] ~= nil then local setting = AutoDrive.settings[settingName] @@ -1013,6 +1022,9 @@ function AutoDrive.getSetting(settingName, vehicle) if setting.values[setting.current] == nil then setting.current = setting.default end + if setting.values[setting.current] == nil then + setting.current = 1 + end return setting.values[setting.current] end end @@ -1028,6 +1040,9 @@ function AutoDrive.getSettingState(settingName, vehicle) if setting.values[setting.current] == nil then setting.current = setting.default end + if setting.values[setting.current] == nil then + setting.current = 1 + end return setting.current end end diff --git a/scripts/Specialization.lua b/scripts/Specialization.lua index 53c07aad..1d8e9824 100644 --- a/scripts/Specialization.lua +++ b/scripts/Specialization.lua @@ -23,12 +23,15 @@ function AutoDrive.registerEventListeners(vehicleType) "onStopAutoDrive", "onPostAttachImplement", "onPreDetachImplement", + "onPostDetachImplement", "onEnterVehicle", "onLeaveVehicle", - -- CP events + -- CP events, see ExternalInterface.lua "onCpFinished", "onCpEmpty", - "onCpFull" + "onCpFull", + "onCpFuelEmpty", + "onCpBroken", } ) do SpecializationUtil.registerEventListener(vehicleType, n, AutoDrive) @@ -42,7 +45,8 @@ function AutoDrive.registerOverwrittenFunctions(vehicleType) SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsVehicleControlledByPlayer", AutoDrive.getIsVehicleControlledByPlayer) -- SpecializationUtil.registerOverwrittenFunction(vehicleType, "getActiveFarm", AutoDrive.getActiveFarm) - --- Disables click to switch, if the user clicks on the hud or the editor mode is active. + -- Disables click to switch, if the user clicks on the hud or the editor mode is active. + -- see ExternalInterface.lua if vehicleType.functions["enterVehicleRaycastClickToSwitch"] ~= nil then SpecializationUtil.registerOverwrittenFunction(vehicleType, "enterVehicleRaycastClickToSwitch", AutoDrive.enterVehicleRaycastClickToSwitch) end @@ -65,6 +69,7 @@ function AutoDrive.registerFunctions(vehicleType) SpecializationUtil.registerFunction(vehicleType, "updateClosestWayPoint", AutoDrive.updateClosestWayPoint) SpecializationUtil.registerFunction(vehicleType, "collisionTestCallback", AutoDrive.collisionTestCallback) SpecializationUtil.registerFunction(vehicleType, "generateUTurn", AutoDrive.generateUTurn) + SpecializationUtil.registerFunction(vehicleType, "getCanAdTakeControl", AutoDrive.getCanAdTakeControl) -- see ExternalInterface.lua end function AutoDrive.registerEvents(vehicleType) @@ -262,7 +267,6 @@ function AutoDrive:onPostLoad(savegame) self.ad.showingMouse = false self.ad.lastMouseState = false - -- Creating a new transform on front of the vehicle self.ad.frontNode = createTransformGroup(self:getName() .. "_frontNode") link(self.components[1].node, self.ad.frontNode) @@ -423,6 +427,7 @@ function AutoDrive:onUpdate(dt) else -- all folded - no further tries necessary self.ad.foldStartTime = 0 + AutoDrive.getAllVehicleDimensions(self, true) end end @@ -439,7 +444,9 @@ function AutoDrive:onUpdate(dt) self.ad.taskModule:abortAllTasks() end - AutoDrive.updateAutoDriveLights(self) + if self.isServer then + AutoDrive.updateAutoDriveLights(self) + end --For 'legacy' purposes, this value should be kept since other mods already test for this: self.ad.mapMarkerSelected = self.ad.stateModule:getFirstMarkerId() @@ -658,46 +665,10 @@ function AutoDrive:onPostAttachImplement(attachable, inputJointDescIndex, jointD self.ad.attachableCombine = attachable attachable.ad = self.ad end + AutoDrive.setValidSupportedFillType(self) - if attachable ~= nil and AutoDrive:hasAL(attachable) then - -- AutoLoad - local currentFillType = AutoDrive:getALCurrentFillType(attachable) - if currentFillType ~= nil then - self.ad.stateModule:setFillType(currentFillType) - if g_currentMission.controlledVehicle ~= nil and g_currentMission.controlledVehicle.ad ~= nil and g_currentMission.controlledVehicle == self then - AutoDrive.Hud.lastUIScale = 0 - end - end - else - local supportedFillTypes = {} - local trailers, trailerCount = AutoDrive.getAllUnits(self) - for index, trailer in ipairs(trailers) do - if trailer.getFillUnits ~= nil then - for fillUnitIndex, _ in pairs(trailer:getFillUnits()) do - if trailer.getFillUnitSupportedFillTypes ~= nil then - for fillType, supported in pairs(trailer:getFillUnitSupportedFillTypes(fillUnitIndex)) do - if index == 1 then -- hide fuel types for 1st vehicle - local fillTypeName = g_fillTypeManager:getFillTypeNameByIndex(fillType) - if table.contains(AutoDrive.fuelFillTypes, fillTypeName) then - supported = false - end - end - if supported then - table.insert(supportedFillTypes, fillType) - end - end - end - end - end - end - - local storedSelectedFillType = self.ad.stateModule:getFillType() - if #supportedFillTypes > 0 and not table.contains(supportedFillTypes, storedSelectedFillType) then - self.ad.stateModule:setFillType(supportedFillTypes[1]) - if g_currentMission.controlledVehicle ~= nil and g_currentMission.controlledVehicle.ad ~= nil and g_currentMission.controlledVehicle == self then - AutoDrive.Hud.lastUIScale = 0 - end - end + if g_currentMission.controlledVehicle ~= nil and g_currentMission.controlledVehicle.ad ~= nil and g_currentMission.controlledVehicle == self then + AutoDrive.Hud.lastUIScale = 0 end AutoDrive.getFrontToolWidth(self, true) end @@ -721,19 +692,34 @@ function AutoDrive:onPreDetachImplement(implement) end end +-- Giants special behaviour: at time of the event the implement and all implements attached to it are still attached! +-- thats why the attached and all following have to be taken to special consideration! +function AutoDrive:onPostDetachImplement(implementIndex) + AutoDrive.setValidSupportedFillType(self, implementIndex) + if g_currentMission.controlledVehicle ~= nil and g_currentMission.controlledVehicle.ad ~= nil and g_currentMission.controlledVehicle == self then + AutoDrive.Hud.lastUIScale = 0 + end +end + + function AutoDrive:onEnterVehicle() - local trailers, trailerCount = AutoDrive.getAllUnits(self) - -- AutoDrive.debugMsg(object, "AutoDrive:onEnterVehicle trailerCount %s", tostring(trailerCount)) - if trailerCount > 0 then + if AutoDrive:hasAL(self) then -- AutoLoad - local currentFillType = AutoDrive:getALCurrentFillType(trailers[1]) + local currentFillType = AutoDrive:getALCurrentFillType(self) if currentFillType ~= nil then self.ad.stateModule:setFillType(currentFillType) + if g_currentMission.controlledVehicle ~= nil and g_currentMission.controlledVehicle.ad ~= nil and g_currentMission.controlledVehicle == self then + AutoDrive.Hud.lastUIScale = 0 + end end end if g_currentMission.controlledVehicle ~= nil and g_currentMission.controlledVehicle.ad ~= nil and g_currentMission.controlledVehicle == self then AutoDrive.Hud.lastUIScale = 0 end + if self.isServer and self.ad and self.ad.stateModule and not self.ad.stateModule:isActive() then + -- do not force dimension update while tabbing through active AD vehicles, which might be unfolded + AutoDrive.getAllVehicleDimensions(self, true) + end end function AutoDrive:onLeaveVehicle() @@ -742,58 +728,6 @@ function AutoDrive:onLeaveVehicle() end end --- CP event handler -function AutoDrive:onCpFinished() - AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpFinished start...") - if self.isServer then - if self.ad and self.ad.stateModule then - AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpFinished - event handler not implemented") - end - else - Logging.devError("AutoDrive:onCpFinished() must be called only on the server.") - end -end - -function AutoDrive:handleCPFieldWorker(vehicle) - AutoDrive.debugPrint(vehicle, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:handleCPFieldWorker start...") - if vehicle.isServer then - if vehicle.ad and vehicle.ad.stateModule and vehicle.startAutoDrive then - -- restart CP - vehicle.ad.restartCP = true - if not vehicle.ad.stateModule:isActive() then - if vehicle.ad.stateModule:getStartCP_AIVE() and vehicle.ad.stateModule:getUseCP_AIVE() then - -- CP button active - if table.contains(AutoDrive.modesToStartFromCP, vehicle.ad.stateModule:getMode()) then - -- mode allowed to activate - AutoDrive.debugPrint(vehicle, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:handleCPFieldWorker start AD") - vehicle.ad.stateModule:getCurrentMode():start() - else - -- deactivate CP button - AutoDriveMessageEvent.sendMessageOrNotification(vehicle, ADMessagesManager.messageTypes.ERROR, "$l10n_AD_Driver_of; %s: $l10n_AD_Wrong_Mode_takeover_from_CP;", 5000, vehicle.ad.stateModule:getName()) - vehicle.ad.restartCP = false -- do not continue CP course - vehicle.ad.stateModule:setStartCP_AIVE(false) - end - end - else - AutoDrive.debugPrint(vehicle, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:handleCPFieldWorker - AD already active, should not happen") - end - end - else - Logging.devError("AutoDrive:handleCPFieldWorker() must be called only on the server.") - end - AutoDrive.debugPrint(vehicle, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:handleCPFieldWorker end") -end - -function AutoDrive:onCpEmpty() - AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpEmpty start...") - AutoDrive:handleCPFieldWorker(self) -end - -function AutoDrive:onCpFull() - AutoDrive.debugPrint(self, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive:onCpFull start...") - AutoDrive:handleCPFieldWorker(self) -end - function AutoDrive:onDelete() AutoDriveHud:deleteMapHotspot(self) end @@ -1053,8 +987,7 @@ function AutoDrive:startAutoDrive() self.ad.isStoppingWithError = false self.ad.onRouteToPark = false self.ad.foldStartTime = g_time - - + AutoDrive.getAllVehicleDimensions(self, true) if self.spec_aiVehicle ~= nil then if self.getAINeedsTrafficCollisionBox ~= nil then if self:getAINeedsTrafficCollisionBox() then @@ -1089,9 +1022,6 @@ function AutoDrive:startAutoDrive() Logging.error("[AD] AutoDrive:startAutoDrive ERROR: unable to get helper for vehicle %s", tostring(name)) end - if self.spec_aiJobVehicle ~= nil then - self.spec_aiJobVehicle.currentHelper = currentHelper - end if currentHelper and currentHelper.index then self.ad.currentHelper = currentHelper self.ad.stateModule:setCurrentHelperIndex(currentHelper.index) @@ -1161,6 +1091,7 @@ function AutoDrive:stopAutoDrive() self.ad.onRouteToRepair = false AutoDrive.debugPrint(self, AutoDrive.DC_VEHICLEINFO, "AutoDrive:startAutoDrive self.ad.onRouteToRefuel %s", tostring(self.ad.onRouteToRefuel)) end + AutoDrive.updateAutoDriveLights(self, true) local isStartingAIVE = (not self.ad.isStoppingWithError and self.ad.stateModule:getStartCP_AIVE() and not self.ad.stateModule:getUseCP_AIVE()) local isPassingToCP = not self.ad.isStoppingWithError and (self.ad.restartCP == true or (self.ad.stateModule:getStartCP_AIVE() and self.ad.stateModule:getUseCP_AIVE())) @@ -1213,7 +1144,7 @@ function AutoDrive:onStartAutoDrive() local actualParkDestination = self.ad.stateModule:getParkDestinationAtJobFinished() if actualParkDestination >= 1 then else - AutoDriveMessageEvent.sendMessage(self, ADMessagesManager.messageTypes.ERROR, "$l10n_AD_parkVehicle_noPosSet;", 5000) + AutoDriveMessageEvent.sendMessage(self, ADMessagesManager.messageTypes.ERROR, "$l10n_AD_Driver_of; %s $l10n_AD_parkVehicle_noPosSet;", 5000, self.ad.stateModule:getName()) end end end @@ -1254,9 +1185,6 @@ function AutoDrive.checkAddHelper(vehicle, helperIndex, numHelpersToAdd) if helper ~= nil then g_helperManager:useHelper(helper) vehicle.ad.stateModule:setCurrentHelperIndex(helper.index) - if vehicle.spec_aiJobVehicle ~= nil and vehicle.spec_aiJobVehicle.currentHelper == nil then - vehicle.spec_aiJobVehicle.currentHelper = helper - end end end else @@ -1280,10 +1208,6 @@ function AutoDrive:onStopAutoDrive(isPassingToCP, isStartingAIVE) if self.ad.currentHelper ~= nil then g_helperManager:releaseHelper(self.ad.currentHelper) end - if self.spec_aiJobVehicle ~= nil and self.spec_aiJobVehicle.currentHelper ~= nil and self.spec_aiJobVehicle.currentHelper == self.ad.currentHelper then - -- we assign a helper for spec_aiJobVehicle, but do not remove it! - -- self.spec_aiJobVehicle.currentHelper = nil - end self.ad.currentHelper = nil self.ad.stateModule:setCurrentHelperIndex(0) @@ -1333,14 +1257,15 @@ function AutoDrive.passToExternalMod(vehicle) if not vehicle.ad.isStoppingWithError and distanceToStart < 30 then AutoDrive.debugPrint(vehicle, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive.passToExternalMod pass to other mod...") - if vehicle.ad.stateModule:getStartCP_AIVE() then - AutoDrive.debugPrint(vehicle, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive.passToExternalMod CP / AIVE button enabled") + if vehicle.ad.stateModule:getStartCP_AIVE() or vehicle.ad.restartCP == true then + AutoDrive.debugPrint(vehicle, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive.passToExternalMod CP / AIVE button enabled or restartCP") -- CP / AIVE button enabled - if vehicle.cpStartStopDriver ~= nil and vehicle.ad.stateModule:getUseCP_AIVE() then + if (vehicle.cpStartStopDriver ~= nil and vehicle.ad.stateModule:getUseCP_AIVE()) or vehicle.ad.restartCP == true then -- CP button active vehicle.spec_enterable.isControlled = false if vehicle.ad.restartCP == true then -- restart CP to continue + vehicle.ad.restartCP = false AutoDrive.debugPrint(vehicle, AutoDrive.DC_EXTERNALINTERFACEINFO, "AutoDrive.passToExternalMod pass control to CP with restart") AutoDrive:RestartCP(vehicle) else @@ -1534,8 +1459,12 @@ function AutoDrive:leaveVehicle(superFunc) superFunc(self) end -function AutoDrive:updateAutoDriveLights() - if self.ad ~= nil and self.ad.stateModule:isActive() then +function AutoDrive:updateAutoDriveLights(switchOff) + if switchOff then + if AutoDrive.getSetting("useHazardLightReverse", self) then + self:setTurnLightState(Lights.TURNLIGHT_OFF) + end + elseif self.ad ~= nil and self.ad.stateModule:isActive() then local isInRangeToLoadUnloadTarget = false local isInBunkerSilo = false local isOnField = ( self.getIsOnField ~= nil and self:getIsOnField() ) @@ -1551,6 +1480,17 @@ function AutoDrive:updateAutoDriveLights() if self.updateAILights ~= nil then self:updateAILights(isOnField or isInRangeToLoadUnloadTarget or isInBunkerSilo) end + + if self.setTurnLightState then + if AutoDrive.getSetting("useHazardLightReverse", self) then + local drivingReverse = (self.lastSpeedReal * self.movingDirection) < 0 + if drivingReverse then + self:setTurnLightState(Lights.TURNLIGHT_HAZARD, true) + elseif self.lastSpeedReal * 3600 < 0.1 then + self:setTurnLightState(Lights.TURNLIGHT_OFF) + end + end + end end end @@ -1563,7 +1503,7 @@ function AutoDrive:getCanMotorRun(superFunc) end function AutoDrive:getIsAIActive(superFunc) - return superFunc(self) or self.ad.stateModule:isActive() + return superFunc(self) or (self.ad and self.ad.stateModule and self.ad.stateModule:isActive()) end function AutoDrive:getIsVehicleControlledByPlayer(superFunc) @@ -1725,17 +1665,3 @@ function AutoDrive:collisionTestCallback(transformId, x, y, z, distance) end end ---- Disables click to switch, if the user clicks on the hud or the editor mode is active. -function AutoDrive:enterVehicleRaycastClickToSwitch(superFunc, x, y) - - if AutoDrive.isEditorModeEnabled() then - return - end - - --- Checks if the mouse is over a hud element. - if AutoDriveHud:isMouseOverHud(x, y) then - return - end - - superFunc(self, x, y) -end \ No newline at end of file diff --git a/scripts/Tasks/CatchCombinePipeTask.lua b/scripts/Tasks/CatchCombinePipeTask.lua index 263e9093..6b3a0689 100644 --- a/scripts/Tasks/CatchCombinePipeTask.lua +++ b/scripts/Tasks/CatchCombinePipeTask.lua @@ -101,6 +101,7 @@ function CatchCombinePipeTask:update(dt) local x, y, z = getWorldTranslation(self.vehicle.components[1].node) self.reverseStartLocation = {x = x, y = y, z = z} self.state = CatchCombinePipeTask.STATE_REVERSING + return end if combineTravelDistance > 85 then diff --git a/scripts/Tasks/LoadAtDestinationTask.lua b/scripts/Tasks/LoadAtDestinationTask.lua index 69a11ad6..415c3777 100644 --- a/scripts/Tasks/LoadAtDestinationTask.lua +++ b/scripts/Tasks/LoadAtDestinationTask.lua @@ -10,6 +10,7 @@ function LoadAtDestinationTask:new(vehicle, destinationID) o.vehicle = vehicle o.destinationID = destinationID o.trailers = nil + o.waitForALLoadTimer = AutoDriveTON:new() return o end @@ -73,6 +74,15 @@ function LoadAtDestinationTask:update(dt) else self.vehicle.ad.specialDrivingModule:stopVehicle() self.vehicle.ad.specialDrivingModule:update(dt) + local waitForALUnloadTime = AutoDrive.getSetting("ALUnloadWaitTime", self.vehicle) + + if self.vehicle.ad.trailerModule:getHasAL() then + -- AutoLoad wait time + if waitForALUnloadTime > 0 and not self.waitForALLoadTimer:timer(true, waitForALUnloadTime, dt) then + AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_PATHINFO, "LoadAtDestinationTask:update wait time for AutoLoad...") + return + end + end if self.vehicle.ad.trailerModule:wasAtSuitableTrigger() or ((AutoDrive.getSetting("rotateTargets", self.vehicle) == AutoDrive.RT_ONLYPICKUP or AutoDrive.getSetting("rotateTargets", self.vehicle) == AutoDrive.RT_PICKUPANDDELIVER) and AutoDrive.getSetting("useFolders")) then AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "LoadAtDestinationTask:update wasAtSuitableTrigger -> self:finished") diff --git a/scripts/Tasks/ParkTask.lua b/scripts/Tasks/ParkTask.lua index cd2d2f82..ee561f25 100644 --- a/scripts/Tasks/ParkTask.lua +++ b/scripts/Tasks/ParkTask.lua @@ -22,7 +22,7 @@ function ParkTask:setUp() self.actualParkDestinationName = ADGraphManager:getMapMarkerById(actualParkDestination).name self.vehicle.ad.onRouteToPark = true else - AutoDriveMessageEvent.sendMessage(self.vehicle, ADMessagesManager.messageTypes.ERROR, "$l10n_AD_parkVehicle_noPosSet;", 5000) + AutoDriveMessageEvent.sendMessage(self.vehicle, ADMessagesManager.messageTypes.ERROR, "$l10n_AD_Driver_of; %s $l10n_AD_parkVehicle_noPosSet;", 5000, self.vehicle.ad.stateModule:getName()) end end @@ -65,9 +65,14 @@ function ParkTask:update(dt) end function ParkTask:abort() + self.vehicle.ad.onRouteToPark = false end function ParkTask:finished(propagate) + self.vehicle.ad.onRouteToPark = false + -- avoid activate CP when park position is reached + self.vehicle.ad.restartCP = false + self.vehicle.ad.stateModule:setStartCP_AIVE(false) self.vehicle.ad.taskModule:setCurrentTaskFinished(propagate) if self.actualParkDestinationName ~= nil then AutoDriveMessageEvent.sendMessageOrNotification(self.vehicle, ADMessagesManager.messageTypes.INFO, "$l10n_AD_Driver_of; %s $l10n_AD_has_reached; %s", 5000, self.vehicle.ad.stateModule:getName(), self.actualParkDestinationName) diff --git a/scripts/Tasks/RefuelTask.lua b/scripts/Tasks/RefuelTask.lua index 36043752..320265c2 100644 --- a/scripts/Tasks/RefuelTask.lua +++ b/scripts/Tasks/RefuelTask.lua @@ -6,17 +6,15 @@ RefuelTask.STATE_DRIVING = 2 function RefuelTask:new(vehicle, destinationID) local o = RefuelTask:create() o.vehicle = vehicle - o.isRefueled = false o.destinationID = destinationID o.trailers = nil - o.fillTypesCount = 1 return o end function RefuelTask:setUp() AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "RefuelTask:setUp ") self.refuelTrigger = nil - self.fillTypesCount = 1 + self.matchingFillTypes = {} if ADGraphManager:getDistanceFromNetwork(self.vehicle) > 30 then self.state = RefuelTask.STATE_PATHPLANNING self.vehicle.ad.pathFinderModule:startPathPlanningToNetwork(self.destinationID) @@ -30,14 +28,12 @@ function RefuelTask:setUp() end function RefuelTask:update(dt) - + local inRefuelRange = false if self.refuelTrigger ~= nil and self.refuelTrigger.stoppedTimer ~= nil then -- update timer self.refuelTrigger.stoppedTimer:timer(not self.refuelTrigger.isLoading,300,dt) end - self.isRefueled = self.fillTypesCount > table.count(AutoDrive.fuelFillTypes) - if self.state == RefuelTask.STATE_PATHPLANNING then if self.vehicle.ad.pathFinderModule:hasFinished() then self.wayPoints = self.vehicle.ad.pathFinderModule:getPath() @@ -60,29 +56,37 @@ function RefuelTask:update(dt) if self.vehicle.ad.drivePathModule:isTargetReached() then self:finished() else - if self.refuelTrigger == nil then - self:isInRefuelRange() - end - if self.refuelTrigger ~= nil and not (self.refuelTrigger.isLoading or (self.refuelTrigger.stoppedTimer ~= nil and not self.refuelTrigger.stoppedTimer:done())) and not self.isRefueled then - self:startRefueling() - end - if self.refuelTrigger ~= nil and (self.refuelTrigger.isLoading or (self.refuelTrigger.stoppedTimer ~= nil and not self.refuelTrigger.stoppedTimer:done())) then + local refuelOngoing = self.refuelTrigger ~= nil and (self.refuelTrigger.isLoading or (self.refuelTrigger.stoppedTimer ~= nil and not self.refuelTrigger.stoppedTimer:done())) + if refuelOngoing then self.vehicle.ad.specialDrivingModule:stopVehicle() self.vehicle.ad.specialDrivingModule:update(dt) else self.vehicle.ad.drivePathModule:update(dt) end + + inRefuelRange = self:isInRefuelRange() + if inRefuelRange and not refuelOngoing then + if self:getMatchingFillTypes() then + + -- if self.refuelTrigger ~= nil and inRefuelRange and not (self.refuelTrigger.isLoading or (self.refuelTrigger.stoppedTimer ~= nil and not self.refuelTrigger.stoppedTimer:done())) then + if self.refuelTrigger ~= nil and not (self.refuelTrigger.isLoading) then + self:startRefueling() + end + + end + end end end end function RefuelTask:abort() + self.vehicle.ad.onRouteToRefuel = false + self.refuelTrigger = nil end function RefuelTask:finished() - self.vehicle.ad.onRouteToRefuel = #AutoDrive.getRequiredRefuels(self.vehicle, true) > 0 - - self.vehicle.ad.stateModule:setRefuelFillType(0) -- before start the mode again, we need to clear the refuel type + self.vehicle.ad.onRouteToRefuel = #AutoDrive.getRequiredRefuels(self.vehicle, self.vehicle.ad.onRouteToRefuel) > 0 + self.refuelTrigger = nil self.vehicle:stopAutoDrive() self.vehicle.ad.stateModule:getCurrentMode():start() self.vehicle.ad.taskModule:setCurrentTaskFinished(ADTaskModule.DONT_PROPAGATE) @@ -95,49 +99,86 @@ function RefuelTask:isInRefuelRange() if distance <= AutoDrive.MAX_REFUEL_TRIGGER_DISTANCE then if self.refuelTrigger == nil then - self.refuelTrigger = ADTriggerManager.getClosestRefuelTrigger(self.vehicle, self.vehicle.ad.onRouteToRefuel) + + local refuelTrigger = ADTriggerManager.getClosestRefuelTrigger(self.vehicle, self.vehicle.ad.onRouteToRefuel) + if refuelTrigger then + for _, fillableObject in pairs(refuelTrigger.fillableObjects) do + if fillableObject == self.vehicle or (fillableObject.object ~= nil and fillableObject.object == self.vehicle) then + AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "RefuelTask:isInRefuelRange return true") + self.refuelTrigger = refuelTrigger + return true + end + end + end end - if self.refuelTrigger ~= nil and not self.refuelTrigger.isLoading then - for _, fillableObject in pairs(self.refuelTrigger.fillableObjects) do - if fillableObject == self.vehicle or (fillableObject.object ~= nil and fillableObject.object == self.vehicle and fillableObject.fillUnitIndex == fillUnitIndex) then - AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "RefuelTask:isInRefuelRange return true") - return true + end + return self.refuelTrigger ~= nil +end + +function RefuelTask:getMatchingFillTypes() + local ret = false + self.matchingFillTypes = {} + if self.refuelTrigger ~= nil then + AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "RefuelTask:getMatchingFillTypes Start ") + + local requiredRefuelFillTypes = AutoDrive.getRequiredRefuels(self.vehicle, self.vehicle.ad.onRouteToRefuel) + if requiredRefuelFillTypes and #requiredRefuelFillTypes > 0 then + local spec = self.vehicle.spec_motorized + if spec ~= nil and spec.consumers ~= nil then + + for index, consumer in pairs(spec.consumers) do + for _, fillType in pairs(requiredRefuelFillTypes) do + local refuelFillTypeTitle = g_fillTypeManager:getFillTypeByIndex(fillType) and g_fillTypeManager:getFillTypeByIndex(fillType).title or "unknown" + if AutoDrive.fillTypesMatch(self.vehicle, self.refuelTrigger, self.vehicle, {fillType}, consumer.fillUnitIndex) then + local item = {fillType = fillType, wasLoaded = false, refuelTrigger = self.refuelTrigger} + table.insert(self.matchingFillTypes, item) + ret = true + end + end end end end end - return false + return ret end function RefuelTask:startRefueling() if self.refuelTrigger ~= nil and (not self.refuelTrigger.isLoading) then AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "RefuelTask:startRefueling Start refueling") - local fillUnits = self.vehicle:getFillUnits() - local fillTypeName = AutoDrive.fuelFillTypes[self.fillTypesCount] - local fillTypeIndex = g_fillTypeManager:getFillTypeIndexByName(fillTypeName) - for i = 1, #fillUnits do - if AutoDrive.fillTypesMatch(self.vehicle, self.refuelTrigger, self.vehicle, {fillTypeIndex}, i) then - AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "RefuelTask:startRefueling fillTypesMatch -> fillTypeName %s", fillTypeName) - - self.refuelTrigger.autoStart = true - self.refuelTrigger.selectedFillType = fillTypeIndex - AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "RefuelTask:startRefueling Start onFillTypeSelection") - self.refuelTrigger:onFillTypeSelection(fillTypeIndex) - if self.refuelTrigger.isLoading then - AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "RefuelTask:startRefueling isLoading") - self.refuelTrigger.selectedFillType = fillTypeIndex - self.refuelTrigger.autoStart = true - g_effectManager:setFillType(self.refuelTrigger.effects, self.refuelTrigger.selectedFillType) - end - if self.refuelTrigger.stoppedTimer == nil then - self.refuelTrigger.stoppedTimer = AutoDriveTON:new() + local spec = self.vehicle.spec_motorized + if spec ~= nil and spec.consumers ~= nil then + for index, consumer in pairs(spec.consumers) do + for _, item in pairs(self.matchingFillTypes) do + if not item.wasLoaded then + local refuelFillTypeTitle = g_fillTypeManager:getFillTypeByIndex(item.fillType) and g_fillTypeManager:getFillTypeByIndex(item.fillType).title or "unknown" + if AutoDrive.fillTypesMatch(self.vehicle, self.refuelTrigger, self.vehicle, {item.fillType}, consumer.fillUnitIndex) then + AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "RefuelTask:startRefueling fillTypesMatch -> refuelFillTypeTitle %s", refuelFillTypeTitle) + + self.refuelTrigger.autoStart = true + self.refuelTrigger.selectedFillType = item.fillType + AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "RefuelTask:startRefueling Start onFillTypeSelection") + self.refuelTrigger:onFillTypeSelection(item.fillType) + if self.refuelTrigger.isLoading then + AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "RefuelTask:startRefueling isLoading") + self.refuelTrigger.selectedFillType = item.fillType + self.refuelTrigger.autoStart = true + g_effectManager:setFillType(self.refuelTrigger.effects, self.refuelTrigger.selectedFillType) + end + if self.refuelTrigger.stoppedTimer == nil then + self.refuelTrigger.stoppedTimer = AutoDriveTON:new() + end + self.refuelTrigger.stoppedTimer:timer(false, 500) + + if self.refuelTrigger.isLoading then + item.wasLoaded = true + return + end + end + end end - self.refuelTrigger.stoppedTimer:timer(false, 300) - break end end - self.fillTypesCount = self.fillTypesCount + 1 end end diff --git a/scripts/Tasks/RepairTask.lua b/scripts/Tasks/RepairTask.lua index b7318a01..3133c27e 100644 --- a/scripts/Tasks/RepairTask.lua +++ b/scripts/Tasks/RepairTask.lua @@ -81,6 +81,7 @@ function RepairTask:update(dt) end function RepairTask:abort() + self.vehicle.ad.onRouteToRepair = false end function RepairTask:finished() diff --git a/scripts/Utils/AutoDriveUtilFuncs.lua b/scripts/Utils/AutoDriveUtilFuncs.lua index 582706b9..9f307659 100644 --- a/scripts/Utils/AutoDriveUtilFuncs.lua +++ b/scripts/Utils/AutoDriveUtilFuncs.lua @@ -342,11 +342,12 @@ function AutoDrive.foldAllImplements(vehicle) end for _, implement in pairs(implements) do local spec = implement.spec_foldable - if spec ~= nil then + if spec ~= nil and implement.getToggledFoldDirection then if implement:getToggledFoldDirection() ~= spec.turnOnFoldDirection then + local toggledFoldDirection = implement:getToggledFoldDirection() -- local ret = Foldable.actionControllerFoldEvent(implement, -1) - if spec.getIsFoldAllowed and spec:getIsFoldAllowed() and spec.setFoldState then - spec:setFoldState(implement:getToggledFoldDirection()) + if implement.getIsFoldAllowed and toggledFoldDirection and implement:getIsFoldAllowed(toggledFoldDirection) and implement.setFoldState then + implement:setFoldState(toggledFoldDirection) end end end @@ -365,7 +366,8 @@ function AutoDrive.getAllImplementsFolded(vehicle) spec = implement.spec_baleLoader if spec then -- bale loader - ret = ret and not spec:getIsAutomaticBaleUnloadingInProgress() + ret = ret and not implement:getIsAutomaticBaleUnloadingInProgress() + ret = ret and not implement:getIsBaleLoaderFoldingPlaying() ret = ret and spec.emptyState == BaleLoader.EMPTY_NONE end end @@ -529,25 +531,26 @@ function AutoDrive.getSupportedFillTypesOfAllUnitsAlphabetically(vehicle) local autoLoadFillTypes = nil -- AutoLoad - TODO: return the correct fillTypes if vehicle ~= nil then + local hasAL = false local trailers, _ = AutoDrive.getAllUnits(vehicle) - for trailerIndex, trailer in ipairs(trailers) do - if AutoDrive:hasAL(trailer) then - -- AutoLoad - TODO: return the correct fillTypes + for _, trailer in ipairs(trailers) do + hasAL = hasAL or AutoDrive:hasAL(trailer) + end + supportedFillTypes = {} + if hasAL then + -- AutoLoad - TODO: return the correct fillTypes + for trailerIndex, trailer in ipairs(trailers) do autoLoadFillTypes = AutoDrive:getALFillTypes(trailer) - else - if trailer.getFillUnits ~= nil then - for fillUnitIndex, _ in pairs(trailer:getFillUnits()) do - if trailer.getFillUnitSupportedFillTypes ~= nil then - for fillType, supported in pairs(trailer:getFillUnitSupportedFillTypes(fillUnitIndex)) do - - if trailerIndex == 1 then -- hide fuel types for 1st vehicle - local fillTypeName = g_fillTypeManager:getFillTypeNameByIndex(fillType) - if table.contains(AutoDrive.fuelFillTypes, fillTypeName) then - supported = false - end - end + end + else + local dischargeableUnits = AutoDrive.getAllDischargeableUnits(vehicle, true) + if dischargeableUnits and #dischargeableUnits > 0 then + for i = 1, #dischargeableUnits do + local dischargeableUnit = dischargeableUnits[i] + if dischargeableUnit.object and dischargeableUnit.object.getFillUnitSupportedFillTypes ~= nil then + if dischargeableUnit.fillUnitIndex and dischargeableUnit.fillUnitIndex > 0 then + for fillType, supported in pairs(dischargeableUnit.object:getFillUnitSupportedFillTypes(dischargeableUnit.fillUnitIndex)) do if supported then - local fillTypeName = g_fillTypeManager:getFillTypeNameByIndex(fillType) table.insert(supportedFillTypes, fillType) end end @@ -576,3 +579,68 @@ function AutoDrive.getSupportedFillTypesOfAllUnitsAlphabetically(vehicle) return supportedFillTypes end + +-- rotLimit is only available on server, so asume there are Y rotateable parts +function AutoDrive.hasVehicleRotatingYComponents(vehicle) + local ret = true + if vehicle.isServer then + ret = false + if vehicle then + if #vehicle.componentJoints >= 1 then + for k, componentJoint in ipairs(vehicle.componentJoints) do + if vehicle.componentJoints[k].rotLimit and vehicle.componentJoints[k].rotLimit[2] ~= 0 then + ret = true + end + end + end + end + end + return ret +end + +AutoDrive.implementsAllowedForReverseDriving = { +"trailer" +,"trailerlow" +,"trailerSaddled" +,"semitrailerCar" +} + +function AutoDrive.isImplementAllowedForReverseDriving(vehicle,implement) +-- return true for implements allowed move reverse + local ret = false + + if implement ~= nil and implement.spec_attachable ~= nil and implement.spec_attachable.attacherJoint ~= nil and implement.spec_attachable.attacherJoint.jointType ~= nil then + for i, name in ipairs(AutoDrive.implementsAllowedForReverseDriving) do + local key = "JOINTTYPE_"..string.upper(name) + + if AttacherJoints[key] ~= nil and AttacherJoints[key] == implement.spec_attachable.attacherJoint.jointType then + -- Logging.info("[AD] isImplementAllowedForReverseDriving implement allowed %s ", tostring(key)) + return true + end + end + end + + if implement ~= nil and implement.spec_attachable ~= nil + and AttacherJoints.JOINTTYPE_IMPLEMENT == implement.spec_attachable.attacherJoint.jointType + then + local breakforce = implement.spec_attachable:getBrakeForce() + -- Logging.info("[AD] isImplementAllowedForReverseDriving implement breakforce %s ", tostring(breakforce)) + if breakforce ~= nil and breakforce > 0.07 * 10 + and not (implement ~= nil and implement.getName ~= nil and implement:getName() == "GL 420") -- Grimme GL 420 needs special handling, as it has breakforce >0.07, but no trailed wheel + then + return true + end + end + + if implement ~= nil and implement.spec_attachable ~= nil + and AttacherJoints.JOINTTYPE_SEMITRAILER == implement.spec_attachable.attacherJoint.jointType + then + local implementX, implementY, implementZ = getWorldTranslation(implement.components[1].node) + local _, _, diffZ = worldToLocal(vehicle.components[1].node, implementX, implementY, implementZ) + if diffZ < -3 then + return true + end + end + return ret +end + diff --git a/scripts/Utils/CollisionDetectionUtils.lua b/scripts/Utils/CollisionDetectionUtils.lua index aa256721..b7dc1555 100644 --- a/scripts/Utils/CollisionDetectionUtils.lua +++ b/scripts/Utils/CollisionDetectionUtils.lua @@ -87,35 +87,46 @@ function AutoDrive.checkForVehiclePathInBox(boundingBox, minTurnRadius, searchin return false end -function AutoDrive.getBoundingBoxForVehicleAtPosition(vehicle, position) +function AutoDrive.getBoundingBoxForVehicleAtPosition(vehicle, position, force) local x, y, z = position.x, position.y, position.z local rx, _, rz = localDirectionToWorld(vehicle.components[1].node, 0, 0, 1) - local width = vehicle.size.width - local length = vehicle.size.length - local frontToolLength = 0 --AutoDrive.getFrontToolLength(vehicle) + local width, length = AutoDrive.getVehicleDimensions(vehicle, force) + local lengthOffset = vehicle.size.lengthOffset local vehicleVector = {x = rx, z = rz} local ortho = {x = -vehicleVector.z, z = vehicleVector.x} + local maxWidthLeft = (width / 2) + local maxWidthRight = (width / 2) + local maxLengthFront = (length / 2) + local maxLengthBack = (length / 2) + if vehicle and vehicle.ad and vehicle.ad.adDimensions and vehicle.ad.adDimensions.maxWidthLeft then + maxWidthLeft = vehicle.ad.adDimensions.maxWidthLeft + maxWidthRight = vehicle.ad.adDimensions.maxWidthRight + maxLengthFront = vehicle.ad.adDimensions.maxLengthFront + maxLengthBack = vehicle.ad.adDimensions.maxLengthBack + lengthOffset = 0 + end + local boundingBox = {} boundingBox[1] = { - x = x + (width / 2) * ortho.x - (length / 2) * vehicleVector.x, + x = x + (maxWidthRight) * ortho.x - ((maxLengthBack) - lengthOffset) * vehicleVector.x, y = y + 2, - z = z + (width / 2) * ortho.z - (length / 2) * vehicleVector.z + z = z + (maxWidthRight) * ortho.z - ((maxLengthBack) - lengthOffset) * vehicleVector.z } boundingBox[2] = { - x = x - (width / 2) * ortho.x - (length / 2) * vehicleVector.x, + x = x - (maxWidthLeft) * ortho.x - ((maxLengthBack) - lengthOffset) * vehicleVector.x, y = y + 2, - z = z - (width / 2) * ortho.z - (length / 2) * vehicleVector.z + z = z - (maxWidthLeft) * ortho.z - ((maxLengthBack) - lengthOffset) * vehicleVector.z } boundingBox[3] = { - x = x - (width / 2) * ortho.x + (length / 2) * vehicleVector.x, + x = x - (maxWidthLeft) * ortho.x + ((maxLengthFront) + lengthOffset) * vehicleVector.x, y = y + 2, - z = z - (width / 2) * ortho.z + (length / 2) * vehicleVector.z + z = z - (maxWidthLeft) * ortho.z + ((maxLengthFront) + lengthOffset) * vehicleVector.z } boundingBox[4] = { - x = x + (width / 2) * ortho.x + (length / 2) * vehicleVector.x, + x = x + (maxWidthRight) * ortho.x + ((maxLengthFront) + lengthOffset) * vehicleVector.x, y = y + 2, - z = z + (width / 2) * ortho.z + (length / 2) * vehicleVector.z + z = z + (maxWidthRight) * ortho.z + ((maxLengthFront) + lengthOffset) * vehicleVector.z } --ADDrawingManager:addLineTask(boundingBox[1].x, boundingBox[1].y, boundingBox[1].z, boundingBox[2].x, boundingBox[2].y, boundingBox[2].z, 1, 1, 0) @@ -126,12 +137,12 @@ function AutoDrive.getBoundingBoxForVehicleAtPosition(vehicle, position) return boundingBox end -function AutoDrive.getBoundingBoxForVehicle(vehicle) +function AutoDrive.getBoundingBoxForVehicle(vehicle, force) local x, y, z = getWorldTranslation(vehicle.components[1].node) local position = {x = x, y = y, z = z} - return AutoDrive.getBoundingBoxForVehicleAtPosition(vehicle, position) + return AutoDrive.getBoundingBoxForVehicleAtPosition(vehicle, position, force) end function AutoDrive.getDistanceBetween(vehicleOne, vehicleTwo) @@ -161,3 +172,170 @@ function AutoDrive.debugDrawBoundingBoxForVehicles() end end end + +-- dimension measurement of vehicles +ADDimensionSensor = {} +function ADDimensionSensor:new(vehicle) + local o = {} + setmetatable(o, self) + self.__index = self + o.vehicle = vehicle + o.mask = 0 + o.collisionHits = 0 + o.selfHits = 0 + return o +end + +function ADDimensionSensor:getMask() + local mask = 0 + + mask = mask + math.pow(2, ADCollSensor.mask_Non_Pushable_1 - 1) + mask = mask + math.pow(2, ADCollSensor.mask_Non_Pushable_2 - 1) + mask = mask + math.pow(2, ADCollSensor.mask_static_world_1 - 1) + mask = mask + math.pow(2, ADCollSensor.mask_static_world_2 - 1) + mask = mask + math.pow(2, ADCollSensor.mask_tractors - 1) + mask = mask + math.pow(2, ADCollSensor.mask_combines - 1) + mask = mask + math.pow(2, ADCollSensor.mask_trailers - 1) + return mask +end + +function ADDimensionSensor:getRealVehicleDimensions() + self.mask = self:getMask() + self.collisionHits = 0 + self.selfHits = 0 + local measureRange = math.max(self.vehicle.size.width + 1, self.vehicle.size.length + 1) + + local maxWidthLeft, maxWidthRight, maxLengthFront, maxLengthBack = 0,0,0,0 + + local rx, ry, rz = getWorldRotation(self.vehicle.components[1].node) + + local function leftright(dimStart, dimEnd) + local ret = self.vehicle.size.width / 2 + local selfHitCount = 0 + local minDistance = math.huge + local diff = dimEnd - dimStart + local step = 0.1 + if diff < 0 then + step = -step + end + for distance = dimStart, dimEnd, step do + local x,y,z = localToWorld(self.vehicle.components[1].node, distance, self.vehicle.size.height / 2, 0) + self.selfHits = 0 + if AutoDrive.getDebugChannelIsSet(AutoDrive.DC_SENSORINFO) then + -- DebugUtil.drawOverlapBox(x,y,z, rx, ry, rz, 0.1, measureRange, measureRange, 1, 1, 1) + end + self.collisionHits = overlapBox(x,y,z, rx, ry, rz, 0.1, measureRange, measureRange, "getRealVehicleDimensions_Callback", self, self.mask, true, true, true) + if self.selfHits == 0 then + -- found no collision with vehicle itself + if selfHitCount < 5 then + selfHitCount = selfHitCount + 1 + minDistance = math.min(minDistance, math.abs(distance)) + else + -- if n consecutive hits are reached, take the min. distance + ret = minDistance + break + end + else + -- if hit itself, reset the counting + selfHitCount = 0 + minDistance = math.huge + end + end + return ret + end + maxWidthLeft = leftright(0, measureRange) -- measure to left + maxWidthRight = leftright(0, -measureRange) -- measure to right + + local function frontback(dimStart, dimEnd) + local ret = self.vehicle.size.length / 2 + local selfHitCount = 0 + local minDistance = math.huge + local diff = dimEnd - dimStart + local step = 0.1 + if diff < 0 then + step = -step + end + for distance = dimStart, dimEnd, step do + local x,y,z = localToWorld(self.vehicle.components[1].node, 0, self.vehicle.size.height / 2, distance) + self.selfHits = 0 + if AutoDrive.getDebugChannelIsSet(AutoDrive.DC_SENSORINFO) then + -- DebugUtil.drawOverlapBox(x,y,z, rx, ry, rz, measureRange, measureRange, 0.1, 1, 1, 1) + end + self.collisionHits = overlapBox(x,y,z, rx, ry, rz, measureRange, measureRange, 0.1, "getRealVehicleDimensions_Callback", self, self.mask, true, true, true) + if self.selfHits == 0 then + -- found no collision with vehicle itself + if selfHitCount < 5 then + selfHitCount = selfHitCount + 1 + minDistance = math.min(minDistance, math.abs(distance)) + else + -- if n consecutive hits are reached, take the min. distance + ret = minDistance + break + end + else + -- if hit itself, reset the counting + selfHitCount = 0 + minDistance = math.huge + end + end + return ret + end + maxLengthFront = frontback(0, measureRange) -- measure to front + maxLengthBack = frontback(0, -measureRange) -- measure to back + + self.vehicle.ad.adDimensions.maxWidthLeft = maxWidthLeft + AutoDrive.DIMENSION_ADDITION + self.vehicle.ad.adDimensions.maxWidthRight = maxWidthRight + AutoDrive.DIMENSION_ADDITION + self.vehicle.ad.adDimensions.maxLengthFront = maxLengthFront + AutoDrive.DIMENSION_ADDITION + self.vehicle.ad.adDimensions.maxLengthBack = maxLengthBack + AutoDrive.DIMENSION_ADDITION + local realWidth = 2 * math.max(maxWidthLeft, maxWidthRight) + AutoDrive.DIMENSION_ADDITION + local realLegth = 2 * math.max(maxLengthFront, maxLengthBack) + AutoDrive.DIMENSION_ADDITION + return realWidth, realLegth +end + +function ADDimensionSensor:getRealVehicleDimensions_Callback(transformId) + if transformId ~= nil then + local collisionObject = g_currentMission.nodeToObject[transformId] + if collisionObject ~= nil and collisionObject == self.vehicle then + self.selfHits = self.selfHits + 1 + end + end + return true +end + +function AutoDrive.getVehicleDimensions(vehicle, force) + if vehicle == nil then + return 0,0 + end + if vehicle.spec_pallet then + -- do not measure pallets + return vehicle.size.width, vehicle.size.length + end + if vehicle.ad == nil then + vehicle.ad = {} + end + if vehicle.ad.adDimensions == nil then + vehicle.ad.adDimensions = {} + end + -- default taken from vehicle definition + vehicle.ad.adDimensions.width, vehicle.ad.adDimensions.length = vehicle.size.width, vehicle.size.length + if force then -- only measure if force true + vehicle.ad.adDimensions = {} + if vehicle.ad.adDimSensor == nil then + vehicle.ad.adDimSensor = ADDimensionSensor:new(vehicle) + end + if vehicle.ad.adDimSensor and vehicle.ad.adDimSensor.getRealVehicleDimensions then + vehicle.ad.adDimensions.width, vehicle.ad.adDimensions.length = vehicle.ad.adDimSensor:getRealVehicleDimensions() + end + end + return vehicle.ad.adDimensions.width, vehicle.ad.adDimensions.length +end + +-- ATTENTION: This shall only be called if all components of the complete vehicle train is folded, in transport position etc. !!! +function AutoDrive.getAllVehicleDimensions(vehicle, force) + local trailers = AutoDrive.getAllImplements(vehicle, true) + for _, trailer in ipairs(trailers) do + if not AutoDrive.hasVehicleRotatingYComponents(trailer) then + AutoDrive.getVehicleDimensions(trailer, force) + end + end +end diff --git a/scripts/Utils/CombineUtil.lua b/scripts/Utils/CombineUtil.lua index d8562173..84aa96cb 100644 --- a/scripts/Utils/CombineUtil.lua +++ b/scripts/Utils/CombineUtil.lua @@ -23,7 +23,7 @@ function AutoDrive.getDischargeNode(combine) end end -function AutoDrive.getPipeRoot(combine) +function AutoDrive.getPipeRoot_old(combine) if combine.ad ~= nil and combine.ad.pipeRoot ~= nil then return combine.ad.pipeRoot end @@ -68,11 +68,55 @@ function AutoDrive.getPipeRoot(combine) return pipeRoot end + +function AutoDrive.getPipeRoot(combine) + if combine.ad ~= nil and combine.ad.pipeRoot ~= nil then + return combine.ad.pipeRoot + end + local dischargeNode = AutoDrive.getDischargeNode(combine) + local pipeRoot = nil + + if dischargeNode then + for _, component in ipairs(combine.components) do + + local node = dischargeNode + local count = 0 + repeat + node = getParent(node) + count = count + 1 + until ((node == component.node) or (node == 0) or (node == nil) or count >= 100) + + if node and node ~= 0 then + -- found + pipeRoot = node + break + end + end + end + if pipeRoot == nil or pipeRoot == 0 then + -- fallback + pipeRoot = combine.components[1].node + end + + if combine.ad ~= nil then + combine.ad.pipeRoot = pipeRoot + end + return pipeRoot +end + +-- ret: -1 right, 1 left, 0 behind +-- not for sugarcane harvesters, choppers!!! function AutoDrive.getPipeSide(combine) - local combineNode = combine.components[1].node + if combine.ad ~= nil and combine.ad.storedPipeSide ~= nil then + return combine.ad.storedPipeSide + end + local combineNode = AutoDrive.getPipeRoot(combine) local dischargeNode = AutoDrive.getDischargeNode(combine) local dischargeX, dichargeY, dischargeZ = getWorldTranslation(dischargeNode) local diffX, _, _ = worldToLocal(combineNode, dischargeX, dichargeY, dischargeZ) + if combine.ad ~= nil and AutoDrive.isPipeOut(combine) and not AutoDrive.getIsBufferCombine(combine) then + combine.ad.storedPipeSide = AutoDrive.sign(diffX) + end return AutoDrive.sign(diffX) end @@ -88,10 +132,10 @@ function AutoDrive.getPipeLength(combine) pipeRootZ - dischargeZ) --AutoDrive.debugPrint(combine, AutoDrive.DC_COMBINEINFO, "AutoDrive.getPipeLength - " .. length) if AutoDrive.isPipeOut(combine) and not AutoDrive.getIsBufferCombine(combine) then - local combineNode = combine.components[1].node + local combineNode = AutoDrive.getPipeRoot(combine) local dischargeX, dichargeY, dischargeZ = getWorldTranslation(AutoDrive.getDischargeNode(combine)) diffX, _, _ = worldToLocal(combineNode, dischargeX, dichargeY, dischargeZ) - length = math.abs(diffX) - combine.size.width /2 + length = math.abs(diffX) -- Store pipe length for 'normal' harvesters if combine.ad ~= nil then diff --git a/scripts/Utils/DevFuncs.lua b/scripts/Utils/DevFuncs.lua index 72f82cd5..d73313b9 100644 --- a/scripts/Utils/DevFuncs.lua +++ b/scripts/Utils/DevFuncs.lua @@ -1,3 +1,25 @@ +function AutoDrive:checkDestinations(showAll) + local vehicle = g_currentMission.controlledVehicle + if vehicle == nil or vehicle.ad == nil or vehicle.ad.stateModule == nil then + Logging.error("ADCheckDestinations needs to be called only while entered an AD vehicle") + return + end + local mapMarkers = ADGraphManager:getMapMarkers() + if mapMarkers and table.count(mapMarkers) > 0 then + + for index, mapMarker in pairs(mapMarkers) do + local wayPoints = ADGraphManager:getPathTo(vehicle, mapMarker.id) + + if wayPoints == nil or (wayPoints[2] == nil and (wayPoints[1] == nil or (wayPoints[1] ~= nil and wayPoints[1].id ~= mapMarker.id))) then + Logging.error("[AD] Could not find a path to ->%s<- !", tostring(mapMarker.name)) + else + if showAll then + Logging.info("[AD] Path found to ->%s<- ", tostring(mapMarker.name)) + end + end + end + end +end function AutoDrive.debugVehicleMsg(vehicle, msg) if vehicle ~= nil and vehicle.ad ~= nil and vehicle.ad.debug ~= nil then vehicle.ad.debug:Enqueue(msg) @@ -30,4 +52,5 @@ end function AutoDrive.devAutoDriveInit() Logging.info("[AD] Info: g_server %s g_client %s g_dedicatedServer %s g_dedicatedServerInfo %s getUserProfileAppPath %s getIsClient %s getIsServer %s isMasterUser %s", tostring(g_server), tostring(g_client), tostring(g_dedicatedServer), tostring(g_dedicatedServerInfo), tostring(getUserProfileAppPath()), tostring(g_currentMission:getIsClient()), tostring(g_currentMission:getIsServer()), tostring(g_currentMission.isMasterUser)) + addConsoleCommand( 'ADCheckDestinations', 'Find path to all destinations', 'checkDestinations', AutoDrive ) end diff --git a/scripts/Utils/PathFinderUtils.lua b/scripts/Utils/PathFinderUtils.lua index 3d9e8c24..8a570621 100644 --- a/scripts/Utils/PathFinderUtils.lua +++ b/scripts/Utils/PathFinderUtils.lua @@ -66,47 +66,3 @@ function AutoDrive.boundingBoxFromCorners(cornerX, cornerZ, corner2X, corner2Z, return boundingBox end -AutoDrive.implementsAllowedForReverseDriving = { -"trailer" -,"trailerlow" -} - -function AutoDrive.isImplementAllowedForReverseDriving(vehicle,implement) --- return true for implements allowed move reverse - local ret = false - - if implement ~= nil and implement.spec_attachable ~= nil and implement.spec_attachable.attacherJoint ~= nil and implement.spec_attachable.attacherJoint.jointType ~= nil then - for i, name in ipairs(AutoDrive.implementsAllowedForReverseDriving) do - local key = "JOINTTYPE_"..string.upper(name) - - if AttacherJoints[key] ~= nil and AttacherJoints[key] == implement.spec_attachable.attacherJoint.jointType then - -- Logging.info("[AD] isImplementAllowedForReverseDriving implement allowed %s ", tostring(key)) - return true - end - end - end - - if implement ~= nil and implement.spec_attachable ~= nil - and AttacherJoints.JOINTTYPE_IMPLEMENT == implement.spec_attachable.attacherJoint.jointType - then - local breakforce = implement.spec_attachable:getBrakeForce() - -- Logging.info("[AD] isImplementAllowedForReverseDriving implement breakforce %s ", tostring(breakforce)) - if breakforce ~= nil and breakforce > 0.07 * 10 - and not (implement ~= nil and implement.getName ~= nil and implement:getName() == "GL 420") -- Grimme GL 420 needs special handling, as it has breakforce >0.07, but no trailed wheel - then - return true - end - end - - if implement ~= nil and implement.spec_attachable ~= nil - and AttacherJoints.JOINTTYPE_SEMITRAILER == implement.spec_attachable.attacherJoint.jointType - then - local implementX, implementY, implementZ = getWorldTranslation(implement.components[1].node) - local _, _, diffZ = worldToLocal(vehicle.components[1].node, implementX, implementY, implementZ) - if diffZ < -3 then - return true - end - end - - return ret -end \ No newline at end of file diff --git a/scripts/Utils/TrailerUtil.lua b/scripts/Utils/TrailerUtil.lua index 94092fbb..03cced65 100644 --- a/scripts/Utils/TrailerUtil.lua +++ b/scripts/Utils/TrailerUtil.lua @@ -52,6 +52,8 @@ function AutoDrive.getAllFillLevels(vehicles) fillFreeCapacity = fillFreeCapacity + vehicleFillFreeCapacity end local filledToUnload = AutoDrive.isUnloadFillLevelReached(rootVehicle, fillFreeCapacity, fillCapacity) + + AutoDrive.debugPrint(nil, AutoDrive.DC_TRAILERINFO, "AutoDrive.getAllFillLevels end hasAL %s fillLevel %s fillCapacity %s filledToUnload %s fillFreeCapacity %s", tostring(hasAL), tostring(fillLevel), tostring(fillCapacity), tostring(filledToUnload), tostring(fillFreeCapacity)) return fillLevel, fillCapacity, filledToUnload, fillFreeCapacity end @@ -180,26 +182,20 @@ function AutoDrive.getObjectFillLevels(object) break end end - elseif object.spec_sowingMachine and object.getSowingMachineFillUnitIndex and object:getSowingMachineFillUnitIndex() > 0 then - if object:getSowingMachineFillUnitIndex() == fillUnitIndex then - updateFillLevels(fillUnitIndex) - end - elseif object.spec_sprayer and object.getSprayerFillUnitIndex and object:getSprayerFillUnitIndex() > 0 then - if object:getSprayerFillUnitIndex() == fillUnitIndex then - updateFillLevels(fillUnitIndex) - end - elseif object.spec_saltSpreader and object.spec_saltSpreader.fillUnitIndex and object.spec_saltSpreader.fillUnitIndex > 0 then - if object.spec_saltSpreader.fillUnitIndex == fillUnitIndex then - updateFillLevels(fillUnitIndex) - end - elseif object.spec_baleLoader and object.spec_baleLoader.fillUnitIndex and object.spec_baleLoader.fillUnitIndex > 0 then - if object.spec_baleLoader.fillUnitIndex == fillUnitIndex then - updateFillLevels(fillUnitIndex) - end + elseif object.spec_sowingMachine and object.getSowingMachineFillUnitIndex and object:getSowingMachineFillUnitIndex() > 0 and object:getSowingMachineFillUnitIndex() == fillUnitIndex then + updateFillLevels(fillUnitIndex) + elseif object.spec_sprayer and object.getSprayerFillUnitIndex and object:getSprayerFillUnitIndex() > 0 and object:getSprayerFillUnitIndex() == fillUnitIndex then + updateFillLevels(fillUnitIndex) + elseif object.spec_saltSpreader and object.spec_saltSpreader.fillUnitIndex and object.spec_saltSpreader.fillUnitIndex > 0 and object.spec_saltSpreader.fillUnitIndex == fillUnitIndex then + updateFillLevels(fillUnitIndex) + elseif object.spec_baleLoader and object.spec_baleLoader.fillUnitIndex and object.spec_baleLoader.fillUnitIndex > 0 and object.spec_baleLoader.fillUnitIndex == fillUnitIndex then + updateFillLevels(fillUnitIndex) end end end local filledToUnload = AutoDrive.isUnloadFillLevelReached(rootVehicle, fillFreeCapacity, fillCapacity) + + AutoDrive.debugPrint(object, AutoDrive.DC_TRAILERINFO, "AutoDrive.getObjectFillLevels end fillLevel %s fillCapacity %s filledToUnload %s fillFreeCapacity %s", tostring(fillLevel), tostring(fillCapacity), tostring(filledToUnload), tostring(fillFreeCapacity)) return fillLevel, fillCapacity, filledToUnload, fillFreeCapacity end @@ -266,6 +262,8 @@ function AutoDrive.getIsFillUnitFull(vehicle, fillUnitIndex) fillUnitFull = false end end + + AutoDrive.debugPrint(vehicle, AutoDrive.DC_TRAILERINFO, "AutoDrive.getIsFillUnitFull end fillUnitIndex %s AutoDrive:hasAL(vehicle) %s fillUnitFull %s", tostring(fillUnitIndex), tostring(AutoDrive:hasAL(vehicle)), tostring(fillUnitFull)) return fillUnitFull end @@ -282,10 +280,10 @@ function AutoDrive.getIsFillUnitEmpty(vehicle, fillUnitIndex) -- AutoLoad local fillLevel, _, _, _ = AutoDrive:getALObjectFillLevels(vehicle) fillUnitEmpty = fillLevel < 0.001 - elseif vehicle.getFillUnitFillLevelPercentage ~= nil then - fillUnitEmpty = vehicle:getFillUnitFillLevelPercentage(fillUnitIndex) <= 0.001 + elseif vehicle.getFillUnitFillLevel ~= nil then + fillUnitEmpty = vehicle:getFillUnitFillLevel(fillUnitIndex) <= 0.001 end - + AutoDrive.debugPrint(vehicle, AutoDrive.DC_TRAILERINFO, "AutoDrive.getIsFillUnitEmpty end fillUnitIndex %s AutoDrive:hasAL(vehicle) %s fillUnitEmpty %s", tostring(fillUnitIndex), tostring(AutoDrive:hasAL(vehicle)), tostring(fillUnitEmpty)) return fillUnitEmpty end @@ -300,8 +298,8 @@ function AutoDrive.fillTypesMatch(vehicle, fillTrigger, workTool, allowedFillTyp if allowedFillTypes ~= nil then fillTypesToCheck = allowedFillTypes else - if vehicle.ad.stateModule:getFillType() == nil then - table.insert(fillTypesToCheck, FillType.UNKNOWN) + if vehicle.ad.stateModule:getFillType() == nil or vehicle.ad.stateModule:getFillType() == FillType.UNKNOWN then + return false else table.insert(fillTypesToCheck, vehicle.ad.stateModule:getFillType()) end @@ -352,7 +350,7 @@ function AutoDrive.fillTypesMatch(vehicle, fillTrigger, workTool, allowedFillTyp if typesMatch then for _, allowedFillType in pairs(fillTypesToCheck) do if allowedFillType == FillType.UNKNOWN then - return true + return false end end @@ -389,26 +387,24 @@ function AutoDrive.getAllUnits(vehicle) Logging.error("[AD] AutoDrive.getAllUnits vehicle == nil") return nil, 0 end + local tempUnits = {} vehicle = vehicle:getRootVehicle() if vehicle ~= nil then - if vehicle.ad == nil then - vehicle.ad = {} - end - if vehicle.ad.tempVehicles == nil then - vehicle.ad.tempVehicles = {} - end - - vehicle.ad.tempVehicles = {} - table.insert(vehicle.ad.tempVehicles, vehicle) -- first is the vehicle itself + table.insert(tempUnits, vehicle) -- first is the vehicle itself local onlyDischargeable = false if vehicle.getAttachedImplements ~= nil then for _, implement in pairs(vehicle:getAttachedImplements()) do - AutoDrive.getTrailersOfImplement(vehicle, implement.object, onlyDischargeable) + local trailers = AutoDrive.getTrailersOfImplement(vehicle, implement.object, onlyDischargeable) + if trailers then + for _, trailer in pairs(trailers) do + table.insert(tempUnits, trailer) + end + end end end - return vehicle.ad.tempVehicles, #vehicle.ad.tempVehicles + return tempUnits, #tempUnits end return nil, 0 end @@ -419,21 +415,34 @@ function AutoDrive.getTrailersOfImplement(vehicle, attachedImplement, onlyDischa Logging.error("[AD] AutoDrive.getTrailersOfImplement vehicle == nil") return end + local trailersOfImplement = nil if attachedImplement ~= nil then if (((attachedImplement.typeDesc == g_i18n:getText("typeDesc_tipper") or attachedImplement.spec_dischargeable ~= nil) or not (onlyDischargeable == true)) and attachedImplement.getFillUnits ~= nil) or AutoDrive:hasAL(attachedImplement) then if not (attachedImplement.typeDesc == g_i18n:getText("typeDesc_frontloaderTool") or attachedImplement.typeDesc == g_i18n:getText("typeDesc_wheelLoaderTool")) then --avoid trying to fill shovels and levellers atached - table.insert(vehicle.ad.tempVehicles, attachedImplement) + if trailersOfImplement == nil then + trailersOfImplement = {} + end + table.insert(trailersOfImplement, attachedImplement) end end if attachedImplement.getAttachedImplements ~= nil then for _, implement in pairs(attachedImplement:getAttachedImplements()) do - AutoDrive.getTrailersOfImplement(vehicle, implement.object) + local trailers = AutoDrive.getTrailersOfImplement(vehicle, implement.object) + if trailers then + if trailersOfImplement == nil then + trailersOfImplement = {} + end + for _, trailer in pairs(trailers) do + table.insert(trailersOfImplement, trailer) + end + end end end end + return trailersOfImplement end --- new, return list of all fillUnits of vehicle and trailers for nonFuel or nil +-- new, return list of all fillUnits of vehicle and trailers for nonFuel or nil - currently not used function AutoDrive.getAllNonFuelFillUnits_old(vehicle, initialize) local nonFuelFillUnits = nil if vehicle == nil or vehicle.ad == nil then @@ -473,12 +482,12 @@ function AutoDrive.getAllNonFuelFillUnits_old(vehicle, initialize) end -- consider only dischargable fillUnits -function AutoDrive.getAllNonFuelFillUnits(vehicle, initialize) - local nonFuelFillUnits = nil +function AutoDrive.getAllDischargeableUnits(vehicle, initialize) + local dischargeableUnits = nil if vehicle == nil or vehicle.ad == nil then - return nonFuelFillUnits + return dischargeableUnits end - if vehicle.ad.nonFuelFillUnits == nil or initialize then + if vehicle.ad.dischargeableUnits == nil or initialize then local trailers = AutoDrive.getAllUnits(vehicle) for _, trailer in ipairs(trailers) do @@ -491,15 +500,15 @@ function AutoDrive.getAllNonFuelFillUnits(vehicle, initialize) if dischargeNode.fillUnitIndex and dischargeNode.fillUnitIndex > 0 and dischargeNode.fillUnitIndex == fillUnitIndex then -- the fillUnit can be discharged if fillUnit.exactFillRootNode then - if nonFuelFillUnits == nil then - nonFuelFillUnits = {} + if dischargeableUnits == nil then + dischargeableUnits = {} end - table.insert(nonFuelFillUnits, {fillUnit = fillUnit, node = fillUnit.exactFillRootNode, object = trailer, fillUnitIndex = fillUnitIndex}) + table.insert(dischargeableUnits, {fillUnit = fillUnit, node = fillUnit.exactFillRootNode, object = trailer, fillUnitIndex = fillUnitIndex}) elseif fillUnit.fillRootNode then - if nonFuelFillUnits == nil then - nonFuelFillUnits = {} + if dischargeableUnits == nil then + dischargeableUnits = {} end - table.insert(nonFuelFillUnits, {fillUnit = fillUnit, node = fillUnit.fillRootNode, object = trailer, fillUnitIndex = fillUnitIndex}) + table.insert(dischargeableUnits, {fillUnit = fillUnit, node = fillUnit.fillRootNode, object = trailer, fillUnitIndex = fillUnitIndex}) end break end @@ -508,38 +517,38 @@ function AutoDrive.getAllNonFuelFillUnits(vehicle, initialize) end end end - vehicle.ad.nonFuelFillUnits = nonFuelFillUnits + vehicle.ad.dischargeableUnits = dischargeableUnits end - return vehicle.ad.nonFuelFillUnits + return vehicle.ad.dischargeableUnits end -- new, return next fillUnit with room to fill or RootVehicle as default -function AutoDrive.getNextFreeNonFuelFillUnit(vehicle) - local nextFreeNonFuelFillUnit = nil +function AutoDrive.getNextFreeDischargeableUnit(vehicle) + local nextFreeDischargeableUnit = nil local rootVehicle = vehicle.getRootVehicle and vehicle:getRootVehicle() -- default in case no free fill unit will be found - local nextFreeNonFuelFillNode = rootVehicle and rootVehicle.components[1].node - + local nextFreeDischargeableNode = rootVehicle and rootVehicle.components[1].node + if vehicle == nil then - return nextFreeNonFuelFillUnit, nextFreeNonFuelFillNode + return nextFreeDischargeableUnit, nextFreeDischargeableNode end - local allNonFuelFillUnits = AutoDrive.getAllNonFuelFillUnits(vehicle) - if allNonFuelFillUnits == nil then - allNonFuelFillUnits = AutoDrive.getAllNonFuelFillUnits(vehicle, true) + local allDischargeableUnits = AutoDrive.getAllDischargeableUnits(vehicle) + if allDischargeableUnits == nil then + allDischargeableUnits = AutoDrive.getAllDischargeableUnits(vehicle, true) end - if allNonFuelFillUnits ~= nil then - for index, item in ipairs(allNonFuelFillUnits) do + if allDischargeableUnits ~= nil then + for index, item in ipairs(allDischargeableUnits) do if item.fillUnit and item.node and item.object and item.object.getFillUnitFreeCapacity and item.fillUnitIndex then local freeCapacity = item.object:getFillUnitFreeCapacity(item.fillUnitIndex) -- needed to consider mass feature if freeCapacity > 0.1 then - nextFreeNonFuelFillUnit = item.fillUnit - nextFreeNonFuelFillNode = item.node + nextFreeDischargeableUnit = item.fillUnit + nextFreeDischargeableNode = item.node break end end end end - return nextFreeNonFuelFillUnit, nextFreeNonFuelFillNode + return nextFreeDischargeableUnit, nextFreeDischargeableNode end -- ################################################################################################### @@ -777,7 +786,7 @@ function AutoDrive.getTriggerAndTrailerPairs(vehicle, dt) -- local trailers, _ = AutoDrive.getTrailersOf(vehicle, false) local trailers, _ = AutoDrive.getAllUnits(vehicle) local maxTriggerDistance = AutoDrive.getSetting("maxTriggerDistance") - for index, trailer in ipairs(trailers) do + for _, trailer in ipairs(trailers) do if trailer.getFillUnits ~= nil then local fillUnits = trailer:getFillUnits() local trailerX, _, trailerZ = getWorldTranslation(trailer.components[1].node) @@ -786,14 +795,14 @@ function AutoDrive.getTriggerAndTrailerPairs(vehicle, dt) if triggerX ~= nil then local distance = MathUtil.vector2Length(triggerX - trailerX, triggerZ - trailerZ) if distance <= maxTriggerDistance then - AutoDrive.debugPrint(vehicle, AutoDrive.DC_TRAILERINFO, "AutoDrive.getTriggerAndTrailerPairs distance %s", tostring(distance)) + AutoDrive.debugPrint(trailer, AutoDrive.DC_TRAILERINFO, "AutoDrive.getTriggerAndTrailerPairs distance %s", tostring(distance)) vehicle.ad.debugTrigger = trigger local allowedFillTypes = {vehicle.ad.stateModule:getFillType()} -- seeds, fertilizer, liquidfertilizer should always be loaded if in trigger available if #fillUnits > 1 then local fillTypeName = g_fillTypeManager:getFillTypeNameByIndex(vehicle.ad.stateModule:getFillType()) - AutoDrive.debugPrint(vehicle, AutoDrive.DC_TRAILERINFO, "AutoDrive.getTriggerAndTrailerPairs #fillUnits > 1 fillTypeName %s", tostring(fillTypeName)) + AutoDrive.debugPrint(trailer, AutoDrive.DC_TRAILERINFO, "AutoDrive.getTriggerAndTrailerPairs #fillUnits > 1 fillTypeName %s", tostring(fillTypeName)) if fillTypeName == 'SEEDS' or fillTypeName == 'FERTILIZER' or fillTypeName == 'LIQUIDFERTILIZER' then -- seeds, fertilizer, liquidfertilizer allowedFillTypes = {} @@ -806,7 +815,7 @@ function AutoDrive.getTriggerAndTrailerPairs(vehicle, dt) local fillLevels = {} if trigger.source ~= nil and trigger.source.getAllFillLevels ~= nil then fillLevels, _ = trigger.source:getAllFillLevels(vehicle:getOwnerFarmId()) - AutoDrive.debugPrint(vehicle, AutoDrive.DC_TRAILERINFO, "AutoDrive.getTriggerAndTrailerPairs fillLevels %s", tostring(fillLevels)) + AutoDrive.debugPrint(trailer, AutoDrive.DC_TRAILERINFO, "AutoDrive.getTriggerAndTrailerPairs fillLevels %s", tostring(fillLevels)) end local hasRequiredFillType = false @@ -816,15 +825,15 @@ function AutoDrive.getTriggerAndTrailerPairs(vehicle, dt) hasRequiredFillType = AutoDrive.fillTypesMatch(vehicle, trigger, trailer, allowedFillTypes, i) local isNotFilled = not AutoDrive.getIsFillUnitFull(trailer, i) - AutoDrive.debugPrint(vehicle, AutoDrive.DC_TRAILERINFO, "AutoDrive.getTriggerAndTrailerPairs hasRequiredFillType %s isNotFilled %s", tostring(hasRequiredFillType), tostring(isNotFilled)) + AutoDrive.debugPrint(trailer, AutoDrive.DC_TRAILERINFO, "AutoDrive.getTriggerAndTrailerPairs hasRequiredFillType %s isNotFilled %s", tostring(hasRequiredFillType), tostring(isNotFilled)) for _, allowedFillType in pairs(allowedFillTypes) do - if trailer:getFillUnitSupportsFillType(i, allowedFillType) then + if trailer:getFillUnitSupportsFillType(i, allowedFillType) and trailer:getFillUnitAllowsFillType(i, allowedFillType) then isFillAllowed = isFillAllowed or (fillLevels[allowedFillType] ~= nil) hasFill = hasFill or (fillLevels[allowedFillType] ~= nil and fillLevels[allowedFillType] > 0) end end - AutoDrive.debugPrint(vehicle, AutoDrive.DC_TRAILERINFO, "AutoDrive.getTriggerAndTrailerPairs isFillAllowed %s hasFill %s", tostring(isFillAllowed), tostring(hasFill)) + AutoDrive.debugPrint(trailer, AutoDrive.DC_TRAILERINFO, "AutoDrive.getTriggerAndTrailerPairs isFillAllowed %s hasFill %s", tostring(isFillAllowed), tostring(hasFill)) local trailerIsInRange = AutoDrive.trailerIsInTriggerList(trailer, trigger, i) if trailer.inRangeTimers == nil then @@ -836,12 +845,12 @@ function AutoDrive.getTriggerAndTrailerPairs(vehicle, dt) if trailer.inRangeTimers[i][trigger] == nil then trailer.inRangeTimers[i][trigger] = AutoDriveTON:new() end - AutoDrive.debugPrint(vehicle, AutoDrive.DC_TRAILERINFO, "AutoDrive.getTriggerAndTrailerPairs trailerIsInRange %s", tostring(trailerIsInRange)) + AutoDrive.debugPrint(trailer, AutoDrive.DC_TRAILERINFO, "AutoDrive.getTriggerAndTrailerPairs trailerIsInRange %s", tostring(trailerIsInRange)) local timerDone = trailer.inRangeTimers[i][trigger]:timer(trailerIsInRange, 200, dt) -- vehicle.ad.stateModule:getFieldSpeedLimit()*100 if timerDone and hasRequiredFillType and isNotFilled and isFillAllowed then - AutoDrive.debugPrint(vehicle, AutoDrive.DC_TRAILERINFO, "AutoDrive.getTriggerAndTrailerPairs timerDone %s", tostring(timerDone)) + AutoDrive.debugPrint(trailer, AutoDrive.DC_TRAILERINFO, "AutoDrive.getTriggerAndTrailerPairs timerDone %s trigger %s fillUnitIndex %s", tostring(timerDone), tostring(trigger), tostring(i)) local pair = {trailer = trailer, trigger = trigger, fillUnitIndex = i, hasFill = hasFill} table.insert(trailerTriggerPairs, pair) end @@ -972,3 +981,113 @@ function AutoDrive.isBaleUnloading(trailer) end end end + +-- return list of fillTypes which are supported to be unloaded, additional sowing, sprayer, saltSpreader +function AutoDrive.getValidSupportedFillTypes(vehicle, excludedVehicles) + if vehicle == nil then + return {} + end + local supportedFillTypes = {} + local function getsupportedFillTypes(object, fillUnitIndex) + if object and fillUnitIndex and fillUnitIndex > 0 then + if object.getFillUnitSupportedFillTypes ~= nil then + for fillType, supported in pairs(object:getFillUnitSupportedFillTypes(fillUnitIndex)) do + if supported and not table.contains(supportedFillTypes, fillType) then + table.insert(supportedFillTypes, fillType) + end + end + end + end + end + -- dischargeable Units + local dischargeableUnits = AutoDrive.getAllDischargeableUnits(vehicle, true) + if dischargeableUnits and #dischargeableUnits > 0 then + for i = 1, #dischargeableUnits do + local dischargeableUnit = dischargeableUnits[i] + if dischargeableUnit and dischargeableUnit.object and dischargeableUnit.fillUnitIndex and (excludedVehicles == nil or not table.contains(excludedVehicles, dischargeableUnit.object)) then + getsupportedFillTypes(dischargeableUnit.object, dischargeableUnit.fillUnitIndex) + end + end + end + -- sowing / fertilizing other tools + local trailers, _ = AutoDrive.getAllUnits(vehicle) + if trailers then + for _, trailer in pairs(trailers) do + if trailer.getFillUnits and (excludedVehicles == nil or not table.contains(excludedVehicles, trailer)) then + for fillUnitIndex, _ in pairs(trailer:getFillUnits()) do + + if trailer.spec_sowingMachine and trailer.getSowingMachineFillUnitIndex and trailer:getSowingMachineFillUnitIndex() > 0 then + if trailer:getSowingMachineFillUnitIndex() == fillUnitIndex then + getsupportedFillTypes(trailer, fillUnitIndex) + end + end + if trailer.spec_sprayer and trailer.getSprayerFillUnitIndex and trailer:getSprayerFillUnitIndex() > 0 then + if trailer:getSprayerFillUnitIndex() == fillUnitIndex then + getsupportedFillTypes(trailer, fillUnitIndex) + end + end + if trailer.spec_saltSpreader and trailer.spec_saltSpreader.fillUnitIndex and trailer.spec_saltSpreader.fillUnitIndex > 0 then + if trailer.spec_saltSpreader.fillUnitIndex == fillUnitIndex then + getsupportedFillTypes(trailer, fillUnitIndex) + end + end + end + end + end + end + return supportedFillTypes +end + +function AutoDrive.setValidSupportedFillType(vehicle, excludedImplementIndex) + if vehicle == nil then + return + end + + local ret = false + local currentFillType = nil + local excludedVehicles = nil + -- try to find AL fillType + local trailers, _ = AutoDrive.getAllUnits(vehicle) + + -- get all vehicles attached to the excludedImplementIndex + if excludedImplementIndex and vehicle.getAttachedImplements ~= nil then + local attachedImplements = vehicle:getAttachedImplements() + if attachedImplements and table.count(attachedImplements) > 0 then + local excludedImplement = attachedImplements[excludedImplementIndex] + if excludedImplement and excludedImplement.object then + excludedVehicles = AutoDrive.getTrailersOfImplement(vehicle, excludedImplement.object) + end + end + end + + for _, trailer in ipairs(trailers) do + + if AutoDrive:hasAL(trailer) and (excludedVehicles == nil or not table.contains(excludedVehicles, trailer)) then + currentFillType = AutoDrive:getALCurrentFillType(trailer) + if currentFillType ~= nil then + -- first found is sufficient + ret = true + vehicle.ad.stateModule:setFillType(currentFillType) + break + end + end + end + + -- no AL fillType found - continue with fillUnits + if currentFillType == nil then + local supportedFillTypes = AutoDrive.getValidSupportedFillTypes(vehicle, excludedVehicles) + + local storedSelectedFillType = vehicle.ad.stateModule:getFillType() + if supportedFillTypes and #supportedFillTypes > 0 then + if not table.contains(supportedFillTypes, storedSelectedFillType) then + -- HUD FillType is different, so set the first supported + ret = true + vehicle.ad.stateModule:setFillType(supportedFillTypes[1]) + end + else + ret = true + vehicle.ad.stateModule:setFillType(FillType.UNKNOWN) + end + end + return ret +end \ No newline at end of file diff --git a/scripts/Utils/UtilFuncs.lua b/scripts/Utils/UtilFuncs.lua index a5a4375f..ec6bce89 100644 --- a/scripts/Utils/UtilFuncs.lua +++ b/scripts/Utils/UtilFuncs.lua @@ -897,6 +897,7 @@ function AutoDrive.checkIsOnField_notFS22(startWorldX, worldY, startWorldZ) end end +--[[ Sprayer.registerOverwrittenFunctions = Utils.appendedFunction( Sprayer.registerOverwrittenFunctions, @@ -916,6 +917,7 @@ Sprayer.registerOverwrittenFunctions = ) end ) +]] -- LoadTrigger doesn't allow filling non controlled tools function AutoDrive:getIsActivatable(superFunc, objectToFill) @@ -973,42 +975,90 @@ function AutoDrive:onActivateObject(superFunc, vehicle) end function AutoDrive:onFillTypeSelection(fillType) - AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection start... fillType %s self.validFillableObject %s self.currentFillableObject %s self.isLoading %s", tostring(fillType), tostring(self.validFillableObject), tostring(self.currentFillableObject), tostring(self.isLoading)) + AutoDrive.debugPrint(self.validFillableObject, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection start... #self.fillableObjects %s fillType %s self.validFillableObject %s self.currentFillableObject %s self.isLoading %s", tostring(table.count(self.fillableObjects)), tostring(fillType), tostring(self.validFillableObject), tostring(self.currentFillableObject), tostring(self.isLoading)) + + -- fillUnit for wrong fillType is active, so disable loading and check again + if fillType ~= nil and fillType ~= FillType.UNKNOWN then + if self.validFillableObject and self.validFillableFillUnitIndex then + if self.validFillableObject.getFillUnitSupportsFillType and not self.validFillableObject:getFillUnitSupportsFillType(self.validFillableFillUnitIndex, fillType) then + AutoDrive.debugPrint(self.validFillableObject, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection not getFillUnitSupportsFillType -> isLoading = false") + self.isLoading = false + end + if self.validFillableObject.getFillUnitAllowsFillType and not self.validFillableObject:getFillUnitAllowsFillType(self.validFillableFillUnitIndex, fillType) then + AutoDrive.debugPrint(self.validFillableObject, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection not getFillUnitAllowsFillType ") + self.isLoading = false + end + end + end + if not self.isLoading then + AutoDrive.debugPrint(self.validFillableObject, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection not self.isLoading") if fillType ~= nil and fillType ~= FillType.UNKNOWN then - AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection self.currentFillableObject == nil") for _, fillableObject in pairs(self.fillableObjects) do --copied from gdn getIsActivatable to get a valid Fillable Object even without entering vehicle (needed for refuel first time) - - - local fillFreeCapacity = 0 - if fillableObject.object.getFillUnitFreeCapacity ~= nil then - fillFreeCapacity = fillableObject.object:getFillUnitFreeCapacity(fillableObject.fillUnitIndex) - AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection fillFreeCapacity %s", tostring(fillFreeCapacity)) - end - - if fillFreeCapacity > 0 and fillableObject.object:getFillUnitSupportsToolType(fillableObject.fillUnitIndex, ToolType.TRIGGER) then - AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection getFillUnitSupportsToolType") - self.currentFillableObject = fillableObject.object - self.currentFillableFillUnitIndex = fillableObject.fillUnitIndex - break + AutoDrive.debugPrint(fillableObject.object, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection fillableObject.object fillableObject.fillUnitIndex %s", tostring(fillableObject.fillUnitIndex)) + + if fillableObject.object.getFillUnitSupportsToolType and fillableObject.object:getFillUnitSupportsToolType(fillableObject.fillUnitIndex, ToolType.TRIGGER) then + AutoDrive.debugPrint(fillableObject.object, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection getFillUnitSupportsToolType") + if fillableObject.object.getFillUnitSupportsFillType and fillableObject.object:getFillUnitSupportsFillType(fillableObject.fillUnitIndex, fillType) then + AutoDrive.debugPrint(fillableObject.object, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection getFillUnitSupportsFillType") + if fillableObject.object.getFillUnitAllowsFillType and fillableObject.object:getFillUnitAllowsFillType(fillableObject.fillUnitIndex, fillType) then + AutoDrive.debugPrint(fillableObject.object, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection getFillUnitAllowsFillType") + if fillableObject.object.getFillUnitFreeCapacity and fillableObject.object:getFillUnitFreeCapacity(fillableObject.fillUnitIndex) > 0 then + AutoDrive.debugPrint(fillableObject.object, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection setIsLoading self.selectedFillType %s -> fillType %s", tostring(self.selectedFillType), tostring(fillType)) + self:setIsLoading(true, fillableObject.object, fillableObject.fillUnitIndex, fillType) + break + end + end + end end end - local currentFillableObject = self.currentFillableObject - local fillUnitIndex = self.currentFillableFillUnitIndex - AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection currentFillableObject %s", tostring(currentFillableObject)) - if currentFillableObject ~= nil and fillUnitIndex ~= nil then - AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection setIsLoading") - self:setIsLoading(true, currentFillableObject, fillUnitIndex, fillType) - end - if currentFillableObject ~= nil and fillUnitIndex == nil and AutoDrive.adErrorFillTypeSelection == nil then + if self.currentFillableObject ~= nil and self.fillUnitIndex == nil and AutoDrive.adErrorFillTypeSelection == nil then -- log an invalid load trigger AutoDrive.adErrorFillTypeSelection = true - local x, y, z = getWorldTranslation(currentFillableObject) - Logging.info("[AD] Info: invalid load trigger (fillUnitIndex == nil) found at position: %s , %s", tostring(x), tostring(z)) + local rootVehicle = self.currentFillableObject.rootVehicle + local name = rootVehicle and rootVehicle.getName and rootVehicle:getName() or "unknown vehicle" + Logging.info("[AD] Info: invalid load trigger (fillUnitIndex == nil) for vehicle '%s'", tostring(name)) + if rootVehicle then + local x, y, z = getWorldTranslation(rootVehicle) + Logging.info("[AD] Info: invalid load trigger (fillUnitIndex == nil) vehicle position: %s , %s", tostring(x), tostring(z)) + end + end + AutoDrive.debugPrint(self.validFillableObject, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection self.isLoading %s", tostring(self.isLoading)) + end + end + + if not self.isLoading then + AutoDrive.debugPrint(self.validFillableObject, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection not self.isLoading") + if fillType ~= nil and fillType ~= FillType.UNKNOWN then + for _, fillableObject in pairs(self.fillableObjects) do + + local spec = fillableObject.object.spec_motorized + if spec ~= nil and spec.consumersByFillTypeName ~= nil then + + for _, consumer in pairs(spec.consumersByFillTypeName) do + local fillUnitIndex = consumer.fillUnitIndex + AutoDrive.debugPrint(fillableObject.object, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection fillUnitIndex %s", tostring(fillUnitIndex)) + if fillableObject.object.getFillUnitSupportsToolType and fillableObject.object:getFillUnitSupportsToolType(fillUnitIndex, ToolType.TRIGGER) then + AutoDrive.debugPrint(fillableObject.object, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection getFillUnitSupportsToolType") + if fillableObject.object.getFillUnitSupportsFillType and fillableObject.object:getFillUnitSupportsFillType(fillUnitIndex, fillType) then + AutoDrive.debugPrint(fillableObject.object, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection getFillUnitSupportsFillType") + if fillableObject.object.getFillUnitAllowsFillType and fillableObject.object:getFillUnitAllowsFillType(fillUnitIndex, fillType) then + AutoDrive.debugPrint(fillableObject.object, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection getFillUnitAllowsFillType") + if fillableObject.object.getFillUnitFreeCapacity and fillableObject.object:getFillUnitFreeCapacity(fillUnitIndex) > 0 then + AutoDrive.debugPrint(fillableObject.object, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection setIsLoading self.selectedFillType %s -> fillType %s", tostring(self.selectedFillType), tostring(fillType)) + self:setIsLoading(true, fillableObject.object, fillUnitIndex, fillType) + break + end + end + end + end + end + end end - AutoDrive.debugPrint(self.vehicle, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection self.isLoading %s", tostring(self.isLoading)) + AutoDrive.debugPrint(self.validFillableObject, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection self.isLoading %s", tostring(self.isLoading)) end end + AutoDrive.debugPrint(nil, AutoDrive.DC_VEHICLEINFO, "AutoDrive:onFillTypeSelection end") end function AutoDrive.driveInDirection(self, dt, steeringAngleLimit, acceleration, slowAcceleration, slowAngleLimit, allowedToDrive, moveForwards, lx, lz, maxSpeed, slowDownFactor) diff --git a/scripts/XML.lua b/scripts/XML.lua index 5c70a16d..99969315 100644 --- a/scripts/XML.lua +++ b/scripts/XML.lua @@ -91,6 +91,7 @@ function AutoDrive.readFromXML(xmlFile) for settingName, setting in pairs(AutoDrive.settings) do if not setting.isVehicleSpecific then + -- also read user specific settings for backward compatibility local value = getXMLFloat(xmlFile, "AutoDrive." .. settingName) if value ~= nil then AutoDrive.settings[settingName].current = value @@ -282,14 +283,14 @@ function AutoDrive.saveToXML(xmlFile) setXMLString(xmlFile, "AutoDrive.version", AutoDrive.version) setXMLString(xmlFile, "AutoDrive.MapName", AutoDrive.loadedMap) - setXMLFloat(xmlFile, "AutoDrive.HudX", AutoDrive.HudX) - setXMLFloat(xmlFile, "AutoDrive.HudY", AutoDrive.HudY) - setXMLBool(xmlFile, "AutoDrive.HudShow", AutoDrive.Hud.showHud) + -- setXMLFloat(xmlFile, "AutoDrive.HudX", AutoDrive.HudX) + -- setXMLFloat(xmlFile, "AutoDrive.HudY", AutoDrive.HudY) + -- setXMLBool(xmlFile, "AutoDrive.HudShow", AutoDrive.Hud.showHud) setXMLInt(xmlFile, "AutoDrive.currentDebugChannelMask", AutoDrive.currentDebugChannelMask) for settingName, setting in pairs(AutoDrive.settings) do - if not setting.isVehicleSpecific then + if not setting.isVehicleSpecific and not setting.isUserSpecific then setXMLFloat(xmlFile, "AutoDrive." .. settingName, AutoDrive.settings[settingName].current) end if setting.userDefault ~= nil then diff --git a/translations/translation_br.xml b/translations/translation_br.xml index 9d01b955..da206441 100644 --- a/translations/translation_br.xml +++ b/translations/translation_br.xml @@ -68,7 +68,7 @@ - + @@ -168,6 +168,8 @@ + + @@ -288,6 +290,8 @@ + + diff --git a/translations/translation_cs.xml b/translations/translation_cs.xml index aa40a11e..df26f7d6 100644 --- a/translations/translation_cs.xml +++ b/translations/translation_cs.xml @@ -11,8 +11,8 @@ - - + + @@ -164,13 +164,15 @@ - - - - - - - + + + + + + + + + @@ -291,6 +293,7 @@ + diff --git a/translations/translation_cz.xml b/translations/translation_cz.xml index 41eaecbb..bbecbd9f 100644 --- a/translations/translation_cz.xml +++ b/translations/translation_cz.xml @@ -68,7 +68,7 @@ - + @@ -168,6 +168,8 @@ + + @@ -290,6 +292,8 @@ + + diff --git a/translations/translation_de.xml b/translations/translation_de.xml index 581cd503..1a0770de 100644 --- a/translations/translation_de.xml +++ b/translations/translation_de.xml @@ -3,6 +3,12 @@ Balu + + + + + + @@ -54,8 +60,8 @@ - - + + @@ -70,7 +76,7 @@ - + @@ -168,6 +174,8 @@ + + @@ -228,8 +236,8 @@ - - + + @@ -290,6 +298,8 @@ + + diff --git a/translations/translation_en.xml b/translations/translation_en.xml index be697481..551fc1c0 100644 --- a/translations/translation_en.xml +++ b/translations/translation_en.xml @@ -70,7 +70,7 @@ - + @@ -168,6 +168,8 @@ + + @@ -228,8 +230,8 @@ - - + + @@ -289,6 +291,8 @@ + + diff --git a/translations/translation_es.xml b/translations/translation_es.xml index 93a55a95..429d7474 100644 --- a/translations/translation_es.xml +++ b/translations/translation_es.xml @@ -68,7 +68,7 @@ - + @@ -166,6 +166,8 @@ + + @@ -274,6 +276,7 @@ + @@ -288,6 +291,8 @@ + + diff --git a/translations/translation_fr.xml b/translations/translation_fr.xml index c5bd4096..24fb6edb 100644 --- a/translations/translation_fr.xml +++ b/translations/translation_fr.xml @@ -168,7 +168,11 @@ - + + + + + @@ -289,6 +293,12 @@ + + + + + + diff --git a/translations/translation_hu.xml b/translations/translation_hu.xml index 3068f63c..5b4188f1 100644 --- a/translations/translation_hu.xml +++ b/translations/translation_hu.xml @@ -68,7 +68,7 @@ - + @@ -166,6 +166,8 @@ + + @@ -284,6 +286,8 @@ + + diff --git a/translations/translation_it.xml b/translations/translation_it.xml index d587e1d0..659c29f8 100644 --- a/translations/translation_it.xml +++ b/translations/translation_it.xml @@ -50,7 +50,7 @@ - + @@ -68,9 +68,9 @@ - + - + @@ -164,10 +164,12 @@ - - - - + + + + + + @@ -212,7 +214,7 @@ - + @@ -276,6 +278,7 @@ + @@ -290,6 +293,8 @@ + + diff --git a/translations/translation_nl.xml b/translations/translation_nl.xml index 17425dda..1b4f8a26 100644 --- a/translations/translation_nl.xml +++ b/translations/translation_nl.xml @@ -70,7 +70,7 @@ - + @@ -170,6 +170,8 @@ + + @@ -292,6 +294,8 @@ + + diff --git a/translations/translation_pl.xml b/translations/translation_pl.xml index 3417e65f..8fb80a5c 100644 --- a/translations/translation_pl.xml +++ b/translations/translation_pl.xml @@ -71,7 +71,7 @@ - + @@ -169,6 +169,8 @@ + + @@ -291,6 +293,8 @@ + + diff --git a/translations/translation_pt.xml b/translations/translation_pt.xml index 015fa029..c9d0908e 100644 --- a/translations/translation_pt.xml +++ b/translations/translation_pt.xml @@ -68,7 +68,7 @@ - + @@ -168,6 +168,8 @@ + + @@ -290,6 +292,8 @@ + + diff --git a/translations/translation_ru.xml b/translations/translation_ru.xml index ea36c1b2..0b028a2b 100644 --- a/translations/translation_ru.xml +++ b/translations/translation_ru.xml @@ -69,7 +69,7 @@ - + @@ -169,6 +169,8 @@ + + @@ -292,6 +294,8 @@ + + diff --git a/translations/translation_tr.xml b/translations/translation_tr.xml index 48a06099..05d93714 100644 --- a/translations/translation_tr.xml +++ b/translations/translation_tr.xml @@ -68,7 +68,7 @@ - + @@ -166,6 +166,8 @@ + + @@ -288,6 +290,8 @@ + +