forked from Courseplay/courseplay
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcombines.lua
408 lines (356 loc) · 15.7 KB
/
combines.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
function courseplay:find_combines(self)
-- reseting reachable combines
local found_combines = {}
-- go through all vehicles and find filter all combines
local all_vehicles = g_currentMission.vehicles
for k, vehicle in pairs(all_vehicles) do
-- trying to identify combines
if vehicle.cp == nil then
vehicle.cp = {};
courseplay:setNameVariable(vehicle)
end;
if vehicle.cp.isCombine or vehicle.cp.isChopper or vehicle.cp.isHarvesterSteerable or vehicle.cp.isSugarBeetLoader or courseplay:isAttachedCombine(vehicle) then
if (courseplay:isAttachedCombine(vehicle) and vehicle.attacherVehicle ~= nil and not Utils.endsWith(vehicle.configFileName, "poettingerMex6.xml")) or not courseplay:isAttachedCombine(vehicle) then
table.insert(found_combines, vehicle);
end;
end;
end;
return found_combines;
end
function courseplay:combine_allows_tractor(self, combine)
if combine.courseplayers == nil then
combine.courseplayers = {}
end
local num_allowed_courseplayers = 1
if combine.cp.isChopper or combine.cp.isSugarBeetLoader then
num_allowed_courseplayers = 2
else
if self.realistic_driving then
if combine.wants_courseplayer == true then
courseplay:debug(nameNum(self)..": combine full or manual call -> allow tractor",4)
return true
end
-- force unload when combine is full
if combine.grainTankFillLevel == combine.grainTankCapacity then
courseplay:debug(nameNum(self)..": set fill level reached -> allow tractor",4)
return true
end
-- is the pipe on the correct side?
if combine.turnStage == 1 or combine.turnStage == 2 or combine.cp.turnStage ~= 0 then
courseplay:debug(nameNum(self)..": combine is turning -> refuse tractor",4)
return false
end
local fruitSide = courseplay:side_to_drive(self, combine, -10)
if fruitSide == "none" then
courseplay:debug(nameNum(self)..": fruitSide is none -> try again with offset 0",4)
fruitSide = courseplay:side_to_drive(self, combine, 0)
end
if fruitSide == "left" then
courseplay:debug(nameNum(self)..": path finding active and pipe in fruit -> refuse tractor",4)
return false
end
end
end
if table.getn(combine.courseplayers) >= num_allowed_courseplayers then
return false
end
if table.getn(combine.courseplayers) == 1 and not combine.courseplayers[1].allow_following then
return false
end
return true
end
-- find combines on the same field (texture)
function courseplay:update_combines(self)
self.reachable_combines = {}
if not self.search_combine and self.saved_combine then
courseplay:debug(nameNum(self)..": combine is manual set",4)
table.insert(self.reachable_combines, self.saved_combine)
return
end
courseplay:debug(string.format("%s: combines total: %d", nameNum(self), table.getn(self.reachable_combines)), 4)
local x, y, z = getWorldTranslation(self.cp.DirectionNode)
local hx, hy, hz = localToWorld(self.cp.DirectionNode, -2, 0, 0)
local lx, ly, lz = nil, nil, nil
local terrain = g_currentMission.terrainDetailId
local found_combines = courseplay:find_combines(self)
courseplay:debug(string.format("%s: combines found: %d", nameNum(self), table.getn(found_combines)), 4)
-- go throuh found
for k, combine in pairs(found_combines) do
lx, ly, lz = getWorldTranslation(combine.rootNode)
local dlx, dly, dlz = worldToLocal(self.cp.DirectionNode, lx, y, lz)
local dnx = dlz * -1
local dnz = dlx
local angle = math.atan(dnz / dnx)
dnx = math.cos(angle) * -2
dnz = math.sin(angle) * -2
hx, hy, hz = localToWorld(self.cp.DirectionNode, dnx, 0, dnz)
local area0, area = Utils.getDensity(terrain, 0, x, z, lx, lz, hx, hz)
local area1 = Utils.getDensity(terrain, 1, x, z, lx, lz, hx, hz)
local area2 = Utils.getDensity(terrain, 2, x, z, lx, lz, hx, hz)
local area3 = Utils.getDensity(terrain, 3, x, z, lx, lz, hx, hz)
local areaAll = area0 + area1 + area2 + area3
courseplay:debug(nameNum(self)..": channel0: "..tostring(area0).." / channel1: "..tostring(area1).." / channel2: "..tostring(area2).." / channel3: "..tostring(area3),4)
courseplay:debug(nameNum(self)..": area: "..tostring(area).." / field in area: "..tostring(areaAll),4)
if courseplay:isBetween(areaAll, area * 0.999, area * 1.1, true) and courseplay:combine_allows_tractor(self, combine) then
courseplay:debug(nameNum(self)..": adding "..tostring(combine.name).." to reachable combines list",4)
table.insert(self.reachable_combines, combine)
end
end
courseplay:debug(string.format("%s: combines reachable: %d ", nameNum(self), table.getn(self.reachable_combines)), 4)
end
function courseplay:register_at_combine(self, combine)
local curFile = "combines.lua"
courseplay:debug(string.format("%s: registering at combine %s", nameNum(self), tostring(combine.name)), 4)
--courseplay:debug(tableShow(combine, tostring(combine.name), 4), 4)
local num_allowed_courseplayers = 1
self.calculated_course = false
if combine.courseplayers == nil then
combine.courseplayers = {};
end;
if combine.cp == nil then
combine.cp = {};
end;
if combine.cp.isChopper or combine.cp.isSugarBeetLoader then
num_allowed_courseplayers = 2
else
if self.realistic_driving then
if combine.wants_courseplayer == true or combine.grainTankFillLevel == combine.grainTankCapacity then
else
-- force unload when combine is full
-- is the pipe on the correct side?
if combine.turnStage == 1 or combine.turnStage == 2 or combine.cp.turnStage ~= 0 then
courseplay:debug(nameNum(self)..": combine is turning -> don't register tractor",4)
return false
end
local fruitSide = courseplay:side_to_drive(self, combine, -10)
if fruitSide == "none" then
courseplay:debug(nameNum(self)..": fruitSide is none -> try again with offset 0",4)
fruitSide = courseplay:side_to_drive(self, combine, 0)
end
courseplay:debug(nameNum(self)..": courseplay:side_to_drive = "..tostring(fruitSide),4)
if fruitSide == "left" then
courseplay:debug(nameNum(self)..": path finding active and pipe in fruit -> don't register tractor",4)
return false
end
end
end
end
if table.getn(combine.courseplayers) == num_allowed_courseplayers then
courseplay:debug(string.format("%s (id %s): combine (id %s) is already registered", nameNum(self), tostring(self.id), tostring(combine.id)), 4);
return false
end
--THOMAS' best_combine START
if combine.cp.isCombine or (courseplay:isAttachedCombine(combine) and not courseplay:isSpecialChopper(combine)) then
local distance = 9999999
local vehicle_ID = 0
for k, vehicle in pairs(g_currentMission.vehicles) do --TODO: Liste einengen, nur Courseplayers
if vehicle.combineID ~= nil then
--print(tostring(vehicle.name).." is calling for "..tostring(vehicle.combineID).." combine.id= "..tostring(combine.id))
if vehicle.combineID == combine.id and vehicle.active_combine == nil then
courseplay:debug(tostring(vehicle.id).." : distanceToCombine:"..tostring(vehicle.distanceToCombine).." for combine.id:"..tostring(combine.id), 4)
if distance > vehicle.distanceToCombine then
distance = vehicle.distanceToCombine
vehicle_ID = vehicle.id
end
end
end
end
if vehicle_ID ~= self.id then
courseplay:debug(nameNum(self) .. " (id " .. tostring(self.id) .. "): there's a closer tractor that's trying to register: "..tostring(vehicle_ID), 4)
return false
else
courseplay:debug(nameNum(self) .. " (id " .. tostring(self.id) .. "): it's my turn", 4);
end
end
--THOMAS' best_combine END
if table.getn(combine.courseplayers) == 1 and not combine.courseplayers[1].allow_following then
return false
end
-- you got a courseplayer, so stop yellin....
if combine.wants_courseplayer ~= nil and combine.wants_courseplayer == true then
combine.wants_courseplayer = false
end
courseplay:debug(string.format("%s is being checked in with %s", nameNum(self), tostring(combine.name)), 4)
combine.isCheckedIn = 1;
self.distanceToCombine = nil
self.combineID = nil
table.insert(combine.courseplayers, self)
self.courseplay_position = table.getn(combine.courseplayers)
self.active_combine = combine
courseplay:askForSpecialSettings(combine, combine)
--OFFSET
if combine.cp == nil then
combine.cp = {};
end;
combine.cp.pipeSide = 1;
if self.auto_combine_offset == true or self.combine_offset == 0 then
if combine.cp.offset == nil then
--print("no saved offset - initialise")
courseplay:calculateInitialCombineOffset(self, combine);
else
--print("take the saved cp.offset")
self.combine_offset = combine.cp.offset;
end;
end;
--END OFFSET
courseplay:add_to_combines_ignore_list(self, combine);
return true;
end
function courseplay:unregister_at_combine(self, combine)
if self.active_combine == nil or combine == nil then
return true
end
self.calculated_course = false;
courseplay:remove_from_combines_ignore_list(self, combine)
combine.isCheckedIn = nil;
table.remove(combine.courseplayers, self.courseplay_position)
-- updating positions of tractors
for k, tractor in pairs(combine.courseplayers) do
tractor.courseplay_position = k
end
self.allow_follwing = false
self.courseplay_position = nil
self.active_combine = nil
self.ai_state = 1
if self.trafficCollisionIgnoreList[combine.rootNode] == true then
self.trafficCollisionIgnoreList[combine.rootNode] = nil
end
return true
end
function courseplay:add_to_combines_ignore_list(self, combine)
if combine == nil or combine.trafficCollisionIgnoreList == nil then
return
end
if combine.trafficCollisionIgnoreList[self.rootNode] == nil then
combine.trafficCollisionIgnoreList[self.rootNode] = true
end
end
function courseplay:remove_from_combines_ignore_list(self, combine)
if combine == nil or combine.trafficCollisionIgnoreList == nil then
return
end
if combine.trafficCollisionIgnoreList[self.rootNode] == true then
combine.trafficCollisionIgnoreList[self.rootNode] = nil
end
end
function courseplay:calculateInitialCombineOffset(self, combine)
local curFile = "combines.lua";
local leftMarker = nil
local currentCutter = nil
combine.cp.lmX, combine.cp.rmX = 1.5, -1.5;
--print("run initial offset")
if combine.attachedCutters ~= nil then
for cutter, implement in pairs(combine.attachedCutters) do
if cutter.aiLeftMarker ~= nil then
if leftMarker == nil then
leftMarker = cutter.aiLeftMarker;
rightMarker = cutter.aiRightMarker;
currentCutter = cutter;
if leftMarker ~= nil and rightMarker ~= nil then
local x, y, z = getWorldTranslation(currentCutter.rootNode);
combine.cp.lmX, _, _ = worldToLocal(leftMarker, x, y, z);
combine.cp.rmX, _, _ = worldToLocal(rightMarker, x, y, z);
end;
end;
end;
end;
end;
local prnX,prnY,prnZ, prnwX,prnwY,prnwZ, combineToPrnX,combineToPrnY,combineToPrnZ = 0,0,0, 0,0,0, 0,0,0;
if combine.pipeRaycastNode ~= nil then
prnX, prnY, prnZ = getTranslation(combine.pipeRaycastNode)
prnwX, prnwY, prnwZ = getWorldTranslation(combine.pipeRaycastNode)
combineToPrnX, combineToPrnY, combineToPrnZ = worldToLocal(combine.rootNode, prnwX, prnwY, prnwZ)
if combineToPrnX >= 0 then
combine.cp.pipeSide = 1; --left
--print("pipe is left")
else
combine.cp.pipeSide = -1; --right
--print("pipe is right")
end;
end;
--special tools, special cases
if combine.name == "Grimme Rootster 604" then
self.combine_offset = -4.3;
elseif combine.name == "Grimme SE 75-55" then
self.combine_offset = 4.3;
elseif combine.name == "Fahr M66" then
self.combine_offset = 4.4;
elseif self.auto_combine_offset and Utils.endsWith(combine.configFileName, "JF_1060.xml") then
self.combine_offset = -7
combine.cp.offset = 7
elseif combine.cp.isSugarBeetLoader then
local utwX,utwY,utwZ = getWorldTranslation(combine.unloadingTrigger.node);
local combineToUtwX,_,_ = worldToLocal(combine.rootNode, utwX,utwY,utwZ);
self.combine_offset = combineToUtwX;
--combine // combine_offset is in auto mode
elseif not combine.cp.isChopper and combine.currentPipeState == 2 and combine.pipeRaycastNode ~= nil then -- pipe is extended
self.combine_offset = combineToPrnX;
courseplay:debug(string.format("%s(%i): %s @ %s: using combineToPrnX=%f, self.combine_offset=%f", curFile, debug.getinfo(1).currentline, nameNum(self), tostring(combine.name), combineToPrnX, self.combine_offset), 4)
elseif not combine.cp.isChopper and combine.pipeRaycastNode ~= nil then --pipe is closed
if getParent(combine.pipeRaycastNode) == combine.rootNode then -- pipeRaycastNode is direct child of combine.root
self.combine_offset = prnX;
courseplay:debug(string.format("%s(%i): %s @ %s: combine.root > pipeRaycastNode / self.combine_offset=prnX=%f", curFile, debug.getinfo(1).currentline, nameNum(self), tostring(combine.name), self.combine_offset), 4)
elseif getParent(getParent(combine.pipeRaycastNode)) == combine.rootNode then --pipeRaycastNode is direct child of pipe is direct child of combine.root
local pipeX, pipeY, pipeZ = getTranslation(getParent(combine.pipeRaycastNode))
self.combine_offset = pipeX - prnZ;
if prnZ == 0 or combine.name == "Grimme Rootster 604" then
self.combine_offset = pipeX - prnY;
end
courseplay:debug(string.format("%s(%i): %s @ %s: combine.root > pipe > pipeRaycastNode / self.combine_offset=pipeX-prnX=%f", curFile, debug.getinfo(1).currentline, nameNum(self), tostring(combine.name), self.combine_offset), 4)
elseif combineToPrnX > combine.cp.lmX then
self.combine_offset = combineToPrnX + (5 * combine.cp.pipeSide);
courseplay:debug(string.format("%s(%i): %s @ %s: using combineToPrnX=%f, self.combine_offset=%f", curFile, debug.getinfo(1).currentline, nameNum(self), tostring(combine.name), combineToPrnX, self.combine_offset), 4)
elseif combine.cp.lmX ~= nil then
if combine.cp.lmX > 0 then --use leftMarker
self.combine_offset = combine.cp.lmX + 2.5;
courseplay:debug(string.format("%s(%i): %s @ %s: using leftMarker+2.5, self.combine_offset=%f", curFile, debug.getinfo(1).currentline, nameNum(self), tostring(combine.name), self.combine_offset), 4);
end;
else --BACKUP
self.combine_offset = 8 * combine.cp.pipeSide;
end;
elseif combine.cp.isChopper then
courseplay:debug(string.format("%s(%i): %s @ %s: combine.forced_side=%s", curFile, debug.getinfo(1).currentline, nameNum(self), combine.name, tostring(combine.forced_side)), 4);
if combine.forced_side ~= nil then
courseplay:debug(string.format("%s(%i): %s @ %s: combine.forced_side=%s, going by forced_side", curFile, debug.getinfo(1).currentline, nameNum(self), tostring(combine.name), combine.forced_side), 4);
if combine.forced_side == "left" then
self.sideToDrive = "left";
if combine.cp.lmX ~= nil then
self.combine_offset = combine.cp.lmX + 2.5;
else
self.combine_offset = 8;
end;
elseif combine.forced_side == "right" then
self.sideToDrive = "right";
if combine.cp.lmX ~= nil then
self.combine_offset = (combine.cp.lmX + 2.5) * -1;
else
self.combine_offset = -8;
end;
end
else
courseplay:debug(string.format("%s(%i): %s @ %s: combine.forced_side=%s, going by fruit", curFile, debug.getinfo(1).currentline, nameNum(self), tostring(combine.name), tostring(combine.forced_side)), 4);
local fruitSide = courseplay:side_to_drive(self, combine, 5);
if fruitSide == "right" then
if combine.cp.lmX ~= nil then
self.combine_offset = math.max(combine.cp.lmX + 2.5, 7);
else --attached chopper
self.combine_offset = 7;
end;
elseif fruitSide == "left" then
if combine.cp.lmX ~= nil then
self.combine_offset = math.max(combine.cp.lmX + 2.5, 7) * -1;
else --attached chopper
self.combine_offset = -3;
end;
elseif fruitSide == "none" then
if combine.cp.lmX ~= nil then
self.combine_offset = math.max(combine.cp.lmX + 2.5, 7);
else --attached chopper
self.combine_offset = 7;
end;
end
--print("saving offset")
combine.cp.offset = math.abs(self.combine_offset)
end;
end;
end;