forked from Courseplay/courseplay
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBunkersiloManager.lua
204 lines (185 loc) · 7.35 KB
/
BunkersiloManager.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
---@class FieldManager
BunkerSiloManager = CpObject()
-- Constructor
function BunkerSiloManager:init()
print("BunkerSiloManager: init()")
end
g_bunkerSiloManager = BunkerSiloManager()
function BunkerSiloManager:createBunkerSiloMap(vehicle, Silo,width, height)
local sx,sz = Silo.bunkerSiloArea.sx,Silo.bunkerSiloArea.sz;
local wx,wz = Silo.bunkerSiloArea.wx,Silo.bunkerSiloArea.wz;
local hx,hz = Silo.bunkerSiloArea.hx,Silo.bunkerSiloArea.hz;
local sy = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, sx, 1, sz);
local bunkerWidth = courseplay:distance(sx,sz, wx, wz)
local bunkerLength = courseplay:distance(sx,sz, hx, hz)
local startDistance = courseplay:distanceToPoint(vehicle, sx, sy, sz)
local endDistance = courseplay:distanceToPoint(vehicle, hx, sy, hz)
local widthDirX,widthDirY,widthDirZ,widthDistance = courseplay:getWorldDirection(sx,sy,sz, wx,sy,wz);
local heightDirX,heightDirY,heightDirZ,heightDistance = courseplay:getWorldDirection(sx,sy,sz, hx,sy,hz);
local widthCount = 0
if width then
widthCount =math.ceil(bunkerWidth/width)
else
widthCount =math.ceil(bunkerWidth/vehicle.cp.workWidth)
end
if vehicle.cp.mode10.leveling and courseplay:isEven(widthCount) then
widthCount = widthCount+1
end
local heightCount = math.ceil(bunkerLength/vehicle.cp.workWidth)
local unitWidth = bunkerWidth/widthCount
local unitHeigth = bunkerLength/heightCount
local heightLengthX = (Silo.bunkerSiloArea.hx-Silo.bunkerSiloArea.sx)/heightCount
local heightLengthZ = (Silo.bunkerSiloArea.hz-Silo.bunkerSiloArea.sz)/heightCount
local widthLengthX = (Silo.bunkerSiloArea.wx-Silo.bunkerSiloArea.sx)/widthCount
local widthLengthZ = (Silo.bunkerSiloArea.wz-Silo.bunkerSiloArea.sz)/widthCount
local getOffTheWall = 0.5;
local lastValidfillType = 0
local map = {}
for heightIndex = 1,heightCount do
map[heightIndex]={}
for widthIndex = 1,widthCount do
local newWx = sx + widthLengthX
local newWz = sz + widthLengthZ
local newHx = sx + heightLengthX
local newHz = sz + heightLengthZ
local wY = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, newWx, 1, newWz);
local hY = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, newHx, 1, newHz);
local fillType = DensityMapHeightUtil.getFillTypeAtLine(newWx, wY, newWz, newHx, hY, newHz, 5)
if lastValidfillType ~= fillType and fillType ~= 0 then
lastValidfillType = fillType
end
local newFillLevel = DensityMapHeightUtil.getFillLevelAtArea(fillType, sx, sz, newWx, newWz, newHx, newHz )
local bx = sx + (widthLengthX/2) + (heightLengthX/2)
local bz = sz + (widthLengthZ/2) + (heightLengthZ/2)
local offset = 0
if vehicle.cp.mode9TargetSilo and vehicle.cp.mode9TargetSilo.type and vehicle.cp.mode9TargetSilo.type == "heap" then
offset = unitWidth/2
else
if widthIndex == 1 then
offset = getOffTheWall+ (vehicle.cp.workWidth/2)
elseif widthIndex == widthCount then
offset = unitWidth- (getOffTheWall+ (vehicle.cp.workWidth/2))
else
offset = unitWidth/2
end
end
local cx,cz = sx +(widthDirX*offset)+(heightLengthX/2),sz +(widthDirZ*offset)+ (heightLengthZ/2)
if vehicle.cp.mode == courseplay.MODE_SHOVEL_FILL_AND_EMPTY and heightIndex == heightCount then
cx,cz = sx +(widthDirX*offset)+(heightLengthX),sz +(widthDirZ*offset)+ (heightLengthZ)
end
local unitArea = unitWidth*unitHeigth
map[heightIndex][widthIndex] ={
sx = sx;
sz = sz;
y = wY;
wx = newWx;
wz = newWz;
hx = newHx;
hz = newHz;
cx = cx;
cz = cz;
bx = bx;
bz = bz;
area = unitArea;
fillLevel = newFillLevel;
fillType = fillType;
bunkerLength = bunkerLength;
bunkerWidth = bunkerWidth;
}
sx = map[heightIndex][widthIndex].wx
sz = map[heightIndex][widthIndex].wz
end
sx = map[heightIndex][1].hx
sz = map[heightIndex][1].hz
end
if lastValidfillType > 0 then
courseplay:debug(('%s: Bunkersilo filled with %s(%i) will be devided in %d lines and %d columns'):format(nameNum(vehicle),g_fillTypeManager.indexToName[lastValidfillType], lastValidfillType, heightCount, widthCount), 10);
else
courseplay:debug(('%s: empty Bunkersilo will be devided in %d lines and %d columns'):format(nameNum(vehicle), heightCount, widthCount), 10);
end
--invert table
if endDistance < startDistance then
courseplay:debug(('%s: Bunkersilo will be approached from the back -> turn map'):format(nameNum(vehicle)), 10);
local newMap = {}
local lineCounter = #map
for lineIndex=1,lineCounter do
local newLineIndex = lineCounter+1-lineIndex;
--print(string.format("put line%s into line%s",tostring(lineIndex),tostring(newLineIndex)))
newMap[newLineIndex]={}
local columnCount = #map[lineIndex]
for columnIndex =1, columnCount do
--print(string.format(" put column%s into column%s",tostring(columnIndex),tostring(columnCount+1-columnIndex)))
newMap[newLineIndex][columnCount+1-columnIndex] = map[lineIndex][columnIndex]
end
end
map = newMap
end
return map
end
function BunkerSiloManager:getTargetBunkerSiloByPointOnCourse(course,forcedPoint)
local pointIndex = forcedPoint or 1 ;
local x,_,z = course:getWaypointPosition(pointIndex)
local tx,tz = x,z + 0.50
local p1x,p1z,p2x,p2z,p1y,p2y = 0,0,0,0,0,0
if g_currentMission.bunkerSilos ~= nil then
for _, bunker in pairs(g_currentMission.bunkerSilos) do
local x1,z1 = bunker.bunkerSiloArea.sx,bunker.bunkerSiloArea.sz
local x2,z2 = bunker.bunkerSiloArea.wx,bunker.bunkerSiloArea.wz
local x3,z3 = bunker.bunkerSiloArea.hx,bunker.bunkerSiloArea.hz
bunker.type = "silo"
if MathUtil.hasRectangleLineIntersection2D(x1,z1,x2-x1,z2-z1,x3-x1,z3-z1,x,z,tx-x,tz-z) then
return bunker
end
end
end
end
function BunkerSiloManager:getBestColumnToFill(siloMap)
local leastFillLevel = math.huge
local leastColumnIndex = 0
for columnIndex=2,#siloMap[1]-1 do
local currentFillLevel = 0
for lineIndex=1,#siloMap do
local fillUnit = siloMap[lineIndex][columnIndex]
currentFillLevel = currentFillLevel + fillUnit.fillLevel
--print(string.format("check:line %s, column %s fillLevel:%s",tostring(lineIndex),tostring(columnIndex),tostring(fillUnit.fillLevel)))
end
--print("column:"..tostring(columnIndex).." :"..tostring(currentFillLevel))
if currentFillLevel<leastFillLevel then
leastFillLevel = currentFillLevel
leastColumnIndex = columnIndex
end
end
return leastColumnIndex
end
function BunkerSiloManager:setOffsetsPerWayPoint(course,siloMap,bestColumn,ix)
local points = {}
local foundFirst = 0
for index=ix,course:getNumberOfWaypoints() do
if self:getTargetBunkerSiloByPointOnCourse(course,index)~= nil then
local closest,cx,cz = 0,0,0
local leastDistance = math.huge
for lineIndex=1,#siloMap do
local fillUnit= siloMap[lineIndex][bestColumn]
local x,z = fillUnit.cx,fillUnit.cz
local distance = course:getDistanceBetweenPointAndWaypoint(x,z, index)
if leastDistance > distance then
leastDistance = distance
closest = lineIndex
cx,cz = x,z
end
end
local y = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, cx, 1, cz);
course.waypoints[index].x = cx
course.waypoints[index].z = cz
--local offsetX,_,offsetZ = course:worldToWaypointLocal(index, cx, y, cz)
points[index]= true
--print(string.format("set %s new",tostring(index)))
if foundFirst == 0 then
foundFirst = index
end
elseif foundFirst ~= 0 then
break
end
end
return foundFirst
end