Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de
1 | -- |
2 | -- WorkArea |
3 | -- Class for all WorkAreas |
4 | -- |
5 | -- @author Manuel Leithner |
6 | -- @date 13/12/13 |
7 | -- |
8 | -- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved. |
9 | |
10 | WorkArea = {}; |
11 | |
12 | WorkArea.NUM_AREATYPES = 0; |
13 | WorkArea.areaTypeNameToInt = {} |
14 | WorkArea.areaTypeIntToName = {} |
15 | |
16 | function WorkArea.registerAreaType(name) |
17 | local key = "AREATYPE_"..string.upper(name); |
18 | if WorkArea[key] == nil then |
19 | if WorkArea.NUM_AREATYPES >= 64 then |
20 | print("Error: WorkArea.registerAreaType too many area types. Only 64 area types are supported"); |
21 | return; |
22 | end; |
23 | WorkArea.NUM_AREATYPES = WorkArea.NUM_AREATYPES+1; |
24 | WorkArea[key] = WorkArea.NUM_AREATYPES; |
25 | WorkArea.areaTypeNameToInt[name] = WorkArea.NUM_AREATYPES; |
26 | WorkArea.areaTypeIntToName[WorkArea.NUM_AREATYPES] = name; |
27 | |
28 | local desc = {}; |
29 | desc.name = name; |
30 | desc.index = WorkArea.NUM_AREATYPES; |
31 | end; |
32 | return WorkArea[key]; |
33 | end; |
34 | |
35 | function WorkArea.initSpecialization() |
36 | WorkArea.registerAreaType("default"); |
37 | end; |
38 | |
39 | function WorkArea.prerequisitesPresent(specializations) |
40 | return true; |
41 | end; |
42 | |
43 | function WorkArea:preLoad(xmlFile) |
44 | assert(self.loadWorkAreaFromXML == nil, "WorkArea needs to be the first specialization which implements loadWorkAreaFromXML"); |
45 | assert(self.loadGroundReferenceNodeFromXML == nil, "WorkArea needs to be the first specialization which implements loadGroundReferenceNodeFromXML"); |
46 | assert(self.getIsWorkAreaActive == nil, "WorkArea needs to be the first specialization which implements getIsWorkAreaActive"); |
47 | self.loadWorkAreaFromXML = WorkArea.loadWorkAreaFromXML; |
48 | self.loadGroundReferenceNodeFromXML = WorkArea.loadGroundReferenceNodeFromXML; |
49 | self.getIsWorkAreaActive = WorkArea.getIsWorkAreaActive; |
50 | self.loadSpeedRotatingPartFromXML = Utils.overwrittenFunction(self.loadSpeedRotatingPartFromXML, WorkArea.loadSpeedRotatingPartFromXML); |
51 | end |
52 | |
53 | function WorkArea:load(xmlFile) |
54 | |
55 | self.updateGroundReferenceNode = SpecializationUtil.callSpecializationsFunction("updateGroundReferenceNode"); |
56 | self.getIsTypedWorkAreaActive = WorkArea.getIsTypedWorkAreaActive; |
57 | self.getTypedWorkAreas = WorkArea.getTypedWorkAreas; |
58 | self.getTypedNetworkAreas = WorkArea.getTypedNetworkAreas; |
59 | self.getIsSpeedRotatingPartActive = Utils.overwrittenFunction(self.getIsSpeedRotatingPartActive, WorkArea.getIsSpeedRotatingPartActive); |
60 | self.getPowerMultiplier = Utils.overwrittenFunction(self.getPowerMultiplier, WorkArea.getPowerMultiplier); |
61 | |
62 | if hasXMLProperty(xmlFile, "vehicle.contactReportNode") or hasXMLProperty(xmlFile, "vehicle.contactReportNode.contactReportNode") then |
63 | print("Warning: Contact report nodes should not be used anymore in "..self.configFileName..". Use vehicle.groundReferenceNodes.groundReferenceNode instead."); |
64 | end |
65 | |
66 | local totalCharge = 0; |
67 | self.groundReferenceNodes = {}; |
68 | local i = 0; |
69 | while true do |
70 | local key = string.format("vehicle.groundReferenceNodes.groundReferenceNode(%d)", i); |
71 | if not hasXMLProperty(xmlFile, key) then |
72 | break; |
73 | end; |
74 | local groundReferenceNode = {}; |
75 | if self:loadGroundReferenceNodeFromXML(groundReferenceNode, xmlFile, key) then |
76 | totalCharge = totalCharge + groundReferenceNode.chargeValue; |
77 | table.insert(self.groundReferenceNodes, groundReferenceNode); |
78 | end; |
79 | i = i + 1; |
80 | end; |
81 | |
82 | if next(self.groundReferenceNodes) == nil then |
83 | local groundReferenceNode = {}; |
84 | if self:loadGroundReferenceNodeFromXML(groundReferenceNode, xmlFile, "vehicle.groundReferenceNode") then |
85 | totalCharge = totalCharge + groundReferenceNode.chargeValue; |
86 | table.insert(self.groundReferenceNodes, groundReferenceNode); |
87 | print("Warning: Using deprecated 'groundReferenceNode' in "..self.configFileName..". Use vehicle.groundReferenceNodes.groundReferenceNode instead!"); |
88 | end; |
89 | end |
90 | |
91 | -- normalize chargeValues |
92 | for _, refNode in pairs(self.groundReferenceNodes) do |
93 | refNode.chargeValue = refNode.chargeValue / totalCharge; |
94 | end; |
95 | |
96 | self.workAreas = {}; |
97 | local i = 0; |
98 | while true do |
99 | local key = string.format("vehicle.workAreas.workArea(%d)", i); |
100 | if not hasXMLProperty(xmlFile, key) then |
101 | break; |
102 | end; |
103 | local workArea = {}; |
104 | if self:loadWorkAreaFromXML(workArea, xmlFile, key) then |
105 | table.insert(self.workAreas, workArea); |
106 | end; |
107 | i = i + 1; |
108 | end; |
109 | |
110 | if hasXMLProperty(xmlFile, "vehicle.cuttingAreas") then |
111 | print("Warning: cuttingAreas should not be used anymore in "..self.configFileName..". Use vehicle.workAreas.workArea instead!"); |
112 | end; |
113 | local numCuttingAreas = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.cuttingAreas#count"), 0); |
114 | for i=1, numCuttingAreas do |
115 | local key = string.format("vehicle.cuttingAreas.cuttingArea%d", i); |
116 | local workArea = {}; |
117 | if self:loadWorkAreaFromXML(workArea, xmlFile, key) then |
118 | table.insert(self.workAreas, workArea); |
119 | end; |
120 | end; |
121 | |
122 | self.workAreaByType = {}; |
123 | for _, area in pairs(self.workAreas) do |
124 | if self.workAreaByType[area.type] == nil then |
125 | self.workAreaByType[area.type] = {}; |
126 | end; |
127 | table.insert(self.workAreaByType[area.type], area); |
128 | end; |
129 | end; |
130 | |
131 | function WorkArea:loadWorkAreaFromXML(workArea, xmlFile, key) |
132 | local start = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#startIndex")); |
133 | local width = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#widthIndex")); |
134 | local height = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#heightIndex")); |
135 | |
136 | if start ~= nil and width ~= nil and height ~= nil then |
137 | local refNodeIndex = getXMLInt(xmlFile, key .."#refNodeIndex"); |
138 | if refNodeIndex ~= nil then |
139 | if self.groundReferenceNodes[refNodeIndex+1] ~= nil then |
140 | workArea.refNode = self.groundReferenceNodes[refNodeIndex+1]; |
141 | else |
142 | print("Warning: Invalid GroundReferenceNode '"..refNodeIndex.."' ("..key..")! Indexing starts with 0"); |
143 | end; |
144 | else |
145 | if table.getn(self.groundReferenceNodes) == 1 then |
146 | workArea.refNode = self.groundReferenceNodes[1]; |
147 | end; |
148 | end; |
149 | |
150 | local areaTypeStr = getXMLString(xmlFile, key .."#type"); |
151 | if areaTypeStr == nil then |
152 | workArea.type = WorkArea.AREATYPE_DEFAULT; |
153 | else |
154 | local areaType = WorkArea.areaTypeNameToInt[areaTypeStr]; |
155 | assert(areaType ~= nil, "Invalid workarea-type '"..areaTypeStr.."' ("..key..")"); |
156 | workArea.type = areaType; |
157 | end; |
158 | |
159 | workArea.disableBackwards = Utils.getNoNil(getXMLBool(xmlFile, key .. "#disableBackwards"), true); |
160 | workArea.start = start; |
161 | workArea.width = width; |
162 | workArea.height = height; |
163 | return true; |
164 | end; |
165 | return false; |
166 | end; |
167 | |
168 | function WorkArea:loadGroundReferenceNodeFromXML(groundReferenceNode, xmlFile, key) |
169 | local node = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#index")); |
170 | if node ~= nil then |
171 | groundReferenceNode.node = node; |
172 | groundReferenceNode.threshold = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#threshold"), 0); |
173 | groundReferenceNode.chargeValue = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#chargeValue"), 1); |
174 | return true; |
175 | end; |
176 | return false; |
177 | end; |
178 | |
179 | function WorkArea:delete() |
180 | end; |
181 | |
182 | function WorkArea:mouseEvent(posX, posY, isDown, isUp, button) |
183 | end; |
184 | |
185 | function WorkArea:keyEvent(unicode, sym, modifier, isDown) |
186 | end; |
187 | |
188 | function WorkArea:update(dt) |
189 | end; |
190 | |
191 | function WorkArea:updateTick(dt) |
192 | if self:getIsActive() then |
193 | for _, refNode in pairs(self.groundReferenceNodes) do |
194 | local x,y,z = getWorldTranslation(refNode.node); |
195 | local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, y, z); |
196 | self:updateGroundReferenceNode(refNode, x, y, z, terrainHeight); |
197 | end |
198 | end; |
199 | end; |
200 | |
201 | function WorkArea:draw() |
202 | end; |
203 | |
204 | function WorkArea:getIsWorkAreaActive(area) |
205 | local isActive = true; |
206 | |
207 | if area.refNode ~= nil then |
208 | isActive = isActive and area.refNode.isActive; |
209 | end; |
210 | |
211 | if area.disableBackwards then |
212 | isActive = isActive and self.movingDirection > 0; |
213 | |
214 | if self.cutterMovingDirection ~= nil then |
215 | if self.cutterMovingDirection > 0 then |
216 | if self.movingDirection < 0 then |
217 | isActive = false; |
218 | else |
219 | isActive = true; |
220 | end |
221 | elseif self.cutterMovingDirection < 0 then |
222 | if self.movingDirection > 0 then |
223 | isActive = false; |
224 | else |
225 | isActive = true; |
226 | end; |
227 | end; |
228 | end; |
229 | end; |
230 | |
231 | return isActive; |
232 | end; |
233 | |
234 | function WorkArea:getTypedNetworkAreas(areaType, needsFieldProperty) |
235 | local workAreasSend = {}; |
236 | local area = 0; |
237 | local typedWorkAreas = self:getTypedWorkAreas(areaType); |
238 | local showFieldNotOwnedWarning = false; |
239 | for _, workArea in pairs(typedWorkAreas) do |
240 | if self:getIsWorkAreaActive(workArea) then |
241 | local x,_,z = getWorldTranslation(workArea.start); |
242 | if not needsFieldProperty or (needsFieldProperty and g_currentMission:getIsFieldOwnedAtWorldPos(x,z)) then |
243 | local x1,_,z1 = getWorldTranslation(workArea.width); |
244 | local x2,_,z2 = getWorldTranslation(workArea.height); |
245 | area = area + math.abs((z1-z)*(x2-x) - (x1-x)*(z2-z)); |
246 | table.insert(workAreasSend, {x,z,x1,z1,x2,z2}); |
247 | else |
248 | showFieldNotOwnedWarning = true; |
249 | end |
250 | end; |
251 | end; |
252 | return workAreasSend, showFieldNotOwnedWarning, area; |
253 | end; |
254 | |
255 | function WorkArea:getTypedWorkAreas(areaType) |
256 | return Utils.getNoNil(self.workAreaByType[areaType], {}); |
257 | end; |
258 | |
259 | function WorkArea:getIsTypedWorkAreaActive(areaType) |
260 | local isActive = false; |
261 | local typedWorkAreas = self:getTypedWorkAreas(areaType); |
262 | for _, workArea in pairs(typedWorkAreas) do |
263 | if self:getIsWorkAreaActive(workArea) then |
264 | isActive = true; |
265 | break; |
266 | end; |
267 | end |
268 | |
269 | return isActive, typedWorkAreas; |
270 | end; |
271 | |
272 | function WorkArea:updateGroundReferenceNode(groundReferenceNode, x, y, z, terrainHeight) |
273 | groundReferenceNode.isActive = (terrainHeight + groundReferenceNode.threshold) >= y; |
274 | end; |
275 | |
276 | function WorkArea:loadSpeedRotatingPartFromXML(superFunc, speedRotatingPart, xmlFile, key) |
277 | if superFunc ~= nil then |
278 | if not superFunc(self, speedRotatingPart, xmlFile, key) then |
279 | return false; |
280 | end |
281 | end; |
282 | |
283 | speedRotatingPart.groundRefNodeIndex = getXMLInt(xmlFile, key.."#refNodeIndex"); |
284 | |
285 | return true; |
286 | end |
287 | |
288 | function WorkArea:getIsSpeedRotatingPartActive(superFunc, speedRotatingPart) |
289 | if speedRotatingPart.groundRefNodeIndex ~= nil then |
290 | if self.groundReferenceNodes[speedRotatingPart.groundRefNodeIndex+1] ~= nil then |
291 | if not self.groundReferenceNodes[speedRotatingPart.groundRefNodeIndex+1].isActive then |
292 | return false; |
293 | end; |
294 | else |
295 | print("Warning: Invalid groundReferenceNode '"..speedRotatingPart.groundRefNodeIndex.."' in '"..self.configFileName.."'. Indexing starts with 0"); |
296 | speedRotatingPart.groundRefNodeIndex = nil; |
297 | end; |
298 | end; |
299 | |
300 | if superFunc ~= nil then |
301 | return superFunc(self, speedRotatingPart); |
302 | end |
303 | return true; |
304 | end; |
305 | |
306 | function WorkArea:getPowerMultiplier(superFunc) |
307 | local powerMultiplier = 1; |
308 | if superFunc ~= nil then |
309 | powerMultiplier = superFunc(self); |
310 | end |
311 | if #self.groundReferenceNodes > 0 then |
312 | local chargeValue = 0; |
313 | for _, refNode in pairs(self.groundReferenceNodes) do |
314 | if refNode.isActive then |
315 | chargeValue = refNode.chargeValue; |
316 | end; |
317 | end; |
318 | powerMultiplier = powerMultiplier * chargeValue; |
319 | end; |
320 | return powerMultiplier; |
321 | end;
|
Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de