diff --git a/AIDriver.lua b/AIDriver.lua index b1fd3a498..6894aff99 100644 --- a/AIDriver.lua +++ b/AIDriver.lua @@ -183,8 +183,11 @@ function AIDriver:init(vehicle) self.settings:validateCurrentValues() end self:setHudContent() + ---@type TriggerHandler self.triggerHandler = TriggerHandler(self,self.vehicle,self:getSiloSelectedFillTypeSetting()) self.triggerHandler:enableFuelLoading() + ---@type TriggerSensor + self.triggerSensor = TriggerSensor(self,self.vehicle) end ---This function is called once on the first update tick, @@ -438,13 +441,13 @@ function AIDriver:update(dt) self:resetSpeed() self:updateLoadingText() self.triggerHandler:onUpdate(dt) + self.triggerSensor:onUpdate(dt) self:shouldDriverBeReleased() - - self:updateDistanceMovedSinceStart(dt) + self:updateDistanceMovedSinceStart() end ---Update moved distance since start. -function AIDriver:updateDistanceMovedSinceStart(dt) +function AIDriver:updateDistanceMovedSinceStart() self.movedDistance = self.movedDistance + self.vehicle.lastMovedDistance end @@ -512,14 +515,9 @@ function AIDriver:driveCourse(dt) if not self:hasTipTrigger() then self:setSpeed(self:getRecordedSpeed()) end - - local isInTrigger, isAugerWagonTrigger = self.triggerHandler:isInTrigger() --- if self:getIsInFilltrigger() or self:hasTipTrigger() then-- or isInTrigger then - if isInTrigger then + + if self.triggerHandler:isInTrigger() or self.triggerSensor:isNearTriggers() then self:setSpeed(self.vehicle.cp.speeds.approach) - if isAugerWagonTrigger then - self:setSpeed(self.APPROACH_AUGER_TRIGGER_SPEED) - end end self:slowDownForWaitPoints() @@ -1368,6 +1366,12 @@ function AIDriver:searchForTipTriggers() end end +function AIDriver:searchForLoadingFillingTriggers() + if self.ppc:getCurrentWaypointIx() > 2 and not self.ppc:reachedLastWaypoint() and not self.ppc:isReversing() then + self.triggerSensor:raycastLoadingFillingTriggers() + end +end + function AIDriver:onUnLoadCourse(allowedToDrive, dt) -- Unloading local takeOverSteering = false @@ -2303,5 +2307,11 @@ function AIDriver:isWorkingToolPositionReached(dt,positionIx) end function AIDriver:getWorkingToolPositionsSetting() - --- override + if self:hasSugarCaneTrailerToolPositions() then + return self.settings.sugarCaneTrailerToolPositions + end +end + +function AIDriver:hasSugarCaneTrailerToolPositions() + return self.settings.sugarCaneTrailerToolPositions:getHasSugarCaneTrailer() end \ No newline at end of file diff --git a/AIDriverUtil.lua b/AIDriverUtil.lua index 0e27d7695..a157959a9 100644 --- a/AIDriverUtil.lua +++ b/AIDriverUtil.lua @@ -399,4 +399,52 @@ function AIDriverUtil.getMixerWagonFillLevelForFillTypes(object,fillType) end end end -end \ No newline at end of file +end + +--- Is a sugarcane trailer attached ? +---@param vehicle table +function AIDriverUtil.hasSugarCaneTrailer(vehicle) + if vehicle.spec_shovel and vehicle.spec_trailer then + return true + end + for _, implement in pairs(AIDriverUtil.getAllAttachedImplements(vehicle)) do + local object = implement.object + if object.spec_shovel and object.spec_trailer then + return true + end + end +end + +--- Are there any trailer under the pipe ? +---@param pipe table +---@param shouldTrailerBeStandingStill boolean +function AIDriverUtil.isTrailerUnderPipe(pipe,shouldTrailerBeStandingStill) + if not pipe then return end + for trailer, value in pairs(pipe.objectsInTriggers) do + if value > 0 then + if shouldTrailerBeStandingStill then + local rootVehicle = trailer:getRootVehicle() + if rootVehicle then + if AIDriverUtil.isStopped(rootVehicle) then + return true + else + return false + end + end + end + return true + end + end + return false +end + +---Gets the total length of the vehicle and all it's implements. +function AIDriverUtil.getVehicleAndImplementsTotalLength(vehicle) + local totalLength = vehicle.sizeLength + for _, implement in pairs(AIDriverUtil.getAllAttachedImplements(vehicle)) do + if implement.object ~= nil then + totalLength = totalLength + implement.object.sizeLength + end + end + return totalLength +end \ No newline at end of file diff --git a/CombineAIDriver.lua b/CombineAIDriver.lua index 202e45c3d..e38c8d28d 100644 --- a/CombineAIDriver.lua +++ b/CombineAIDriver.lua @@ -105,6 +105,13 @@ function CombineAIDriver:init(vehicle) self.unloadAIDriverToRendezvous = CpTemporaryObject() end +function CombineAIDriver:postInit() + ---Refresh the Hud content here,as otherwise the moveable pipe is not + ---detected the first time after loading a savegame. + self:setHudContent() + UnloadableFieldworkAIDriver.postInit(self) +end + function CombineAIDriver:setUpPipe() if self.vehicle.spec_pipe then self.pipe = self.vehicle.spec_pipe @@ -212,7 +219,7 @@ end function CombineAIDriver:drive(dt) -- handle the pipe in any state - self:handlePipe() + self:handlePipe(dt) -- the rest is the same as the parent class UnloadableFieldworkAIDriver.drive(self, dt) end @@ -1085,20 +1092,23 @@ function CombineAIDriver:isChopper() return self.combine:getFillUnitCapacity(self.combine.fillUnitIndex) > 10000000 end -function CombineAIDriver:handlePipe() +function CombineAIDriver:handlePipe(dt) if self.pipe then if self:isChopper() then self:handleChopperPipe() else - self:handleCombinePipe() + self:handleCombinePipe(dt) end end end -function CombineAIDriver:handleCombinePipe() +function CombineAIDriver:handleCombinePipe(dt) if self:isFillableTrailerUnderPipe() or self:isAutoDriveWaitingForPipe() or (self:isWaitingForUnload() and self.vehicle.cp.settings.pipeAlwaysUnfold:is(true)) then self:openPipe() + if self.pipe and self.pipe.currentState == AIDriverUtil.PIPE_STATE_OPEN then + self:isWorkingToolPositionReached(dt,1) + end else --wait until the objects under the pipe are gone if self.pipe.numObjectsInTriggers <=0 then @@ -1765,3 +1775,8 @@ function CombineAIDriver:isProximitySlowDownEnabled(vehicle) return true end end + +function CombineAIDriver:getWorkingToolPositionsSetting() + local setting = self.settings.pipeToolPositions + return setting:getHasMoveablePipe() and setting:hasValidToolPositions() and setting +end \ No newline at end of file diff --git a/FieldSupplyAIDriver.lua b/FieldSupplyAIDriver.lua index d5fb73e80..a64630538 100644 --- a/FieldSupplyAIDriver.lua +++ b/FieldSupplyAIDriver.lua @@ -41,19 +41,26 @@ function FieldSupplyAIDriver:init(vehicle) self.supplyState = self.states.ON_REFILL_COURSE self.mode=courseplay.MODE_FIELD_SUPPLY self.debugChannel = courseplay.DBG_MODE_8 - self:setHudContent() +end + +function FieldSupplyAIDriver:postInit() + ---Refresh the Hud content here,as otherwise the moveable pipe is not + ---detected the first time after loading a savegame. + self:setHudContent() + FillableFieldworkAIDriver.postInit(self) end function FieldSupplyAIDriver:setHudContent() + self:findPipe() AIDriver.setHudContent(self) courseplay.hud:setFieldSupplyAIDriverContent(self.vehicle) end --this one is should be better derived!! function FieldSupplyAIDriver:start(startingPoint) self.refillState = self.states.REFILL_DONE + self.supplyState = self.states.ON_REFILL_COURSE AIDriver.start(self,startingPoint) self.state = self.states.ON_UNLOAD_OR_REFILL_COURSE - self:findPipe() --for Augerwagons end function FieldSupplyAIDriver:stop(msgReference) @@ -84,9 +91,18 @@ function FieldSupplyAIDriver:drive(dt) elseif self.supplyState == self.states.WAITING_FOR_GETTING_UNLOADED then self:holdWithFuelSave() self:updateInfoText() - if self.pipe then - self.pipe:setPipeState(AIDriverUtil.PIPE_STATE_OPEN) + if self.objectWithPipe then self.triggerHandler:enableFillTypeUnloadingAugerWagon() + ---TODO: Currently it's not possible to open the pipe after the mode 4 driver arrives, + --- as there is not trigger to detect it, while the pipe is closed. + + -- if AIDriverUtil.isTrailerUnderPipe(self.pipe,true) then + --- Open the pipe if there is a trailer under the pipe and standing still. + self.objectWithPipe:setPipeState(AIDriverUtil.PIPE_STATE_OPEN) + self:isWorkingToolPositionReached(dt,1) + -- else + -- self.objectWithPipe:setPipeState(AIDriverUtil.PIPE_STATE_CLOSED) + -- end else self.triggerHandler:enableFillTypeUnloading() end @@ -130,7 +146,7 @@ function FieldSupplyAIDriver:isFillLevelToContinueReached() return end --pipe still opening wait! - if self.pipe and not self.pipe:getIsPipeStateChangeAllowed(AIDriverUtil.PIPE_STATE_CLOSED) then + if self.objectWithPipe and not self.objectWithPipe:getIsPipeStateChangeAllowed(AIDriverUtil.PIPE_STATE_CLOSED) then return end local fillLevelInfo = {} @@ -154,15 +170,16 @@ function FieldSupplyAIDriver:needsFillTypeLoading() end function FieldSupplyAIDriver:findPipe() - local implementWithPipe = AIDriverUtil.getImplementWithSpecialization(self.vehicle, Pipe) + local implementWithPipe = AIDriverUtil.getImplementWithSpecialization(self.vehicle, Pipe) or self.vehicle.spec_pipe and self.vehicle if implementWithPipe then - self.pipe = implementWithPipe + self.objectWithPipe = implementWithPipe + self.pipe = implementWithPipe.spec_pipe end end function FieldSupplyAIDriver:closePipeIfNeeded(isInWaitPointRange) - if self.pipe and not self.isInWaitPointRange then - self.pipe:setPipeState(AIDriverUtil.PIPE_STATE_CLOSED) + if self.objectWithPipe and not self.isInWaitPointRange then + self.objectWithPipe:setPipeState(AIDriverUtil.PIPE_STATE_CLOSED) end end @@ -172,4 +189,9 @@ end function FieldSupplyAIDriver:getCanShowDriveOnButton() return AIDriver.getCanShowDriveOnButton(self) or self.refillState == self.states.WAITING_FOR_GETTING_UNLOADED +end + +function FieldSupplyAIDriver:getWorkingToolPositionsSetting() + local setting = self.settings.pipeToolPositions + return setting:getHasMoveablePipe() and setting:hasValidToolPositions() and setting end \ No newline at end of file diff --git a/FillableFieldworkAIDriver.lua b/FillableFieldworkAIDriver.lua index 0d1ae8760..26c9ed765 100644 --- a/FillableFieldworkAIDriver.lua +++ b/FillableFieldworkAIDriver.lua @@ -68,6 +68,7 @@ function FillableFieldworkAIDriver:driveUnloadOrRefill() else self:clearInfoText('NO_SELECTED_FILLTYPE') end + local isNearWaitPoint, waitPointIx = self.course:hasWaitPointWithinDistance(self.ppc:getRelevantWaypointIx(), 25) --this one is used to disable loading at the unloading stations, --might be better to disable the triggerID for loading @@ -91,6 +92,7 @@ function FillableFieldworkAIDriver:driveUnloadOrRefill() -- just drive normally self:setSpeed(self:getRecordedSpeed()) self:closePipeIfNeeded(isNearWaitPoint) + self:searchForLoadingFillingTriggers() end end diff --git a/GrainTransportAIDriver.lua b/GrainTransportAIDriver.lua index 6564c8fb4..1a17e6ff8 100644 --- a/GrainTransportAIDriver.lua +++ b/GrainTransportAIDriver.lua @@ -70,9 +70,9 @@ function GrainTransportAIDriver:drive(dt) local allowedToDrive = true if self:getSiloSelectedFillTypeSetting():isEmpty() then - courseplay:setInfoText(self.vehicle, "COURSEPLAY_MANUAL_LOADING") --checking FillLevels, while loading at StartPoint if self.readyToLoadManualAtStart then + courseplay:setInfoText(self.vehicle, "COURSEPLAY_MANUAL_LOADING") self:setInfoText('REACHED_OVERLOADING_POINT') self:checkFillUnits() if self.nextClosestExactFillRootNode then diff --git a/OverloaderAIDriver.lua b/OverloaderAIDriver.lua index 8ba3f7457..98d51a602 100644 --- a/OverloaderAIDriver.lua +++ b/OverloaderAIDriver.lua @@ -52,11 +52,7 @@ function OverloaderAIDriver:findPipeAndTrailer() if implementWithPipe then self.pipe = implementWithPipe.spec_pipe self.objectWithPipe = implementWithPipe - self.moveablePipe = implementWithPipe.spec_cylindered self:debug('Overloader found its pipe') - if self.moveablePipe then - self:debug('Overloader found moveable pipe') - end else self:debug('Overloader has no implement with pipe') end @@ -66,7 +62,7 @@ end function OverloaderAIDriver:setHudContent() CombineUnloadAIDriver.setHudContent(self) self:findPipeAndTrailer() - courseplay.hud:setOverloaderAIDriverContent(self.vehicle,self.moveablePipe) + courseplay.hud:setOverloaderAIDriverContent(self.vehicle) end function OverloaderAIDriver:start(startingPoint) @@ -79,23 +75,7 @@ function OverloaderAIDriver:start(startingPoint) end function OverloaderAIDriver:isTrailerUnderPipe(shouldTrailerBeStandingStill) - if not self.pipe then return end - for trailer, value in pairs(self.pipe.objectsInTriggers) do - if value > 0 then - if shouldTrailerBeStandingStill then - local rootVehicle = trailer:getRootVehicle() - if rootVehicle then - if rootVehicle:getLastSpeed(true) <1 then - return true - else - return false - end - end - end - return true - end - end - return false + return AIDriverUtil.isTrailerUnderPipe(self.pipe,shouldTrailerBeStandingStill) end function OverloaderAIDriver:driveUnloadCourse(dt) @@ -135,10 +115,10 @@ function OverloaderAIDriver:driveUnloadCourse(dt) AIDriver.drive(self, dt) end ---if we have augerPipeToolPositions, then wait until we have set them +--if we have pipeToolPositions, then wait until we have set them function OverloaderAIDriver:getWorkingToolPositionsSetting() - local setting = self.vehicle.cp.settings.augerPipeToolPositions - return self.moveablePipe and setting:hasValidToolPositions() and self.vehicle.cp.settings.augerPipeToolPositions + local setting = self.settings.pipeToolPositions + return setting:getHasMoveablePipe() and setting:hasValidToolPositions() and setting end function OverloaderAIDriver:isProximitySwerveEnabled(vehicle) diff --git a/TriggerHandler.lua b/TriggerHandler.lua index f71923f5a..373cf1be6 100644 --- a/TriggerHandler.lua +++ b/TriggerHandler.lua @@ -27,9 +27,7 @@ function TriggerHandler:init(driver,vehicle,siloSelectedFillTypeSetting) self.loadingState = StateModule(self,"debug", self.vehicle) self.loadingState:initStates(TriggerHandler.myLoadingStates) self.loadingState.state = self.loadingState.states.STOPPED - self.triggers = {} self.objectsInTrigger= {} - self.isInAugerWagonTrigger = false self.fillableObject = nil self.lastLoadedFillTypes = {} self.debugTicks = 10 @@ -55,7 +53,6 @@ end function TriggerHandler:onStart() self:changeLoadingState("NOTHING") self.lastDistanceToTrigger = nil - self.triggers = {} self.objectsInTrigger = {} self.lastLoadedFillTypes = {} end @@ -71,7 +68,12 @@ function TriggerHandler:onUpdate(dt) end if not self:isStopped() then if self.validFillTypeUnloading then - self:updateUnloadingTriggers() + self:updateUnloadingTriggers(dt) + end + if not self:isUnloading() then + if self.driver:hasSugarCaneTrailerToolPositions() then + self.driver:isWorkingToolPositionReached(dt,SugarCaneTrailerToolPositionsSetting.TRANSPORT_POSITION) + end end end --temp hack to reset driveNow @@ -211,9 +213,12 @@ function TriggerHandler:updateLoadingTriggers() end end -function TriggerHandler:updateUnloadingTriggers() +function TriggerHandler:updateUnloadingTriggers(dt) if self:isUnloading() then self:disableUnloadingIfEmpty() + if self.driver:hasSugarCaneTrailerToolPositions() then + self.driver:isWorkingToolPositionReached(dt,SugarCaneTrailerToolPositionsSetting.UNLOADING_POSITION) + end end end @@ -229,7 +234,7 @@ function TriggerHandler:disableUnloadingIfEmpty() if self.fillableObject then local fillUnitIndex = self.fillableObject.fillUnitIndex local object = self.fillableObject.object - if object:getFillUnitFillLevelPercentage(fillUnitIndex)*100 < 0.5 and object.spec_waterTrailer then + if object:getFillUnitFillLevelPercentage(fillUnitIndex)*100 < 0.5 and (object.spec_waterTrailer or self.driver:hasSugarCaneTrailerToolPositions()) then self:resetUnloadingState() end end @@ -385,9 +390,7 @@ function TriggerHandler:isInTrigger() if oldCpTrigger and oldCpTrigger.bunkerSilo ~= nil then return false end - local bool = self.validFillTypeLoading and (self.driver:getIsInFilltrigger() or next(self.triggers) ~=nil) or self.validFillTypeUnloading and self.driver:hasTipTrigger() --- local bool = next(self.triggers) ~=nil or next(self.objectsInTrigger) ~=nil - return bool, self.isInAugerWagonTrigger + return self.validFillTypeUnloading and self.driver:hasTipTrigger() end function TriggerHandler:isDriveNowActivated() @@ -934,12 +937,6 @@ end LoadTrigger.loadTriggerCallback = Utils.appendedFunction(LoadTrigger.loadTriggerCallback,TriggerHandler.loadTriggerCallback) function TriggerHandler.handleLoadTriggerCallback(self,triggerId, otherId, onEnter, onLeave, onStay, otherShapeId,rootVehicle,fillableObject) - local triggerHandler = rootVehicle.cp.driver.triggerHandler - if not onLeave and triggerHandler.triggers[self] == nil then - triggerHandler.triggers[self] = true - elseif onLeave and (self.courseplayersInTrigger[rootVehicle] == nil or next(self.courseplayersInTrigger[rootVehicle]) == nil) then - triggerHandler.triggers[self] = nil - end if onEnter then courseplay.debugVehicle(courseplay.DBG_LOAD_UNLOAD,fillableObject, 'LoadTrigger onEnter') if fillableObject.getFillUnitIndexFromNode ~= nil then @@ -955,7 +952,7 @@ function TriggerHandler.handleLoadTriggerCallback(self,triggerId, otherId, onEnt if fillableObject:getFillUnitSupportsFillType(foundFillUnitIndex, fillTypeIndex) then if fillableObject:getFillUnitAllowsFillType(foundFillUnitIndex, fillTypeIndex) and fillableObject.spec_cover then SpecializationUtil.raiseEvent(fillableObject, "onAddedFillUnitTrigger",fillTypeIndex,foundFillUnitIndex,1) - triggerHandler:debugSparse(fillableObject,"LoadTrigger: open Cover for loading") + courseplay.debugVehicle(courseplay.DBG_LOAD_UNLOAD,fillableObject,"LoadTrigger: open Cover for loading") end end end @@ -1009,11 +1006,6 @@ function TriggerHandler:fillTriggerCallback(superFunc, triggerId, otherId, onEnt if not triggerHandler.validFillTypeLoading then return superFunc(self,triggerId, otherId, onEnter, onLeave, onStay, otherShapeId) end - if not onLeave and triggerHandler.triggers[self] == nil then - triggerHandler.triggers[self] = true - elseif onLeave and (self.courseplayersInTrigger[rootVehicle] == nil or next(self.courseplayersInTrigger[rootVehicle]) == nil) then - triggerHandler.triggers[self] = nil - end if onEnter then courseplay.debugVehicle(courseplay.DBG_LOAD_UNLOAD,fillableObject, 'fillTrigger onEnter') end @@ -1038,14 +1030,6 @@ end --Augerwagons handling --Pipe callback used for augerwagons to open the cover on the fillableObject function TriggerHandler:unloadingTriggerCallback(superFunc,triggerId, otherId, onEnter, onLeave, onStay, otherShapeId) - if not self.objectsInTrigger then - self.objectsInTrigger = {} - end - if onEnter then - self.objectsInTrigger[otherId] = true - elseif onLeave then - self.objectsInTrigger[otherId] = nil - end local rootVehicle = self:getRootVehicle() if courseplay:isAIDriverActive(rootVehicle) and not rootVehicle.cp.driver.triggerHandler.validFillTypeUnloadingAugerWagon then return superFunc(self,triggerId, otherId, onEnter, onLeave, onStay, otherShapeId) @@ -1060,11 +1044,7 @@ function TriggerHandler:unloadingTriggerCallback(superFunc,triggerId, otherId, o if not objectTriggerHandler.validFillTypeLoading then return superFunc(self,triggerId, otherId, onEnter, onLeave, onStay, otherShapeId) end - if not onLeave and objectTriggerHandler.triggers[self] == nil then - objectTriggerHandler.triggers[self] = true - elseif onLeave and next(self.objectsInTrigger) == nil then - objectTriggerHandler.triggers[self] = nil - end + if object.getFillUnitIndexFromNode ~= nil and not onLeave then local fillUnitIndex = object:getFillUnitIndexFromNode(otherId) if fillUnitIndex ~= nil then @@ -1075,7 +1055,6 @@ function TriggerHandler:unloadingTriggerCallback(superFunc,triggerId, otherId, o if fillType and validFillUnitIndex then courseplay.debugVehicle(courseplay.DBG_LOAD_UNLOAD,object,"unloadingTriggerCallback open Cover for "..g_fillTypeManager:getFillTypeByIndex(fillType).title) SpecializationUtil.raiseEvent(object, "onAddedFillUnitTrigger",fillType,validFillUnitIndex,1) - objectTriggerHandler.isInAugerWagonTrigger = true end end end @@ -1083,7 +1062,6 @@ function TriggerHandler:unloadingTriggerCallback(superFunc,triggerId, otherId, o SpecializationUtil.raiseEvent(object, "onRemovedFillUnitTrigger",0) courseplay.debugVehicle(courseplay.DBG_LOAD_UNLOAD,object,"unloadingTriggerCallback close Cover") objectTriggerHandler:resetLoadingState() - objectTriggerHandler.isInAugerWagonTrigger = false end end return superFunc(self,triggerId, otherId, onEnter, onLeave, onStay, otherShapeId) @@ -1168,38 +1146,57 @@ end Dischargeable.updateRaycast = Utils.overwrittenFunction(Dischargeable.updateRaycast, TriggerHandler.updateRaycast) --check if we can unload and then wait and also set triggerSpeed for unloadingTriggers for now until raycast is fixed -function TriggerHandler:onUpdateDischargeable(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) - local rootVehicle = self:getRootVehicle() - local spec = self.spec_dischargeable - if courseplay:isAIDriverActive(rootVehicle) and spec and spec.currentDischargeState == Dischargeable.DISCHARGE_STATE_OFF then - local triggerHandler = rootVehicle.cp.driver.triggerHandler +function TriggerHandler.onUpdateDischargeable(object,dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) + local rootVehicle = object:getRootVehicle() + local spec = object.spec_dischargeable + local driver = rootVehicle.cp.driver + if courseplay:isAIDriverActive(rootVehicle) and (spec.currentDischargeState == Dischargeable.DISCHARGE_STATE_OFF or driver:hasSugarCaneTrailerToolPositions())then + local triggerHandler = driver.triggerHandler local currentDischargeNode = spec.currentDischargeNode if triggerHandler:isStopped() or not triggerHandler.validFillTypeUnloading or not currentDischargeNode then return end - if spec:getCanDischargeToObject(currentDischargeNode) and not triggerHandler:isDriveNowActivated() then - triggerHandler:setUnloadingState(self,currentDischargeNode.fillUnitIndex,spec:getDischargeFillType(currentDischargeNode)) - triggerHandler:debugSparse(self,"getCanDischargeToObject") - spec:setDischargeState(Dischargeable.DISCHARGE_STATE_OBJECT) + if driver:hasSugarCaneTrailerToolPositions() then + triggerHandler:handleSugarCaneTrailerUnloading(object,driver,triggerHandler) + else + if spec:getCanDischargeToObject(currentDischargeNode) and not triggerHandler:isDriveNowActivated() then + triggerHandler:setUnloadingState(object,currentDischargeNode.fillUnitIndex,spec:getDischargeFillType(currentDischargeNode)) + triggerHandler:debugSparse(object,"getCanDischargeToObject") + spec:setDischargeState(Dischargeable.DISCHARGE_STATE_OBJECT) + end end if currentDischargeNode.dischargeFailedReason and currentDischargeNode.dischargeFailedReason == Dischargeable.DISCHARGE_REASON_NO_FREE_CAPACITY then g_globalInfoTextHandler:setInfoText(rootVehicle, 'FARM_SILO_IS_FULL') -- not working for now, might have to double check end if currentDischargeNode.dischargeObject then - if triggerHandler.objectsInTrigger[self] == nil then - triggerHandler.objectsInTrigger[self] = true + if triggerHandler.objectsInTrigger[object] == nil then + triggerHandler.objectsInTrigger[object] = true end else - triggerHandler.objectsInTrigger[self] = nil + triggerHandler.objectsInTrigger[object] = nil end if spec.currentDischargeState == Dischargeable.DISCHARGE_STATE_OFF and rootVehicle.cp.driver:hasTipTrigger() then courseplay:setInfoText(rootVehicle,"COURSEPLAY_TIPTRIGGER_REACHED") - triggerHandler:debugSparse(self,"COURSEPLAY_TIPTRIGGER_REACHED") + triggerHandler:debugSparse(object,"COURSEPLAY_TIPTRIGGER_REACHED") end end end Dischargeable.onUpdate = Utils.appendedFunction(Dischargeable.onUpdate, TriggerHandler.onUpdateDischargeable) +function TriggerHandler:handleSugarCaneTrailerUnloading(object,driver,triggerHandler) + local spec = object.spec_dischargeable + local currentDischargeNode = spec.currentDischargeNode + if currentDischargeNode.dischargeObject and object:getFillUnitFillLevelPercentage(currentDischargeNode.fillUnitIndex)*100 > 0.5 then + if not driver:areWorkingToolPositionsValid() then + triggerHandler:resetUnloadingState() + driver:hold() + return + end + triggerHandler:setUnloadingState(object,currentDischargeNode.fillUnitIndex,spec:getDischargeFillType(currentDischargeNode)) + triggerHandler:debugSparse(object,"Discharging with sugar cane trailer.") + end +end + --check if we have any fillTrigger nearby and handle them function TriggerHandler:onUpdateTickFillUnit(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) local rootVehicle = self:getRootVehicle() diff --git a/TriggerSensor.lua b/TriggerSensor.lua new file mode 100644 index 000000000..f9bc6d51e --- /dev/null +++ b/TriggerSensor.lua @@ -0,0 +1,146 @@ + +---@class TriggerSensor +TriggerSensor = CpObject() +TriggerSensor.TRIGGER_RAYCAST_DISTANCE = 10 + +---@param driver AIDriver +---@param vehicle table +function TriggerSensor:init(driver,vehicle) + self.driver = driver + self.vehicle = vehicle + self.totalVehicleLength = AIDriverUtil.getVehicleAndImplementsTotalLength(self.vehicle) + self.triggers = {} + self.numTriggers = 0 + self.debugChannel = courseplay.DBG_TRIGGERS +end + +function TriggerSensor:debug(...) + courseplay.debugVehicle(self.debugChannel,self.vehicle,...) +end + +function TriggerSensor:debugEnabled() + return courseplay.debugChannels[self.debugChannel] +end + +function TriggerSensor:onDraw() + if not self:debugEnabled() then + return + end + local i = 0 + local y = 0.5 + for trigger,data in pairs(self.triggers) do + y = self:renderText(y,0.4,"%d: Trigger(%s), dist: %.2f",i,tostring(getName(data.triggerID)),data.distanceUntilFound) + i = i+1 + end + y = self:renderText(y,0.4,"Current triggers: %d",self.numTriggers) + y = self:renderText(y,0.4,"Total vehicle length: %.2f",self.totalVehicleLength) + y = self:renderText(y,0.4,"Distance Traveled: %.2f",self.driver:getDistanceMovedSinceStart() or 0) +end + +function TriggerSensor:renderText(y,xOffset,text,...) + renderText(xOffset and 0.3+xOffset or 0.3,y,0.02,string.format(text,...)) + return y-0.02 +end + +function TriggerSensor:onUpdate(dt) + self:updateTriggers() +end + +function TriggerSensor:updateTriggers() + for trigger,data in pairs(self.triggers) do + if self:hasTriggerPassed(data.distanceUntilFound) then + self.triggers[trigger] = nil + self.numTriggers = math.max(self.numTriggers-1,0) + self:debug("Removed trigger(%s)",tostring(getName(data.triggerID))) + end + end +end + +function TriggerSensor:hasTriggerPassed(distanceUntilFound) + return (distanceUntilFound + self.TRIGGER_RAYCAST_DISTANCE + self.totalVehicleLength) < self.driver:getDistanceMovedSinceStart() +end + +---@param trigger table +---@param triggerID number +function TriggerSensor:addTrigger(trigger,triggerID) + self.triggers[trigger] = { + triggerID = triggerID, + distanceUntilFound = self.driver:getDistanceMovedSinceStart() + } + self:debug("Added trigger(%s)",tostring(getName(triggerID))) + self.numTriggers = self.numTriggers + 1 +end + +function TriggerSensor:isNearTriggers() + return self.numTriggers>0 +end + + +--- Loading/ filling trigger callback +---@param transformId number +---@param x number +---@param y number +---@param z number +---@param distance number +function TriggerSensor:loadingFillingTriggerCallback(transformId, x, y, z, distance) + if CpManager.confirmedNoneSpecialTriggers[transformId] then + return true; + end; + local objectName = tostring(getName(transformId)); + if self:debugEnabled() then + cpDebug:drawPoint(x, y, z, 1, 1, 0); + end; + + local loadingTriggers = Triggers.getLoadingTriggers() + local fillingTriggers = Triggers.getFillTriggers() + local trigger = loadingTriggers[transformId] or fillingTriggers[transformId] + if trigger and not self.triggers[trigger] then + self:addTrigger(trigger, transformId) + return false + end + + CpManager.confirmedNoneSpecialTriggers[transformId] = true + CpManager.confirmedNoneSpecialTriggersCounter = CpManager.confirmedNoneSpecialTriggersCounter + 1 + self:debug("added %d (%s) to trigger blacklist -> total = %d",transformId,objectName, CpManager.confirmedNoneSpecialTriggersCounter) + return true +end + +function TriggerSensor:raycastLoadingFillingTriggers() + local raycastDistance = self.TRIGGER_RAYCAST_DISTANCE + local dx,dz = self.driver.course:getDirectionToWPInDistance(self.driver.ppc:getCurrentWaypointIx(),self.vehicle,raycastDistance) + local x,y,z,nx,ny,nz = courseplay:getTipTriggerRaycastDirection(self.vehicle,dx,dz,raycastDistance) + + self:raycast(x,y,z, nx,ny,nz, "loadingFillingTriggerCallback", raycastDistance) + + local directionNode = self.driver:getDirectionNode() + local ny = 0 + + -- raycast start point in front of vehicle + local x1,_,z1 = localToWorld(directionNode,2,0,0) + local x2,_,z2 = localToWorld(directionNode,-2,0,0) + + local dx1,dz1 = x1+nx*raycastDistance,z1+nz*raycastDistance + local dx2,dz2 = x2+nx*raycastDistance,z2+nz*raycastDistance + + local nx1,nz1 = MathUtil.vector2Normalize(dx2 - x1, dz2 - z1) + local nx2,nz2 = MathUtil.vector2Normalize(dx1 - x2, dz1 - z2) + + --create a hammerhead raycast to get small triggers + nx, ny, nz = localDirectionToWorld(directionNode, 1, 0, 0) + self:raycast(dx2, y+2, dz2, nx, ny, nz,"loadingFillingTriggerCallback", 4) +end + +---@param x number +---@param y number +---@param z number +---@param nx number +---@param ny number +---@param nz number +---@param callback function +---@param raycastDistance number +function TriggerSensor:raycast(x,y,z, nx,ny,nz, callback, raycastDistance) + if self:debugEnabled() then + cpDebug:drawLine(x,y,z, 1,0,0, x+(nx*raycastDistance),y+(ny*raycastDistance),z+(nz*raycastDistance)) + end + raycastAll(x,y,z, nx,ny,nz, callback, raycastDistance, self) +end \ No newline at end of file diff --git a/base.lua b/base.lua index e47f24c26..f1347054c 100644 --- a/base.lua +++ b/base.lua @@ -175,7 +175,6 @@ function courseplay:onLoad(savegame) self.cp.hasRunRaycastThisLoop = {}; self.findVehicleHeights = courseplay.findVehicleHeights; - self.cp.fillTriggers = {} if self.maxRotation then self.cp.steeringAngle = math.deg(self.maxRotation); @@ -327,6 +326,7 @@ function courseplay:onDraw() courseplay:showTemporaryMarkers(self) if self.cp.driver then self.cp.driver.triggerHandler:onDraw() + self.cp.driver.triggerSensor:onDraw() end local isDriving = self:getIsCourseplayDriving(); @@ -1176,14 +1176,7 @@ function courseplay.onStartCpAIDriver(vehicle,helperIndex,noEventSend, startedFa end --- Add new helpers, if we run out of giants helpers available. --- TODO: Figure out if this needs tweaks for multiplayer. - while(spec.currentHelper == nil) do - --- Default helpers are index 1-10 - local index = math.random(1,10) - local source = g_helperManager:getHelperByIndex(index) - local name = "C"..tostring(math.random(1,100)) - - spec.currentHelper = g_helperManager:addHelper(name, name, source.filename) - end + spec.currentHelper = courseplay.addNewHelper(spec.currentHelper) g_helperManager:useHelper(spec.currentHelper) ---Make sure the farmId is never: 0 == spectator farm id, @@ -1250,6 +1243,18 @@ function courseplay.onStartCpAIDriver(vehicle,helperIndex,noEventSend, startedFa end end +function courseplay.addNewHelper(currentHelper) + while(currentHelper == nil and currentHelper.index~=nil) do + --- Default helpers are index 1-10 + local index = math.random(1,10) + local source = g_helperManager:getHelperByIndex(index) + local name = "C"..tostring(math.random(1,100)) + + currentHelper = g_helperManager:addHelper(name, name, source.filename) + end + return currentHelper +end + --the same code as giants AIVehicle:stopAIVehicle(helperIndex, noEventSend, startedFarmId), but customized for cp --All the code that has to be run on Server and Client from the "start_stop" file has to get in here diff --git a/courseplay.lua b/courseplay.lua index 69c45957a..132f52222 100644 --- a/courseplay.lua +++ b/courseplay.lua @@ -85,6 +85,7 @@ local function initialize() 'Waypoint', 'StateModule', 'TriggerHandler', + 'TriggerSensor', 'BaleToCollect', 'AIDriver', 'CombineUnloadAIDriver', diff --git a/hud.lua b/hud.lua index ea2f0ed1a..8c4bd4a64 100644 --- a/hud.lua +++ b/hud.lua @@ -1139,10 +1139,10 @@ function courseplay.hud:updatePageContent(vehicle, page) else self:disableButtonWithFunction(vehicle,page,'changeByX', vehicle.cp.settings.levelCompactShieldHeight) end - elseif entry.functionToCall == 'augerPipeToolPositions:setOrClearPostion' then - --AugerPipeToolPositionsSetting - vehicle.cp.hud.content.pages[page][5][1].text = courseplay:loc('COURSEPLAY_SHOVEL_LOADING_POSITION'); - vehicle.cp.hud.content.pages[page][5][2].text = vehicle.cp.settings.augerPipeToolPositions:getText() + elseif entry.functionToCall == 'pipeToolPositions:setOrClearPostion' then + --PipeToolPositionsSetting + vehicle.cp.hud.content.pages[page][line][1].text = courseplay:loc('COURSEPLAY_SHOVEL_LOADING_POSITION'); + vehicle.cp.hud.content.pages[page][line][2].text = vehicle.cp.settings.pipeToolPositions:getText() elseif entry.functionToCall == 'mixerWagonToolPositions:setOrClearPostion' then --MixerWagonToolPositionsSetting vehicle.cp.hud.content.pages[page][1][1].text = courseplay:loc('COURSEPLAY_SHOVEL_LOADING_POSITION'); @@ -1161,6 +1161,14 @@ function courseplay.hud:updatePageContent(vehicle, page) for i=1,4 do vehicle.cp.hud.content.pages[page][i][2].text = texts[i] end + elseif entry.functionToCall == 'sugarCaneTrailerToolPositions:setOrClearPostion' then + --SugarCaneTrailerToolPositionsSetting + vehicle.cp.hud.content.pages[page][1][1].text = courseplay:loc('COURSEPLAY_SHOVEL_TRANSPORT_POSITION'); + vehicle.cp.hud.content.pages[page][2][1].text = courseplay:loc('COURSEPLAY_SHOVEL_UNLOADING_POSITION'); + local texts = vehicle.cp.settings.sugarCaneTrailerToolPositions:getTexts() + for i=1,4 do + vehicle.cp.hud.content.pages[page][i][2].text = texts[i] + end end end end @@ -2090,6 +2098,11 @@ function courseplay.hud:setGrainTransportAIDriverContent(vehicle) self:addSettingsRow(vehicle,vehicle.cp.settings.loadUnloadOffsetX,'changeByX', 7, 6, 1 ) self:addSettingsRow(vehicle,vehicle.cp.settings.loadUnloadOffsetZ,'changeByX', 7, 7, 1 ) + if vehicle.cp.driver:hasSugarCaneTrailerToolPositions() then + self:enablePageButton(vehicle,9) + self:setupToolPositionButtons(vehicle,vehicle.cp.settings.sugarCaneTrailerToolPositions,9,1) + end + self:setReloadPageOrder(vehicle, -1, true) end @@ -2156,6 +2169,9 @@ function courseplay.hud:setCombineAIDriverContent(vehicle) self:addRowButton(vehicle,vehicle.cp.settings.pipeAlwaysUnfold,'toggle', 6, 3, 1 ) self:addRowButton(vehicle,vehicle.cp.settings.strawSwath,'changeByX', 6, 4, 1 ) self:addRowButton(vehicle,vehicle.cp.settings.allowUnloadOnFirstHeadland,'toggle', 6, 5, 1 ) + if vehicle.cp.settings.pipeToolPositions:getHasMoveablePipe() then + self:setupToolPositionButtons(vehicle,vehicle.cp.settings.pipeToolPositions,3,6) + end end @@ -2188,15 +2204,20 @@ function courseplay.hud:setCombineUnloadAIDriverContent(vehicle,assignedCombines self:addRowButton(vehicle,vehicle.cp.settings.useRealisticDriving,'toggle', 8, 4, 1 ) self:addRowButton(vehicle,vehicle.cp.settings.turnOnField,'toggle', 8, 3, 1 ) + if vehicle.cp.driver:hasSugarCaneTrailerToolPositions() then + self:enablePageButton(vehicle,9) + self:setupToolPositionButtons(vehicle,vehicle.cp.settings.sugarCaneTrailerToolPositions,9,1) + end + self:setReloadPageOrder(vehicle, -1, true) end -function courseplay.hud:setOverloaderAIDriverContent(vehicle,hasMoveablePipe) +function courseplay.hud:setOverloaderAIDriverContent(vehicle) -- page 3 self:addSettingsRowWithArrows(vehicle,vehicle.cp.settings.driveOnAtFillLevel,'changeByX', 3, 2, 1 ) self:addSettingsRowWithArrows(vehicle,vehicle.cp.settings.followAtFillLevel,'changeByX', 3, 3, 1 ) - if hasMoveablePipe then - self:setupToolPositionButtons(vehicle,vehicle.cp.settings.augerPipeToolPositions, 3, 5) + if vehicle.cp.settings.pipeToolPositions:getHasMoveablePipe() then + self:setupToolPositionButtons(vehicle,vehicle.cp.settings.pipeToolPositions, 3, 5) end self:addSettingsRowWithArrows(vehicle,vehicle.cp.settings.moveOnAtFillLevel,'changeByX', 3, 4, 1 ) end @@ -2206,6 +2227,9 @@ function courseplay.hud:setFieldSupplyAIDriverContent(vehicle) self:addSettingsRowWithArrows(vehicle,vehicle.cp.settings.moveOnAtFillLevel,'changeByX', 3, 1, 1 ) self:addRowButton(vehicle,vehicle.cp.settings.siloSelectedFillTypeFieldSupplyDriver,'addFilltype', 3, 2, 1 ) self:setupSiloSelectedFillTypeList(vehicle,vehicle.cp.settings.siloSelectedFillTypeFieldSupplyDriver, 3, 3, 4, 1) + if vehicle.cp.settings.pipeToolPositions:getHasMoveablePipe() then + self:setupToolPositionButtons(vehicle,vehicle.cp.settings.pipeToolPositions, 3, 5) + end end diff --git a/settings.lua b/settings.lua index 3d969bc47..a1709318d 100644 --- a/settings.lua +++ b/settings.lua @@ -1599,7 +1599,7 @@ function DriverModeSetting:setAIDriver() end function DriverModeSetting:resetToDefault() - self:set(self.defaultMode) + self:set(self.defaultMode,true) end function DriverModeSetting:getDefaultMode() @@ -3482,11 +3482,13 @@ function WorkingToolPositionsSetting:updateAndSetPosition(object,dt,posX,callbac local spec = object.spec_cylindered if spec and spec.cpWorkingToolPos and spec.cpWorkingToolPos[posX] and self:isValidSpec(object) then for toolIndex, tool in ipairs(spec.movingTools) do - local isRotating,rotDiff = self.checkToolRotation(object,tool,toolIndex,posX,dt,self) - local isMoving,moveDiff = self.checkToolTranslation(object,tool,toolIndex,posX,dt,self) - if isRotating or isMoving then - callback.isDirty = true - callback.diff = math.max(rotDiff,moveDiff,callback.diff) + if object:getIsMovingToolActive(tool) then + local isRotating,rotDiff = self.checkToolRotation(object,tool,toolIndex,posX,dt,self) + local isMoving,moveDiff = self.checkToolTranslation(object,tool,toolIndex,posX,dt,self) + if isRotating or isMoving then + callback.isDirty = true + callback.diff = math.max(rotDiff,moveDiff,callback.diff) + end end end end @@ -3734,21 +3736,33 @@ function FrontloaderToolPositionsSetting:isDisabled() return self.driverModeSetting:get() ~= courseplay.MODE_SHOVEL_FILL_AND_EMPTY end ----@class AugerPipeToolPositionsSetting : WorkingToolPositionsSetting -AugerPipeToolPositionsSetting = CpObject(WorkingToolPositionsSetting) -function AugerPipeToolPositionsSetting:init(vehicle) +---@class PipeToolPositionsSetting : WorkingToolPositionsSetting +PipeToolPositionsSetting = CpObject(WorkingToolPositionsSetting) +function PipeToolPositionsSetting:init(vehicle) local label = "pipe" local toolTip = "pipe" local validSpecs = {Pipe} - WorkingToolPositionsSetting.init(self,"augerPipeToolPositions", label, toolTip, vehicle,1,validSpecs) + WorkingToolPositionsSetting.init(self,"pipeToolPositions", label, toolTip, vehicle,1,validSpecs) end -function AugerPipeToolPositionsSetting:getText() +function PipeToolPositionsSetting:getText() if self.hasPosition[1] then return "ok" end end +function PipeToolPositionsSetting:validateCurrentValue() + self.hasMoveablePipe = nil + local pipeImplement = AIDriverUtil.getImplementWithSpecialization(self.vehicle,Pipe) or self.vehicle.spec_pipe and self.vehicle + if pipeImplement then + self.hasMoveablePipe = pipeImplement.spec_cylindered ~= nil + end +end + +function PipeToolPositionsSetting:getHasMoveablePipe() + return self.hasMoveablePipe +end + ---@class MixerWagonToolPositionsSetting : WorkingToolPositionsSetting MixerWagonToolPositionsSetting = CpObject(WorkingToolPositionsSetting) function MixerWagonToolPositionsSetting:init(vehicle) @@ -3757,6 +3771,25 @@ function MixerWagonToolPositionsSetting:init(vehicle) WorkingToolPositionsSetting.init(self,"mixerWagonToolPositions", label, toolTip, vehicle,2) end +---@class SugarCaneTrailerToolPositionsSetting : WorkingToolPositionsSetting +SugarCaneTrailerToolPositionsSetting = CpObject(WorkingToolPositionsSetting) +SugarCaneTrailerToolPositionsSetting.TRANSPORT_POSITION = 1 +SugarCaneTrailerToolPositionsSetting.UNLOADING_POSITION = 2 +function SugarCaneTrailerToolPositionsSetting:init(vehicle) + local label = "sugarCaneTrailer" + local toolTip = "sugarCaneTrailer" + local validSpecs = {Shovel} + WorkingToolPositionsSetting.init(self,"sugarCaneTrailerToolPositions", label, toolTip, vehicle,2,validSpecs) +end + +function SugarCaneTrailerToolPositionsSetting:validateCurrentValue() + self.hasSugarCaneTrailer = AIDriverUtil.hasSugarCaneTrailer(self.vehicle) +end + +function SugarCaneTrailerToolPositionsSetting:getHasSugarCaneTrailer() + return self.hasSugarCaneTrailer +end + ---@class AlwaysWaitForShovelPositionsSetting : BooleanSetting AlwaysWaitForShovelPositionsSetting = CpObject(BooleanSetting) function AlwaysWaitForShovelPositionsSetting:init(vehicle) @@ -4146,7 +4179,7 @@ function SettingsContainer.createVehicleSpecificSettings(vehicle) container:addSetting(ConvoyMinDistanceSetting,vehicle) container:addSetting(ConvoyMaxDistanceSetting,vehicle) -- do we need this one ? container:addSetting(FrontloaderToolPositionsSetting,vehicle,container.driverMode) - container:addSetting(AugerPipeToolPositionsSetting,vehicle) + container:addSetting(PipeToolPositionsSetting,vehicle) container:addSetting(AlwaysWaitForShovelPositionsSetting,vehicle) container:addSetting(LevelCompactModeSetting,vehicle) container:addSetting(LevelCompactSearchOnlyAutomatedDriverSetting,vehicle) @@ -4164,6 +4197,7 @@ function SettingsContainer.createVehicleSpecificSettings(vehicle) container:addSetting(MixerWagonAIDriver_SiloSelectedFillTypeSetting, vehicle) container:addSetting(MixerWagonToolPositionsSetting, vehicle) container:addSetting(CourseDrawModeSetting,vehicle) + container:addSetting(SugarCaneTrailerToolPositionsSetting, vehicle) return container end diff --git a/start_stop.lua b/start_stop.lua index 88d392b61..b7156b853 100644 --- a/start_stop.lua +++ b/start_stop.lua @@ -116,7 +116,6 @@ function courseplay:stop(self) ---Is this one still used as cp.isTurning isn't getting set to true ?? self.cp.isTurning = nil; courseplay:clearTurnTargets(self); - self.cp.fillTrigger = nil; self.cp.hasMachineToFill = false; -- resetting variables diff --git a/triggers.lua b/triggers.lua index e8069864c..d24adf28c 100644 --- a/triggers.lua +++ b/triggers.lua @@ -70,7 +70,7 @@ function courseplay:doSingleRaycast(vehicle, triggerType, direction, callBack, x end; end; --- FIND TIP TRIGGER CALLBACK +--- FIND TIP TRIGGER CALLBACK -- target object in raycastAll() was the vehicle, so here, super confusingly, self is the vehicle and not courseplay, -- TODO: function signature should really be courseplay.findTipTriggerCallback(vehicle, transformId, x, y, z) for clarity. -- When a trigger with a suitable fill type is found, vehicle.cp.currentTipTrigger is set to the trigger (definition unclear) @@ -184,115 +184,6 @@ function courseplay:findTipTriggerCallback(transformId, x, y, z, distance) return true; end; --- FIND SPECIAL TRIGGER CALLBACK -function courseplay:findSpecialTriggerCallback(transformId, x, y, z, distance) - if CpManager.confirmedNoneSpecialTriggers[transformId] then - return true; - end; - - if courseplay.debugChannels[courseplay.DBG_TRIGGERS] then - cpDebug:drawPoint(x, y, z, 1, 1, 0); - end; - - --[[Tommi TODO check if its still nessesary (mode8) - local name = tostring(getName(transformId)); - local parent = getParent(transformId); - for _,implement in pairs(self:getAttachedImplements()) do - if (implement.object ~= nil and implement.object.rootNode == parent) then - courseplay:debug(('%s: trigger %s is from my own implement'):format(nameNum(self), tostring(transformId)), courseplay.DBG_TRIGGERS); - return true - end - end - ]] - - --if the trigger is on my list an I'm not in the trigger (because I allready filled up here), add it to my found triggers - if courseplay.triggers.fillTriggers[transformId] then - local imNotInThisTrigger = true - local trigger = courseplay.triggers.fillTriggers[transformId] - for _,workTool in pairs (self.cp.workTools) do - if (trigger.onActivateObject and trigger.getIsActivatable and trigger:getIsActivatable(workTool)) - or (trigger.sourceObject and #workTool.spec_fillUnit.fillTrigger.triggers > 0 and workTool.spec_fillUnit.fillTrigger.triggers[1] == trigger) then - courseplay:debug(('%s: %s is allready in fillTrigger(%d)'):format(nameNum(self),tostring(workTool:getName()), transformId), courseplay.DBG_TRIGGERS); - imNotInThisTrigger = false - end - end - if imNotInThisTrigger then - courseplay:debug(('%s: fillTrigger(%d) found, add to vehicle.cp.fillTriggers'):format(nameNum(self), transformId), courseplay.DBG_TRIGGERS); - courseplay:addFoundFillTrigger(self, transformId) - courseplay:setCustomTimer(self, 'triggerFailBackup', 10); - else - courseplay:debug(('%s: fillTrigger(%d) found, but Im allready in it so ignore it'):format(nameNum(self), transformId), courseplay.DBG_TRIGGERS); - end - return false; - end - - CpManager.confirmedNoneSpecialTriggers[transformId] = true; - CpManager.confirmedNoneSpecialTriggersCounter = CpManager.confirmedNoneSpecialTriggersCounter + 1; - courseplay:debug(('%s: added %d (%s) to trigger blacklist -> total=%d'):format(nameNum(self), transformId, name, CpManager.confirmedNoneSpecialTriggersCounter), courseplay.DBG_TRIGGERS); - - return true; -end; - -function courseplay:addFoundFillTrigger(vehicle, transformId) - --if we dont have a fillTrigger, set cp.fillTrigger - if vehicle.cp.fillTrigger == nil then - courseplay:debug(string.format("set %s as vehicle.cp.fillTrigger",tostring(transformId)),courseplay.DBG_TRIGGERS) - vehicle.cp.fillTrigger = transformId; - end - -- check whether we have it in our list allready - local allreadyThere = false - if #vehicle.cp.fillTriggers >0 then - for i=1,#vehicle.cp.fillTriggers do - if vehicle.cp.fillTriggers[i] == transformId then - allreadyThere = true; - break; - end - end - end - --if not, add it - if not allreadyThere then - table.insert(vehicle.cp.fillTriggers,transformId) - courseplay.debugVehicle(courseplay.DBG_TRIGGERS,vehicle,'add %s to vehicle.cp.fillTriggers; new number of triggers: %d',tostring(transformId),#vehicle.cp.fillTriggers) - end -end - --- FIND Fuel TRIGGER CALLBACK -function courseplay:findFuelTriggerCallback(transformId, x, y, z, distance) - if CpManager.confirmedNoneSpecialTriggers[transformId] then - return true; - end; - - if courseplay.debugChannels[courseplay.DBG_TRIGGERS] then - cpDebug:drawPoint(x, y, z, 1, 1, 0); - end; - - --[[Tommi TODO check if its still nessesary (mode8) - local name = tostring(getName(transformId)); - local parent = getParent(transformId); - for _,implement in pairs(self:getAttachedImplements()) do - if (implement.object ~= nil and implement.object.rootNode == parent) then - courseplay:debug(('%s: trigger %s is from my own implement'):format(nameNum(self), tostring(transformId)), courseplay.DBG_TRIGGERS); - return true - end - end - ]] - - --print("findSpecialTriggerCallback found "..tostring(transformId).." "..getName(transformId)) - if courseplay.triggers.fillTriggers[transformId] then - --print(transformId.." is in fillTrigers") - self.cp.fuelFillTrigger = transformId; - courseplay:setCustomTimer(self, 'triggerFailBackup', 10); - return false; - end - - CpManager.confirmedNoneSpecialTriggers[transformId] = true; - CpManager.confirmedNoneSpecialTriggersCounter = CpManager.confirmedNoneSpecialTriggersCounter + 1; - courseplay:debug(('%s: added %d (%s) to trigger blacklist -> total=%d'):format(nameNum(self), transformId, name, CpManager.confirmedNoneSpecialTriggersCounter), courseplay.DBG_TRIGGERS); - - return true; -end; - - function courseplay:updateAllTriggers() courseplay:debug('updateAllTriggers()', courseplay.DBG_TRIGGERS); @@ -634,6 +525,15 @@ function Triggers.getBunkerSilos() return Triggers.bunkerSilos end +function Triggers.getLoadingTriggers() + return Triggers.loadingTriggers +end + +function Triggers.getFillTriggers() + return Triggers.fillTriggers +end + + ---Add all relevant triggers on create and remove them on delete. function Triggers.addLoadingTrigger(trigger,superFunc,...) local returnValue = superFunc(trigger,...)