90 | function AIDriveStrategyCombine:getDriveData(dt, vX,vY,vZ) |
91 | local rootVehicle = self.vehicle.rootVehicle |
92 | local isTurning = rootVehicle.getAIFieldWorkerIsTurning ~= nil and rootVehicle:getAIFieldWorkerIsTurning() |
93 | |
94 | local allowedToDrive = true |
95 | local waitForStraw = false |
96 | local maxSpeed = math.huge |
97 | |
98 | for _, combine in pairs(self.combines) do |
99 | if combine.spec_pipe ~= nil then |
100 | local fillLevel = 0 |
101 | local capacity = 0 |
102 | |
103 | local trailerInTrigger = false |
104 | local invalidTrailerInTrigger = false |
105 | local dischargeNode = combine:getCurrentDischargeNode() |
106 | if dischargeNode ~= nil then |
107 | fillLevel = combine:getFillUnitFillLevel(dischargeNode.fillUnitIndex) |
108 | capacity = combine:getFillUnitCapacity(dischargeNode.fillUnitIndex) |
109 | end |
110 | |
111 | local trailer = NetworkUtil.getObject(combine.spec_pipe.nearestObjectInTriggers.objectId) |
112 | if trailer ~= nil then |
113 | trailerInTrigger = true |
114 | end |
115 | |
116 | if combine.spec_pipe.nearestObjectInTriggerIgnoreFillLevel then |
117 | invalidTrailerInTrigger = true |
118 | end |
119 | |
120 | local currentPipeTargetState = combine.spec_pipe.targetState |
121 | |
122 | if capacity == math.huge then |
123 | -- forage harvesters |
124 | if currentPipeTargetState ~= 2 then |
125 | combine:setPipeState(2) |
126 | end |
127 | |
128 | if not isTurning then |
129 | local targetObject, _ = combine:getDischargeTargetObject(dischargeNode) |
130 | allowedToDrive = trailerInTrigger and targetObject ~= nil |
131 | |
132 | if VehicleDebug.state == VehicleDebug.DEBUG_AI then |
133 | if not trailerInTrigger then |
134 | self.vehicle:addAIDebugText("COMBINE -> Waiting for trailer enter the trigger") |
135 | elseif trailerInTrigger and targetObject == nil then |
136 | self.vehicle:addAIDebugText("COMBINE -> Waiting for pipe hitting the trailer") |
137 | end |
138 | end |
139 | end |
140 | else |
141 | -- combine harvesters |
142 | local pipeState = currentPipeTargetState |
143 | |
144 | if fillLevel > (0.8*capacity) then |
145 | if not self.beaconLightsActive then |
146 | self.vehicle:setAIMapHotspotBlinking(true) |
147 | self.vehicle:setBeaconLightsVisibility(true) |
148 | self.beaconLightsActive = true |
149 | end |
150 | |
151 | if not self.notificationGrainTankWarningShown then |
152 | g_currentMission:addIngameNotification(FSBaseMission.INGAME_NOTIFICATION_CRITICAL, string.format(g_i18n:getText("ai_messageErrorGrainTankIsNearlyFull"), self.vehicle:getCurrentHelper().name) ) |
153 | self.notificationGrainTankWarningShown = true |
154 | end |
155 | else |
156 | if self.beaconLightsActive then |
157 | self.vehicle:setAIMapHotspotBlinking(false) |
158 | self.vehicle:setBeaconLightsVisibility(false) |
159 | self.beaconLightsActive = false |
160 | end |
161 | |
162 | self.notificationGrainTankWarningShown = false |
163 | end |
164 | |
165 | if fillLevel == capacity then |
166 | pipeState = 2 |
167 | self.wasCompletelyFull = true |
168 | if self.notificationFullGrainTankShown ~= true then |
169 | g_currentMission:addIngameNotification(FSBaseMission.INGAME_NOTIFICATION_CRITICAL, string.format(g_i18n:getText("ai_messageErrorGrainTankIsFull"), self.vehicle:getCurrentHelper().name) ) |
170 | self.notificationFullGrainTankShown = true |
171 | end |
172 | else |
173 | self.notificationFullGrainTankShown = false |
174 | end |
175 | |
176 | if trailerInTrigger then |
177 | pipeState = 2 |
178 | end |
179 | |
180 | if not trailerInTrigger then |
181 | if fillLevel < capacity * 0.8 then |
182 | self.wasCompletelyFull = false |
183 | |
184 | if not combine:getIsTurnedOn() and combine:getCanBeTurnedOn() then |
185 | combine:aiImplementStartLine() |
186 | end |
187 | end |
188 | end |
189 | |
190 | if (not trailerInTrigger and not invalidTrailerInTrigger) and fillLevel < capacity then |
191 | pipeState = 1 |
192 | end |
193 | |
194 | if fillLevel < 0.1 then |
195 | if not combine.spec_pipe.aiFoldedPipeUsesTrailerSpace then |
196 | if not trailerInTrigger and not invalidTrailerInTrigger then |
197 | pipeState = 1 |
198 | end |
199 | |
200 | if not combine:getIsTurnedOn() and combine:getCanBeTurnedOn() then |
201 | combine:aiImplementStartLine() |
202 | end |
203 | end |
204 | |
205 | self.wasCompletelyFull = false |
206 | end |
207 | |
208 | if currentPipeTargetState ~= pipeState then |
209 | combine:setPipeState(pipeState) |
210 | end |
211 | |
212 | allowedToDrive = fillLevel < capacity |
213 | |
214 | if pipeState == 2 and self.wasCompletelyFull then |
215 | allowedToDrive = false |
216 | if VehicleDebug.state == VehicleDebug.DEBUG_AI then |
217 | self.vehicle:addAIDebugText("COMBINE -> Waiting for trailer to unload") |
218 | end |
219 | end |
220 | |
221 | if isTurning and trailerInTrigger then |
222 | if combine:getCanDischargeToObject(dischargeNode) then |
223 | allowedToDrive = fillLevel == 0 |
224 | |
225 | if VehicleDebug.state == VehicleDebug.DEBUG_AI then |
226 | if not allowedToDrive then |
227 | self.vehicle:addAIDebugText("COMBINE -> Unload to trailer on headland") |
228 | end |
229 | end |
230 | end |
231 | end |
232 | |
233 | local freeFillLevel = capacity - fillLevel |
234 | if freeFillLevel < self.slowDownFillLevel then |
235 | -- we want to drive at least 2 km/h to avoid combine stops too early |
236 | maxSpeed = 2 + (freeFillLevel / self.slowDownFillLevel) * self.slowDownStartSpeed |
237 | |
238 | if VehicleDebug.state == VehicleDebug.DEBUG_AI then |
239 | self.vehicle:addAIDebugText(string.format("COMBINE -> Slow down because nearly full: %.2f", maxSpeed)) |
240 | end |
241 | end |
242 | end |
243 | |
244 | if not trailerInTrigger then |
245 | if combine.spec_combine.isSwathActive then |
246 | if combine.spec_combine.strawPSenabled then |
247 | waitForStraw = true |
248 | end |
249 | end |
250 | end |
251 | end |
252 | end |
253 | |
254 | if isTurning and waitForStraw then |
255 | if VehicleDebug.state == VehicleDebug.DEBUG_AI then |
256 | self.vehicle:addAIDebugText("COMBINE -> Waiting for straw to drop") |
257 | end |
258 | |
259 | local x, _, z = localToWorld(self.vehicle:getAIDirectionNode(), 0, 0, -10) |
260 | local dist = MathUtil.vector2Length(vX-x, vZ-z) |
261 | return x, z, false, 10, dist |
262 | else |
263 | if not allowedToDrive then |
264 | return 0, 1, true, 0, math.huge |
265 | else |
266 | return nil, nil, nil, maxSpeed, nil |
267 | end |
268 | end |
269 | end |
53 | function AIDriveStrategyCombine:update(dt) |
54 | for _, combine in pairs(self.combines) do |
55 | if combine.spec_pipe ~= nil then |
56 | local capacity = 0 |
57 | |
58 | local dischargeNode = combine:getCurrentDischargeNode() |
59 | if dischargeNode ~= nil then |
60 | capacity = combine:getFillUnitCapacity(dischargeNode.fillUnitIndex) |
61 | end |
62 | |
63 | if capacity == math.huge then |
64 | local rootVehicle = self.vehicle.rootVehicle |
65 | if rootVehicle.getAIFieldWorkerIsTurning ~= nil and not rootVehicle:getAIFieldWorkerIsTurning() then |
66 | local trailer = NetworkUtil.getObject(combine.spec_pipe.nearestObjectInTriggers.objectId) |
67 | if trailer ~= nil then |
68 | local trailerFillUnitIndex = combine.spec_pipe.nearestObjectInTriggers.fillUnitIndex |
69 | local fillType = combine:getDischargeFillType(dischargeNode) |
70 | if fillType == FillType.UNKNOWN then |
71 | -- if nothing is in combine fillUnit we just check if we're targetting the trailer with the trailers first fill type or the current fill type if something is loaded |
72 | fillType = trailer:getFillUnitFillType(trailerFillUnitIndex) |
73 | if fillType == FillType.UNKNOWN then |
74 | fillType = trailer:getFillUnitFirstSupportedFillType(trailerFillUnitIndex) |
75 | end |
76 | combine:setForcedFillTypeIndex(fillType) |
77 | else |
78 | -- otherwise we check if the fill type of the combine is supported on the trailer |
79 | combine:setForcedFillTypeIndex(nil) |
80 | end |
81 | end |
82 | end |
83 | end |
84 | end |
85 | end |
86 | end |