50 | function Cutter:load(savegame) |
51 | |
52 | self.processCutterAreas = Cutter.processCutterAreas |
53 | self.getDoConsumePtoPower = Utils.overwrittenFunction(self.getDoConsumePtoPower, Cutter.getDoConsumePtoPower) |
54 | |
55 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.reel#index", "vehicle.turnedOnRotationNodes.turnedOnRotationNode (type: cutter)") |
56 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.reelspikes#count", "vehicle.cutter.reelspikes#count") |
57 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.reelspikes#index", "vehicle.cutter.reelspikes#index") |
58 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.reelspikes.spike", "vehicle.cutter.reelspikes.spike") |
59 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.fruitExtraObjects.fruitExtraObject", "vehicle.cutter.fruitExtraObjects.fruitExtraObject") |
60 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.reelspikes#turnedOnRotNodeRef", "vehicle.cutter.reelspikes#turnedOnRotNodeRef") |
61 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cutterThreshingUVScrollParts", "vehicle.cutter.turnedOnScrollers.turnedOnScroller") |
62 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cutterTurnedOnScrollers.cutterTurnedOnScroller", "vehicle.cutter.turnedOnScrollers.turnedOnScroller") |
63 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.rolls", "vehicle.turnedOnRotationNodes.turnedOnRotationNode (type: cutter)") |
64 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cutterSpeedRotatingParts", "vehicle.speedRotatingParts.speedRotatingPart") |
65 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cutterSpeedLimit", nil) |
66 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cutterFruitTypes#fruitTypes", "vehicle.cutter#fruitTypes") |
67 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cutterFruitTypes#fruitTypeCategories", "vehicle.cutter#fruitTypeCategories") |
68 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cutterFruitTypes#useWindrowed", "vehicle.cutter#useWindrowed") |
69 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.convertedFillTypes#category", "vehicle.cutter#convertedFillTypeCategories") |
70 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cutterStartAnimation#name", "vehicle.cutter#startAnimationName") |
71 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cutterStartAnimation#speedScale", "vehicle.cutter#startAnimationSpeedScale") |
72 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cutterStartAnimation#initialIsStarted", "vehicle.cutter#startAnimationInitialIsStarted") |
73 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cutterEffects#baseNode", "vehicle.cutter.effect#baseNode") |
74 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cutterEffect", "vehicle.cutter.effect") |
75 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cutterParticleSystems.emitterShape", "vehicle.cutter.particleSystems.emitterShape") |
76 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cutterTestAreas.cutterTestArea", "vehicle.cutter.testAreas.testArea") |
77 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cutterAllowCuttingWhileRaised", "vehicle.cutter#allowsForageGrowhtState") |
78 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cutterMovingDirection", "vehicle.cutter#movingDirection") |
79 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.threshingParticleSystem", "vehicle.cutter.threshingParticleSystems.threshingParticleSystem") |
80 | |
81 | local fruitTypes = nil |
82 | local fruitTypeNames = getXMLString(self.xmlFile, "vehicle.cutter#fruitTypes") |
83 | local fruitTypeCategories = getXMLString(self.xmlFile, "vehicle.cutter#fruitTypeCategories") |
84 | if fruitTypeCategories ~= nil and fruitTypeNames == nil then |
85 | fruitTypes = FruitUtil.getFruitTypeByCategoryName(fruitTypeCategories, "Warning ("..self.configFileName.."): Cutter has invalid fruitTypeCategory '%s'.") |
86 | elseif fruitTypeCategories == nil and fruitTypeNames ~= nil then |
87 | fruitTypes = FruitUtil.getFruitTypesByNames(fruitTypeNames, "Warning ("..self.configFileName.."): Cutter has invalid fruitType '%s'.") |
88 | else |
89 | print("Warning ("..self.configFileName.."): Cutter needs either the 'cutterFruitTypes#fruitTypeCategories' or 'cutterFruitTypes#fruitTypes' attribute.") |
90 | end |
91 | |
92 | self.fruitTypes = {} |
93 | if fruitTypes ~= nil then |
94 | for _,fruitType in pairs(fruitTypes) do |
95 | self.fruitTypes[fruitType] = true |
96 | end |
97 | end |
98 | |
99 | self.fruitTypesUseWindrowed = getXMLBool(self.xmlFile, "vehicle.cutter#useWindrowed") |
100 | self.windrowFillTypes = {} |
101 | if self.fruitTypesUseWindrowed then |
102 | for fruitType, state in pairs(self.fruitTypes) do |
103 | local windrowFillType = FruitUtil.fruitTypeToWindrowFillType[fruitType] |
104 | self.windrowFillTypes[windrowFillType] = true |
105 | end |
106 | end |
107 | |
108 | |
109 | self.fillTypeConverters = {} |
110 | local category = getXMLString(self.xmlFile, "vehicle.cutter#convertedFillTypeCategories") |
111 | if category ~= nil then |
112 | local converter = FruitUtil.converterNameToInt[category] |
113 | if converter ~= nil and FruitUtil.converterToFillTypes[converter] ~= nil then |
114 | for input, converter in pairs(FruitUtil.converterToFillTypes[converter]) do |
115 | self.fillTypeConverters[input] = converter |
116 | end |
117 | end |
118 | end |
119 | |
120 | if self.isClient then |
121 | self.cutterTurnedOnRotationNodes = Utils.loadRotationNodes(self.xmlFile, {}, "vehicle.turnedOnRotationNodes.turnedOnRotationNode", "cutter", self.components) |
122 | self.cutterTurnedOnScrollers = Utils.loadScrollers(self.components, self.xmlFile, "vehicle.cutter.turnedOnScrollers.turnedOnScroller", {}, false) |
123 | |
124 | self.spikesCount = getXMLInt(self.xmlFile, "vehicle.cutter.reelspikes#count") |
125 | local indexSpikesStr = getXMLString(self.xmlFile, "vehicle.cutter.reelspikes#index") |
126 | self.spikesRootNode = Utils.indexToObject(self.components, indexSpikesStr) |
127 | |
128 | self.spikeAnimNodes = {} |
129 | local i = 0 |
130 | while true do |
131 | local key = string.format("vehicle.cutter.reelspikes.spike(%d)", i) |
132 | if not hasXMLProperty(self.xmlFile, key) then |
133 | break |
134 | end |
135 | |
136 | local node = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key.."#node")) |
137 | local animCurve = AnimCurve:new(linearInterpolator1) |
138 | local keyI = 0 |
139 | while true do |
140 | local animKey = key .. string.format(".key(%d)", keyI) |
141 | if not hasXMLProperty(self.xmlFile, animKey) then |
142 | break |
143 | end |
144 | local keyTime = getXMLFloat(self.xmlFile, animKey.."#time") |
145 | local xRot = math.rad(Utils.getNoNil(getXMLFloat(self.xmlFile, animKey.."#rotX"), 0)) |
146 | |
147 | animCurve:addKeyframe({v=xRot, time=keyTime}) |
148 | keyI = keyI +1 |
149 | end |
150 | table.insert(self.spikeAnimNodes, {node=node, animCurve = animCurve}) |
151 | i = i + 1 |
152 | end |
153 | |
154 | if table.getn(self.spikeAnimNodes) == 0 then |
155 | self.spikeAnimNodes = nil |
156 | end |
157 | |
158 | local turnedOnRotNodeRef = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.cutter.reelspikes#turnedOnRotNodeRef"), 1) |
159 | if self.cutterTurnedOnRotationNodes.nodes[turnedOnRotNodeRef] == nil and (self.spikesRootNode ~= nil or self.spikeAnimNodes ~= nil) then |
160 | print("Warning ("..self.configFileName.."): No 'turnedOnRotNodeRef' defined for reelspikes in '"..self.configFileName.."'") |
161 | self.spikesRootNode = nil |
162 | self.spikeAnimNodes = nil |
163 | else |
164 | self.spikesRef = self.cutterTurnedOnRotationNodes.nodes[turnedOnRotNodeRef] |
165 | end |
166 | |
167 | self.fruitExtraObjects = {} |
168 | local i = 0 |
169 | while true do |
170 | local key = string.format("vehicle.cutter.fruitExtraObjects.fruitExtraObject(%d)", i) |
171 | local t = getXMLString(self.xmlFile, key.."#fruitType") |
172 | local index = getXMLString(self.xmlFile, key.."#index") |
173 | local anim = getXMLString(self.xmlFile, key.."#anim") |
174 | if t==nil or (index==nil and anim==nil) then |
175 | break |
176 | end |
177 | |
178 | local node = Utils.indexToObject(self.components, index) |
179 | if node ~= nil then |
180 | setVisibility(node, false) |
181 | end |
182 | self.fruitExtraObjects[t] = {node=node, anim=anim} |
183 | i = i +1 |
184 | end |
185 | |
186 | self.cutterStartAnimation = getXMLString(self.xmlFile, "vehicle.cutter#startAnimationName") |
187 | self.cutterStartAnimationSpeedScale = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.cutter#startAnimationSpeedScale"), 1) |
188 | self.cutterStartAnimationInitialIsStarted = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.cutter#startAnimationInitialIsStarted"), false) |
189 | |
190 | self.threshingParticleSystems = {} |
191 | local i = 0 |
192 | while true do |
193 | local keyPS = string.format("vehicle.cutter.threshingParticleSystems.threshingParticleSystem(%d)", i) |
194 | if not hasXMLProperty(self.xmlFile, keyPS) then |
195 | break |
196 | end |
197 | local currentPS = {} |
198 | ParticleUtil.loadParticleSystem(self.xmlFile, currentPS, keyPS, self.components, false, nil, self.baseDirectory) |
199 | table.insert(self.threshingParticleSystems, currentPS) |
200 | i = i + 1 |
201 | end |
202 | |
203 | local i = 0 |
204 | while true do |
205 | local key = string.format("vehicle.cutter.threshingParticleSystems.emitterShape(%d)", i) |
206 | if not hasXMLProperty(self.xmlFile, key) then |
207 | break |
208 | end |
209 | |
210 | local emitterShape = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key.."#node")) |
211 | local particleType = getXMLString(self.xmlFile, key.."#particleType") |
212 | if emitterShape ~= nil then |
213 | local fillType = FillUtil.FILLTYPE_UNKNOWN |
214 | local fillTypeStr = getXMLString(self.xmlFile, key.."#fillType") |
215 | if fillTypeStr ~= nil and FillUtil.fillTypeNameToInt[fillTypeStr] ~= nil then |
216 | fillType = FillUtil.fillTypeNameToInt[fillTypeStr] |
217 | end |
218 | |
219 | local particleSystem = MaterialUtil.getParticleSystem(fillType, particleType) |
220 | if particleSystem ~= nil then |
221 | table.insert(self.threshingParticleSystems, ParticleUtil.copyParticleSystem(self.xmlFile, key, particleSystem, emitterShape)) |
222 | end |
223 | end |
224 | i = i + 1 |
225 | end |
226 | |
227 | self.cutterFillEffects = EffectManager:loadEffect(self.xmlFile, "vehicle.cutter.fillEffect", self.components, self) |
228 | |
229 | self.cutterFillParticleSystems = {} |
230 | self.currentCutterFillParticleSystem = nil |
231 | local i = 0 |
232 | while true do |
233 | local key = string.format("vehicle.cutter.fillParticleSystems.emitterShape(%d)", i) |
234 | if not hasXMLProperty(self.xmlFile, key) then |
235 | break |
236 | end |
237 | |
238 | local emitterShape = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key.."#node")) |
239 | local particleType = getXMLString(self.xmlFile, key.."#particleType") |
240 | if emitterShape ~= nil then |
241 | for fruitTypeIndex,_ in pairs(self.fruitTypes) do |
242 | local fillType = FruitUtil.fruitTypeToFillType[fruitTypeIndex] |
243 | |
244 | if self.fruitTypesUseWindrowed then |
245 | fillType = FruitUtil.fruitTypeToWindrowFillType[fillType] |
246 | end |
247 | local particleSystem = MaterialUtil.getParticleSystem(fillType, particleType) |
248 | if particleSystem ~= nil then |
249 | if self.cutterFillParticleSystems[fillType] == nil then |
250 | self.cutterFillParticleSystems[fillType] = {} |
251 | end |
252 | table.insert(self.cutterFillParticleSystems[fillType], ParticleUtil.copyParticleSystem(self.xmlFile, key, particleSystem, emitterShape)) |
253 | end |
254 | end |
255 | end |
256 | i = i + 1 |
257 | end |
258 | |
259 | self.cutterEffectBaseNode = Utils.getNoNil(Utils.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.cutter.effect#baseNode")), self.rootNode) |
260 | self.cutterEffects = {} |
261 | self.currentCutterEffect = nil |
262 | if hasXMLProperty(self.xmlFile, "vehicle.cutter.effect") then |
263 | for fruitTypeIndex,_ in pairs(self.fruitTypes) do |
264 | self.cutterEffects[fruitTypeIndex] = {} |
265 | local i = 0 |
266 | while true do |
267 | local key = string.format("vehicle.cutter.effect.effectNode(%d)", i) |
268 | if not hasXMLProperty(self.xmlFile, key) then |
269 | break |
270 | end |
271 | local effect = CutterEffect:new() |
272 | effect:load(self.xmlFile, key, self.components, self, fruitTypeIndex) |
273 | table.insert(self.cutterEffects[fruitTypeIndex], effect) |
274 | i = i + 1 |
275 | end |
276 | end |
277 | end |
278 | |
279 | self.cutterParticleSystems = {} |
280 | local i = 0 |
281 | while true do |
282 | local key = string.format("vehicle.cutter.particleSystems.emitterShape(%d)", i) |
283 | if not hasXMLProperty(self.xmlFile, key) then |
284 | break |
285 | end |
286 | |
287 | local emitterShape = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key.."#node")) |
288 | local particleType = getXMLString(self.xmlFile, key.."#particleType") |
289 | if emitterShape ~= nil then |
290 | for fruitTypeIndex,_ in pairs(self.fruitTypes) do |
291 | local fillType = FruitUtil.fruitTypeToFillType[fruitTypeIndex] |
292 | local particleSystem = MaterialUtil.getParticleSystem(fillType, particleType) |
293 | if particleSystem ~= nil then |
294 | self.cutterParticleSystems[fillType] = ParticleUtil.copyParticleSystem(self.xmlFile, key, particleSystem, emitterShape) |
295 | end |
296 | end |
297 | end |
298 | i = i + 1 |
299 | end |
300 | |
301 | self.cutterTestAreas = {} |
302 | local i = 0 |
303 | while true do |
304 | local key = string.format("vehicle.cutter.testAreas.testArea(%d)", i) |
305 | if not hasXMLProperty(self.xmlFile, key) then |
306 | break |
307 | end |
308 | local testArea = {} |
309 | if self:loadTestAreaFromXML(testArea, self.xmlFile, key) then |
310 | table.insert(self.cutterTestAreas, testArea) |
311 | end |
312 | i = i + 1 |
313 | end |
314 | end |
315 | |
316 | self.allowsForageGrowhtState = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.cutter#allowsForageGrowhtState"), false) |
317 | self.cutterAllowCuttingWhileRaised = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.cutter#allowCuttingWhileRaised"), false) |
318 | self.cutterMovingDirection = Utils.sign(Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.cutter#movingDirection"), 1)) |
319 | self.currentInputFruitType = FruitUtil.FRUITTYPE_UNKNOWN |
320 | self.reelStarted = false |
321 | self.isCutterSpeedLimitActive = false |
322 | |
323 | self.showFieldNotOwnedWarning = false |
324 | |
325 | self.fillEffectTimer = 0 |
326 | self.lastCutterArea = 0 |
327 | self.lastCutterAreaBiggerZero = self.lastCutterArea > 0 |
328 | self.lastCutterAreaBiggerZeroTime = -1 |
329 | self.cutterGroundFlag = self:getNextDirtyFlag() |
330 | end |
450 | function Cutter:updateTick(dt) |
451 | self.isCutterSpeedLimitActive = false |
452 | if self.isServer then |
453 | self.lastCutterArea = 0 |
454 | self.lastCutterAreaBiggerZero = false |
455 | end |
456 | |
457 | local showFieldNotOwnedWarning = false |
458 | |
459 | if self.reelStarted and self.movingDirection == self.cutterMovingDirection and (self.cutterAllowCuttingWhileRaised or self:isLowered(true)) then |
460 | if self.isClient then |
461 | local minEffectValue = math.huge |
462 | local maxEffectValue = -math.huge |
463 | for k, testArea in pairs(self.cutterTestAreas) do |
464 | local x,y,z = getWorldTranslation(testArea.start) |
465 | local x1,y1,z1 = getWorldTranslation(testArea.width) |
466 | local x2,_,z2 = getWorldTranslation(testArea.height) |
467 | |
468 | if self.isServer and self:getLastSpeed() > 0.5 and self.currentInputFruitType ~= nil then |
469 | if self:getIsTestAreaActive(testArea) then |
470 | local fruitValue, _, growthState = Utils.getFruitArea(self.currentInputFruitType, x, z, x1, z1, x2, z2, nil, self.allowsForageGrowhtState) |
471 | testArea.hasFruitContact = fruitValue > 0 |
472 | if fruitValue > 0 then |
473 | self.currentInputFruitTypeGrowthState = growthState; |
474 | end; |
475 | end |
476 | end |
477 | |
478 | if testArea.hasFruitContact then |
479 | local lx1,_,_ = worldToLocal(self.cutterEffectBaseNode, x,y,z) |
480 | local lx2,_,_ = worldToLocal(self.cutterEffectBaseNode, x1,y1,z1) |
481 | minEffectValue = math.min(minEffectValue, lx1, lx2) |
482 | maxEffectValue = math.max(maxEffectValue, lx1, lx2) |
483 | end |
484 | end |
485 | |
486 | local reset = false |
487 | if minEffectValue == math.huge and maxEffectValue == -math.huge then |
488 | minEffectValue = 0 |
489 | maxEffectValue = 0 |
490 | reset = true |
491 | end |
492 | if self.cutterMovingDirection > 0 then |
493 | minEffectValue = minEffectValue * -1 |
494 | maxEffectValue = maxEffectValue * -1 |
495 | if maxEffectValue < minEffectValue then |
496 | local t = minEffectValue |
497 | minEffectValue = maxEffectValue |
498 | maxEffectValue = t |
499 | end |
500 | end |
501 | |
502 | if self.currentInputFruitType ~= nil then |
503 | local newEffect = self.cutterEffects[self.currentInputFruitType] |
504 | if newEffect ~= nil then |
505 | if self.currentCutterEffect ~= newEffect then |
506 | EffectManager:resetEffects(self.currentCutterEffect) |
507 | end |
508 | self.currentCutterEffect = newEffect |
509 | for _, effect in pairs(self.currentCutterEffect) do |
510 | if effect.setGrowthState ~= nil then |
511 | effect:setGrowthState(self.currentInputFruitTypeGrowthState) |
512 | end |
513 | if effect.setMinMax ~= nil then |
514 | effect:setMinMax(minEffectValue, maxEffectValue, reset) |
515 | end |
516 | end |
517 | else |
518 | if self.currentCutterEffect ~= nil then |
519 | EffectManager:resetEffects(self.currentCutterEffect) |
520 | end |
521 | end |
522 | |
523 | local particle = self.cutterParticleSystems[self.currentInputFruitType] |
524 | if particle ~= self.currentCutterParticles and self.currentCutterParticles ~= nil then |
525 | ParticleUtil.setEmittingState(self.currentCutterParticles, false) |
526 | end |
527 | |
528 | self.currentCutterParticles = particle |
529 | if self.currentCutterParticles ~= nil then |
530 | local widthX = math.abs(minEffectValue-maxEffectValue) |
531 | |
532 | ParticleUtil.setEmittingState(self.currentCutterParticles, widthX > 0) |
533 | if self.currentCutterParticles.emitterShape ~= nil and self.currentCutterParticles.emitterShape ~= 0 then |
534 | local sx,sy,sz = getScale(self.currentCutterParticles.emitterShape) |
535 | setScale(self.currentCutterParticles.emitterShape, widthX, sy, sz) |
536 | local _,y,z = getTranslation(self.currentCutterParticles.emitterShape) |
537 | setTranslation(self.currentCutterParticles.emitterShape, -(minEffectValue+(widthX/2)), y,z) |
538 | end |
539 | ParticleUtil.setEmitCountScale(self.currentCutterParticles, widthX) |
540 | end |
541 | end |
542 | end |
543 | |
544 | self.isCutterSpeedLimitActive = true |
545 | |
546 | local oldInputFruitType = self.currentInputFruitType |
547 | if self.isServer then |
548 | local combine = self:getCombine() |
549 | if combine ~= nil and combine:getIsThreshingAllowed(false) and combine.allowsThreshing then |
550 | local workAreas, showWarning, _ = self:getTypedNetworkAreas(WorkArea.AREATYPE_CUTTER, true) |
551 | showFieldNotOwnedWarning = showWarning |
552 | |
553 | if (table.getn(workAreas) > 0) then |
554 | local fruitTypesToUse = self.fruitTypes; |
555 | if combine.aiIsStarted then |
556 | if self.currentInputFruitType ~= FruitUtil.FRUITTYPE_UNKNOWN then |
557 | fruitTypesToUse = {}; |
558 | fruitTypesToUse[self.currentInputFruitType] = true; |
559 | end |
560 | end |
561 | |
562 | for fruitType,_ in pairs(fruitTypesToUse) do |
563 | |
564 | local usedFruitType = fruitType |
565 | local outputFillType = FruitUtil.fruitTypeToFillType[usedFruitType] |
566 | |
567 | local conversionFactor = 1.0 |
568 | if self.fillTypeConverters[usedFruitType] ~= nil then |
569 | outputFillType = self.fillTypeConverters[usedFruitType].fillTypeTarget |
570 | conversionFactor = self.fillTypeConverters[usedFruitType].conversionFactor |
571 | end |
572 | |
573 | if combine:allowFillType(outputFillType, false) then |
574 | local lastCutterArea = 0 |
575 | local lastRealArea = 0 |
576 | local lastGrowthState = nil |
577 | |
578 | if self.fruitTypesUseWindrowed then |
579 | local totalArea, actualFruitType = ForageWagon.processForageWagonAreas(self, workAreas, self.windrowFillTypes, false, usedFruitType) |
580 | lastCutterArea = totalArea |
581 | lastRealArea = totalArea |
582 | |
583 | |
584 | usedFruitType = actualFruitType |
585 | if self.fillTypeConverters[usedFruitType] ~= nil then |
586 | outputFillType = self.fillTypeConverters[usedFruitType].fillTypeTarget |
587 | conversionFactor = self.fillTypeConverters[usedFruitType].windrowConversionFactor |
588 | end |
589 | else |
590 | local cutterArea, realArea, growthState = self:processCutterAreas(workAreas, usedFruitType) |
591 | lastCutterArea = cutterArea |
592 | lastRealArea = realArea |
593 | lastGrowthState = growthState |
594 | end |
595 | |
596 | if lastCutterArea > 0 then |
597 | self.lastCutterArea = lastCutterArea |
598 | self.lastCutterAreaBiggerZero = (self.lastCutterArea > 0) |
599 | if self.lastCutterAreaBiggerZero then |
600 | self.lastCutterAreaBiggerZeroTime = g_currentMission.time |
601 | end |
602 | lastCutterArea = lastCutterArea * conversionFactor |
603 | combine:addCutterArea(self, lastCutterArea, lastRealArea, usedFruitType, outputFillType) |
604 | |
605 | self.currentInputFruitType = usedFruitType |
606 | self.currentInputFruitTypeGrowthState = lastGrowthState |
607 | |
608 | if self.lastCutterAreaBiggerZero ~= self.lastCutterAreaBiggerZeroSent then |
609 | self:raiseDirtyFlags(self.cutterGroundFlag) |
610 | self.lastCutterAreaBiggerZeroSent = self.lastCutterAreaBiggerZero |
611 | end |
612 | |
613 | local ha = Utils.areaToHa(lastRealArea, g_currentMission:getFruitPixelsToSqm()) -- 4096px are mapped to 2048m |
614 | g_currentMission.missionStats:updateStats("threshedHectares", ha) |
615 | g_currentMission.missionStats:updateStats("workedHectares", ha) |
616 | |
617 | -- Stop the loop over all fruit types |
618 | break |
619 | end |
620 | end |
621 | end |
622 | end |
623 | end |
624 | |
625 | else |
626 | local combine = self:getCombine() |
627 | if combine ~= nil and combine.lastValidInputFruitType ~= FruitUtil.FRUITTYPE_UNKNOWN then |
628 | self.currentInputFruitType = combine.lastValidInputFruitType |
629 | end |
630 | end |
631 | |
632 | if self.currentInputFruitType ~= oldInputFruitType and self.isClient then |
633 | Cutter.updateExtraObjects(self) |
634 | end |
635 | |
636 | self.aiRequiredFruitType = self.currentInputFruitType |
637 | else |
638 | if self.currentCutterEffect ~= nil then |
639 | for _, effect in pairs(self.currentCutterEffect) do |
640 | if effect.setMinMax ~= nil then |
641 | effect:setMinMax(0, 0, true) |
642 | end |
643 | end |
644 | end |
645 | if self.currentCutterParticles ~= nil then |
646 | ParticleUtil.setEmittingState(self.currentCutterParticles, false) |
647 | end |
648 | end |
649 | |
650 | if self.isServer then |
651 | if showFieldNotOwnedWarning ~= self.showFieldNotOwnedWarning then |
652 | self.showFieldNotOwnedWarning = showFieldNotOwnedWarning |
653 | self:raiseDirtyFlags(self.cutterGroundFlag) |
654 | end |
655 | end |
656 | |
657 | if self.isClient then |
658 | for _, ps in pairs(self.threshingParticleSystems) do |
659 | ParticleUtil.setEmittingState(ps, (self.reelStarted and self.lastCutterAreaBiggerZero)) |
660 | end |
661 | |
662 | if self.currentInputFruitType ~= FruitUtil.FRUITTYPE_UNKNOWN and self.reelStarted and self.lastCutterAreaBiggerZero then |
663 | self.fillEffectTimer = 500 |
664 | else |
665 | if self.fillEffectTimer > 0 then |
666 | self.fillEffectTimer = self.fillEffectTimer - dt |
667 | end |
668 | end |
669 | |
670 | local fillType = FruitUtil.fruitTypeToFillType[self.currentInputFruitType] |
671 | if self.fruitTypesUseWindrowed then |
672 | fillType = FruitUtil.fruitTypeToWindrowFillType[self.currentInputFruitType] |
673 | end |
674 | |
675 | if fillType ~= nil then |
676 | if self.cutterFillEffects ~= nil then |
677 | if self.fillEffectTimer > 0 then |
678 | EffectManager:setFillType(self.cutterFillEffects, fillType) |
679 | EffectManager:startEffects(self.cutterFillEffects) |
680 | else |
681 | EffectManager:stopEffects(self.cutterFillEffects) |
682 | end |
683 | end |
684 | |
685 | local currentCutterFillParticleSystem = self.cutterFillParticleSystems[fillType] |
686 | if currentCutterFillParticleSystem ~= self.currentCutterFillParticleSystem then |
687 | if self.currentCutterFillParticleSystem ~= nil then |
688 | for _, ps in pairs(self.currentCutterFillParticleSystem) do |
689 | ParticleUtil.setEmittingState(ps, false) |
690 | end |
691 | self.currentCutterFillParticleSystem = nil |
692 | end |
693 | self.currentCutterFillParticleSystem = currentCutterFillParticleSystem |
694 | end |
695 | end |
696 | |
697 | if self.currentCutterFillParticleSystem ~= nil then |
698 | for _, ps in pairs(self.currentCutterFillParticleSystem) do |
699 | ParticleUtil.setEmittingState(ps, self.fillEffectTimer > 0) |
700 | end |
701 | end |
702 | |
703 | Utils.updateRotationNodes(self, self.cutterTurnedOnRotationNodes, dt, self:getIsActive() and self.reelStarted) |
704 | Utils.updateScrollers(self.cutterTurnedOnScrollers, dt, self:getIsActive() and self.reelStarted) |
705 | |
706 | if self.cutterTurnedOnRotationNodes.isRunning then |
707 | if self.spikesRootNode ~= nil then |
708 | --correct spikes, so that they always look down |
709 | local atx, aty, atz = getRotation(self.spikesRef.node) |
710 | for i=1, self.spikesCount do |
711 | local spike = getChildAt(self.spikesRootNode, i-1) |
712 | setRotation(spike, -atx, aty, atz) |
713 | end |
714 | end |
715 | |
716 | if self.spikeAnimNodes ~= nil then |
717 | local x,y,z = getRotation(self.spikesRef.node) |
718 | local ref = x |
719 | if self.spikesRef.rotAxis == 2 then |
720 | ref = y |
721 | elseif self.spikesRef.rotAxis == 3 then |
722 | ref = z |
723 | end |
724 | local t = (ref % (2*math.pi)) / (2*math.pi) |
725 | for k, spike in pairs(self.spikeAnimNodes) do |
726 | local rotX = spike.animCurve:get(t) |
727 | setRotation(spike.node, rotX, 0, 0) |
728 | end |
729 | end |
730 | end |
731 | end |
732 | end |