20 | function WorkArea.registerAreaType(name) |
21 | local key = "AREATYPE_"..string.upper(name); |
22 | if WorkArea[key] == nil then |
23 | if WorkArea.NUM_AREATYPES >= 64 then |
24 | print("Error: WorkArea.registerAreaType too many area types. Only 64 area types are supported"); |
25 | return; |
26 | end; |
27 | WorkArea.NUM_AREATYPES = WorkArea.NUM_AREATYPES+1; |
28 | WorkArea[key] = WorkArea.NUM_AREATYPES; |
29 | WorkArea.areaTypeNameToInt[name] = WorkArea.NUM_AREATYPES; |
30 | WorkArea.areaTypeIntToName[WorkArea.NUM_AREATYPES] = name; |
31 | |
32 | local desc = {}; |
33 | desc.name = name; |
34 | desc.index = WorkArea.NUM_AREATYPES; |
35 | end; |
36 | return WorkArea[key]; |
37 | end; |
52 | function WorkArea:preLoad(savegame) |
53 | self.loadWorkAreaFromXML = WorkArea.loadWorkAreaFromXML; |
54 | self.loadGroundReferenceNodeFromXML = WorkArea.loadGroundReferenceNodeFromXML; |
55 | self.getIsWorkAreaActive = WorkArea.getIsWorkAreaActive; |
56 | self.loadSpeedRotatingPartFromXML = Utils.overwrittenFunction(self.loadSpeedRotatingPartFromXML, WorkArea.loadSpeedRotatingPartFromXML); |
57 | self.getIsTypedWorkAreaActive = WorkArea.getIsTypedWorkAreaActive; |
58 | self.getTypedWorkAreas = WorkArea.getTypedWorkAreas; |
59 | self.getTypedNetworkAreas = WorkArea.getTypedNetworkAreas; |
60 | |
61 | self.updateGroundReferenceNode = SpecializationUtil.callSpecializationsFunction("updateGroundReferenceNode"); |
62 | end |
67 | function WorkArea:load(savegame) |
68 | |
69 | self.getIsSpeedRotatingPartActive = Utils.overwrittenFunction(self.getIsSpeedRotatingPartActive, WorkArea.getIsSpeedRotatingPartActive); |
70 | self.getPowerMultiplier = Utils.overwrittenFunction(self.getPowerMultiplier, WorkArea.getPowerMultiplier); |
71 | |
72 | if hasXMLProperty(self.xmlFile, "vehicle.contactReportNode") or hasXMLProperty(self.xmlFile, "vehicle.contactReportNode.contactReportNode") then |
73 | print("Warning: Contact report nodes are not supported anymore in "..self.configFileName..". Use vehicle.groundReferenceNodes.groundReferenceNode instead."); |
74 | end |
75 | |
76 | local totalCharge = 0; |
77 | self.groundReferenceNodes = {}; |
78 | local i = 0; |
79 | while true do |
80 | local key = string.format("vehicle.groundReferenceNodes.groundReferenceNode(%d)", i); |
81 | if not hasXMLProperty(self.xmlFile, key) then |
82 | break; |
83 | end; |
84 | local groundReferenceNode = {}; |
85 | if self:loadGroundReferenceNodeFromXML(groundReferenceNode, self.xmlFile, key) then |
86 | totalCharge = totalCharge + groundReferenceNode.chargeValue; |
87 | table.insert(self.groundReferenceNodes, groundReferenceNode); |
88 | end; |
89 | i = i + 1; |
90 | end; |
91 | |
92 | -- normalize chargeValues |
93 | for _, refNode in pairs(self.groundReferenceNodes) do |
94 | refNode.chargeValue = refNode.chargeValue / totalCharge; |
95 | end; |
96 | |
97 | self.workAreas = {}; |
98 | local i = 0; |
99 | while true do |
100 | local key = string.format("vehicle.workAreas.workArea(%d)", i); |
101 | if not hasXMLProperty(self.xmlFile, key) then |
102 | break; |
103 | end; |
104 | local workArea = {}; |
105 | if self:loadWorkAreaFromXML(workArea, self.xmlFile, key) then |
106 | table.insert(self.workAreas, workArea); |
107 | end; |
108 | i = i + 1; |
109 | end; |
110 | |
111 | if hasXMLProperty(self.xmlFile, "vehicle.cuttingAreas") then |
112 | print("Warning: cuttingAreas should not be used anymore in "..self.configFileName..". Use vehicle.workAreas.workArea instead!"); |
113 | end; |
114 | local numCuttingAreas = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.cuttingAreas#count"), 0); |
115 | for i=1, numCuttingAreas do |
116 | local key = string.format("vehicle.cuttingAreas.cuttingArea%d", i); |
117 | local workArea = {}; |
118 | if self:loadWorkAreaFromXML(workArea, self.xmlFile, key) then |
119 | table.insert(self.workAreas, workArea); |
120 | end; |
121 | end; |
122 | |
123 | self.workAreaByType = {}; |
124 | for _, area in pairs(self.workAreas) do |
125 | if self.workAreaByType[area.type] == nil then |
126 | self.workAreaByType[area.type] = {}; |
127 | end; |
128 | table.insert(self.workAreaByType[area.type], area); |
129 | end; |
130 | end; |
138 | function WorkArea:loadWorkAreaFromXML(workArea, xmlFile, key) |
139 | local start = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key .. "#startIndex")); |
140 | local width = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key .. "#widthIndex")); |
141 | local height = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key .. "#heightIndex")); |
142 | |
143 | if start ~= nil and width ~= nil and height ~= nil then |
144 | local refNodeIndex = getXMLInt(self.xmlFile, key .."#refNodeIndex"); |
145 | if refNodeIndex ~= nil then |
146 | if self.groundReferenceNodes[refNodeIndex+1] ~= nil then |
147 | workArea.refNode = self.groundReferenceNodes[refNodeIndex+1]; |
148 | else |
149 | print("Warning: Invalid GroundReferenceNode '"..refNodeIndex.."' ("..key..")! Indexing starts with 0"); |
150 | end; |
151 | else |
152 | if table.getn(self.groundReferenceNodes) == 1 then |
153 | workArea.refNode = self.groundReferenceNodes[1]; |
154 | end; |
155 | end; |
156 | |
157 | local areaTypeStr = getXMLString(self.xmlFile, key .."#type"); |
158 | if areaTypeStr == nil then |
159 | workArea.type = WorkArea.AREATYPE_DEFAULT; |
160 | else |
161 | local areaType = WorkArea.areaTypeNameToInt[areaTypeStr]; |
162 | assert(areaType ~= nil, "Invalid workarea-type '"..areaTypeStr.."' ("..key..")"); |
163 | workArea.type = areaType; |
164 | end; |
165 | |
166 | workArea.disableBackwards = Utils.getNoNil(getXMLBool(self.xmlFile, key .. "#disableBackwards"), true); |
167 | workArea.start = start; |
168 | workArea.width = width; |
169 | workArea.height = height; |
170 | return true; |
171 | end; |
172 | return false; |
173 | end; |
207 | function WorkArea:updateTick(dt) |
208 | if self:getIsActive() then |
209 | for _, refNode in pairs(self.groundReferenceNodes) do |
210 | local x,y,z = getWorldTranslation(refNode.node); |
211 | local densityHeight, deltaHeight = TipUtil.getHeightAtWorldPos(x,y,z); |
212 | self:updateGroundReferenceNode(refNode, x, y, z, densityHeight-deltaHeight, densityHeight); |
213 | end |
214 | end; |
215 | end; |
224 | function WorkArea:getIsWorkAreaActive(area) |
225 | local isActive = true; |
226 | |
227 | if area.refNode ~= nil then |
228 | isActive = isActive and area.refNode.isActive; |
229 | end; |
230 | |
231 | if area.disableBackwards then |
232 | isActive = isActive and self.movingDirection > 0; |
233 | |
234 | if self.cutterMovingDirection ~= nil then |
235 | if self.cutterMovingDirection > 0 then |
236 | if self.movingDirection < 0 then |
237 | isActive = false; |
238 | else |
239 | isActive = true; |
240 | end |
241 | elseif self.cutterMovingDirection < 0 then |
242 | if self.movingDirection > 0 then |
243 | isActive = false; |
244 | else |
245 | isActive = true; |
246 | end; |
247 | end; |
248 | end; |
249 | end; |
250 | |
251 | return isActive; |
252 | end; |
261 | function WorkArea:getTypedNetworkAreas(areaType, needsFieldProperty) |
262 | local workAreasSend = {}; |
263 | local area = 0; |
264 | local typedWorkAreas = self:getTypedWorkAreas(areaType); |
265 | local showFieldNotOwnedWarning = false; |
266 | for _, workArea in pairs(typedWorkAreas) do |
267 | if self:getIsWorkAreaActive(workArea) then |
268 | local x,_,z = getWorldTranslation(workArea.start); |
269 | if not needsFieldProperty or (needsFieldProperty and g_currentMission:getIsFieldOwnedAtWorldPos(x,z)) then |
270 | local x1,_,z1 = getWorldTranslation(workArea.width); |
271 | local x2,_,z2 = getWorldTranslation(workArea.height); |
272 | area = area + math.abs((z1-z)*(x2-x) - (x1-x)*(z2-z)); |
273 | table.insert(workAreasSend, {x,z,x1,z1,x2,z2}); |
274 | else |
275 | showFieldNotOwnedWarning = true; |
276 | end |
277 | end; |
278 | end; |
279 | return workAreasSend, showFieldNotOwnedWarning, area; |
280 | end; |
342 | function WorkArea:getIsSpeedRotatingPartActive(superFunc, speedRotatingPart) |
343 | if speedRotatingPart.groundRefNodeIndex ~= nil then |
344 | if self.groundReferenceNodes[speedRotatingPart.groundRefNodeIndex+1] ~= nil then |
345 | if not self.groundReferenceNodes[speedRotatingPart.groundRefNodeIndex+1].isActive then |
346 | return false; |
347 | end; |
348 | else |
349 | print("Warning: Invalid groundReferenceNode '"..speedRotatingPart.groundRefNodeIndex.."' in '"..self.configFileName.."'. Indexing starts with 0"); |
350 | speedRotatingPart.groundRefNodeIndex = nil; |
351 | end; |
352 | end; |
353 | |
354 | if superFunc ~= nil then |
355 | return superFunc(self, speedRotatingPart); |
356 | end |
357 | return true; |
358 | end; |