40 | function ForageWagon:load(savegame) |
41 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.fillScale#value", "vehicle.forageWagon#fillScale") |
42 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.forageWagonSound", "vehicle.forageWagon#sound") |
43 | Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.turnedOnTipScrollerSpeedFactor#value", "vehicle.forageWagon#turnedOnTipScrollerSpeedFactor") |
44 | |
45 | self.doCheckSpeedLimit = Utils.overwrittenFunction(self.doCheckSpeedLimit, ForageWagon.doCheckSpeedLimit) |
46 | self.getIsSpeedRotatingPartActive = Utils.overwrittenFunction(self.getIsSpeedRotatingPartActive, ForageWagon.getIsSpeedRotatingPartActive) |
47 | self.getTipScrollerSpeed = Utils.overwrittenFunction(self.getTipScrollerSpeed, ForageWagon.getTipScrollerSpeed) |
48 | self.processForageWagonAreas = ForageWagon.processForageWagonAreas |
49 | |
50 | self.forageWagon = {} |
51 | self.forageWagon.turnedOnRotationNodes = Utils.loadRotationNodes(self.xmlFile, {}, "vehicle.turnedOnRotationNodes.turnedOnRotationNode", "forageWagon", self.components) |
52 | self.forageWagon.isSpeedLimitActive = false |
53 | self.forageWagon.lastAreaBiggerZero = false |
54 | self.forageWagon.lastAreaBiggerZeroSent = false |
55 | self.forageWagon.lastAreaBiggerZeroTime = 0 |
56 | self.forageWagon.fillScale = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.forageWagon#fillScale"), 1) |
57 | self.forageWagon.fillUnitIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.forageWagon#fillUnitIndex"), 1) |
58 | self.forageWagon.unloadInfoIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.forageWagon#unloadInfoIndex"), 1) |
59 | self.forageWagon.loadInfoIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.forageWagon#loadInfoIndex"), 1) |
60 | self.forageWagon.dischargeInfoIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.forageWagon#dischargeInfoIndex"), 1) |
61 | self.forageWagon.turnedOnTipScrollerSpeedFactor = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.forageWagon#turnedOnTipScrollerSpeedFactor"), 0.25) |
62 | |
63 | if self.isClient then |
64 | self.forageWagon.sampleRunning = SoundUtil.loadSample(self.xmlFile, {}, "vehicle.forageWagon.runningSound", nil, self.baseDirectory) |
65 | self.forageWagon.sampleAlarm = SoundUtil.loadSample(self.xmlFile, {}, "vehicle.forageWagon.alarmSound", nil, self.baseDirectory) |
66 | |
67 | self.forageWagon.fillEffects = EffectManager:loadEffect(self.xmlFile, "vehicle.forageWagon.fillEffect", self.components, self) |
68 | |
69 | self.forageWagon.fillParticleSystems = {} |
70 | self.forageWagon.currentFillParticleSystem = nil |
71 | local i = 0 |
72 | while true do |
73 | local key = string.format("vehicle.forageWagon.fillParticleSystems.emitterShape(%d)", i) |
74 | if not hasXMLProperty(self.xmlFile, key) then |
75 | break |
76 | end |
77 | |
78 | local emitterShape = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key.."#node")) |
79 | local particleType = getXMLString(self.xmlFile, key.."#particleType") |
80 | if emitterShape ~= nil then |
81 | for index, _ in pairs(self.fillUnits) do |
82 | for fillType, _ in pairs(self:getUnitFillTypes(index)) do |
83 | if self.forageWagon.fillParticleSystems[fillType] == nil then |
84 | self.forageWagon.fillParticleSystems[fillType] = {} |
85 | end |
86 | |
87 | local particleSystem = MaterialUtil.getParticleSystem(fillType, particleType) |
88 | if particleSystem ~= nil then |
89 | table.insert(self.forageWagon.fillParticleSystems[fillType], ParticleUtil.copyParticleSystem(self.xmlFile, key, particleSystem, emitterShape)) |
90 | end |
91 | end |
92 | end |
93 | end |
94 | i = i + 1 |
95 | end |
96 | end |
97 | |
98 | self.forageWagon.dirtyFlag = self:getNextDirtyFlag() |
99 | end |
161 | function ForageWagon:update(dt) |
162 | if self.isClient then |
163 | Utils.updateRotationNodes(self, self.forageWagon.turnedOnRotationNodes, dt, self:getIsActive() and self:getIsTurnedOn() ) |
164 | |
165 | if self:getIsActive() then |
166 | if self:getIsTurnedOn() then |
167 | if self.lastForageFillLevel ~= self:getFillLevel(self:getUnitFillType(self.forageWagon.fillUnitIndex)) then |
168 | self.lastForageFillLevel = self:getFillLevel(self:getUnitFillType(self.forageWagon.fillUnitIndex)) |
169 | self.lastForageFillTime = g_currentMission.time + 250 |
170 | end |
171 | if self.lastForageFillTime > g_currentMission.time then |
172 | if self.fillUnits ~= nil then |
173 | local fillUnit = self.fillUnits[self.forageWagon.fillUnitIndex]; |
174 | if fillUnit ~= nil then |
175 | local fillVolume = self.fillVolumes[fillUnit.fillVolumeIndex]; |
176 | if fillVolume ~= nil then |
177 | if fillVolume.scrollSpeedLoad[1] ~= 0 or fillVolume.scrollSpeedLoad[2] ~= 0 or fillVolume.scrollSpeedLoad[3] ~= 0 then |
178 | fillVolume.uvPosition[1] = fillVolume.uvPosition[1] + fillVolume.scrollSpeedLoad[1]*dt |
179 | fillVolume.uvPosition[2] = fillVolume.uvPosition[2] + fillVolume.scrollSpeedLoad[2]*dt |
180 | fillVolume.uvPosition[3] = fillVolume.uvPosition[3] + fillVolume.scrollSpeedLoad[3]*dt |
181 | setShaderParameter(fillVolume.volume, "uvOffset", fillVolume.uvPosition[1], fillVolume.uvPosition[2], fillVolume.uvPosition[3], 0, false) |
182 | end |
183 | end |
184 | end |
185 | end |
186 | end |
187 | end |
188 | end |
189 | end |
190 | end |
195 | function ForageWagon:updateTick(dt) |
196 | self.forageWagon.isSpeedLimitActive = false |
197 | if self.isServer then |
198 | self.forageWagon.lastAreaBiggerZero = false |
199 | end |
200 | |
201 | if self:getIsActive() then |
202 | if self:getIsTurnedOn() then |
203 | if self:getUnitFillLevel(self.forageWagon.fillUnitIndex) < self:getUnitCapacity(self.forageWagon.fillUnitIndex) then |
204 | if self:allowPickingUp() then |
205 | self.forageWagon.isSpeedLimitActive = true |
206 | if self.isServer then |
207 | local workAreas, _, _ = self:getTypedNetworkAreas(WorkArea.AREATYPE_FORAGEWAGON, false) |
208 | |
209 | if (table.getn(workAreas) > 0) then |
210 | local fruitTypeFix = false |
211 | local fruitType = FruitUtil.FRUITTYPE_UNKNOWN |
212 | local fillType = self:getUnitFillType(self.forageWagon.fillUnitIndex) |
213 | |
214 | if self:getUnitFillLevel(self.forageWagon.fillUnitIndex) > self:getUnitCapacity(self.forageWagon.fillUnitIndex)*self.fillTypeChangeThreshold and FruitUtil.fillTypeToFruitType[fillType] ~= nil and FruitUtil.fillTypeIsWindrow[fillType] then |
215 | fruitTypeFix = true |
216 | fruitType = FruitUtil.fillTypeToFruitType[fillType] |
217 | end |
218 | local liters, usedFruitType = self:processForageWagonAreas(workAreas, self:getUnitFillTypes(self.forageWagon.fillUnitIndex), fruitTypeFix, fruitType) |
219 | |
220 | if liters > 0 then |
221 | local deltaLevel = liters * self.forageWagon.fillScale |
222 | self:setUnitFillLevel(self.forageWagon.fillUnitIndex, self:getUnitFillLevel(self.forageWagon.fillUnitIndex)+deltaLevel, FruitUtil.fruitTypeToWindrowFillType[usedFruitType], true, self.fillVolumeLoadInfos[self.forageWagon.loadInfoIndex]) |
223 | |
224 | self.forageWagon.lastAreaBiggerZero = true |
225 | if self.forageWagon.lastAreaBiggerZero ~= self.forageWagon.lastAreaBiggerZeroSent then |
226 | self:raiseDirtyFlags(self.forageWagon.dirtyFlag) |
227 | self.forageWagon.lastAreaBiggerZeroSent = self.forageWagon.lastAreaBiggerZero |
228 | end |
229 | end |
230 | end |
231 | end |
232 | end |
233 | |
234 | if self:getIsActiveForSound() then |
235 | SoundUtil.playSample(self.forageWagon.sampleRunning, 0, 0, nil) |
236 | end |
237 | |
238 | if self.forageWagon.lastAreaBiggerZero and self.fillUnits[self.forageWagon.fillUnitIndex].lastValidFillType ~= FillUtil.FILLTYPE_UNKNOWN then |
239 | self.forageWagon.lastAreaBiggerZeroTime = 500 |
240 | else |
241 | if self.forageWagon.lastAreaBiggerZeroTime > 0 then |
242 | self.forageWagon.lastAreaBiggerZeroTime = self.forageWagon.lastAreaBiggerZeroTime - dt |
243 | end |
244 | end |
245 | |
246 | if self.isClient then |
247 | if self.forageWagon.fillEffects ~= nil then |
248 | if self.forageWagon.lastAreaBiggerZeroTime > 0 then |
249 | EffectManager:setFillType(self.forageWagon.fillEffects, self.fillUnits[self.forageWagon.fillUnitIndex].lastValidFillType) |
250 | EffectManager:startEffects(self.forageWagon.fillEffects) |
251 | else |
252 | EffectManager:stopEffects(self.forageWagon.fillEffects) |
253 | end |
254 | end |
255 | |
256 | local currentFillParticleSystem = self.forageWagon.fillParticleSystems[self.fillUnits[self.forageWagon.fillUnitIndex].lastValidFillType] |
257 | if currentFillParticleSystem ~= self.forageWagon.currentFillParticleSystem then |
258 | if self.forageWagon.currentFillParticleSystem ~= nil then |
259 | for _, ps in pairs(self.forageWagon.currentFillParticleSystem) do |
260 | ParticleUtil.setEmittingState(ps, false) |
261 | end |
262 | self.forageWagon.currentFillParticleSystem = nil |
263 | end |
264 | self.forageWagon.currentFillParticleSystem = currentFillParticleSystem |
265 | end |
266 | |
267 | if self.forageWagon.currentFillParticleSystem ~= nil then |
268 | for _, ps in pairs(self.forageWagon.currentFillParticleSystem) do |
269 | ParticleUtil.setEmittingState(ps, self.forageWagon.lastAreaBiggerZeroTime > 0) |
270 | end |
271 | end |
272 | |
273 | end |
274 | else |
275 | self:setIsTurnedOn(false) |
276 | if self.setPickupState ~= nil then |
277 | self:setPickupState(false) |
278 | end |
279 | end |
280 | end |
281 | |
282 | -- alarm sound |
283 | if self.isClient then |
284 | if self:getIsTurnedOn() and self:getUnitFillLevel(self.forageWagon.fillUnitIndex) > (self:getUnitCapacity(self.forageWagon.fillUnitIndex) * 0.98) and self:getUnitFillLevel(self.forageWagon.fillUnitIndex) < self:getUnitCapacity(self.forageWagon.fillUnitIndex) then |
285 | if self:getIsActiveForSound() then |
286 | SoundUtil.playSample(self.forageWagon.sampleAlarm, 0, 0, nil) |
287 | end |
288 | else |
289 | SoundUtil.stopSample(self.forageWagon.sampleAlarm) |
290 | end |
291 | end |
292 | end |
293 | end |
431 | function ForageWagon:processForageWagonAreas(workAreas, fillTypes, fruitTypeFix, fruitType) |
432 | |
433 | local numAreas = table.getn(workAreas) |
434 | local totalLiters = 0 |
435 | for i=1, numAreas do |
436 | local x0 = workAreas[i][1] |
437 | local z0 = workAreas[i][2] |
438 | local x1 = workAreas[i][3] |
439 | local z1 = workAreas[i][4] |
440 | local x2 = workAreas[i][5] |
441 | local z2 = workAreas[i][6] |
442 | |
443 | local hx = x2 - x0 |
444 | local hz = z2 - z0 |
445 | local hLength = Utils.vector2Length(hx, hz) |
446 | local hLength_2 = 0.5 * hLength |
447 | |
448 | local wx = x1 - x0 |
449 | local wz = z1 - z0 |
450 | local wLength = Utils.vector2Length(wx, wz) |
451 | |
452 | local sx = x0 + (hx * 0.5) + ((wx/wLength)*hLength_2) |
453 | local sz = z0 + (hz * 0.5) + ((wz/wLength)*hLength_2) |
454 | |
455 | local ex = x1 + (hx * 0.5) - ((wx/wLength)*hLength_2) |
456 | local ez = z1 + (hz * 0.5) - ((wz/wLength)*hLength_2) |
457 | |
458 | local sy = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, sx,0,sz) |
459 | local ey = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, ex,0,ez) |
460 | |
461 | |
462 | local liters = 0 |
463 | if fruitTypeFix then |
464 | local fillType = FruitUtil.fruitTypeToWindrowFillType[fruitType] |
465 | liters = -TipUtil.tipToGroundAroundLine(self, -math.huge, fillType, sx,sy,sz, ex,ey,ez, hLength_2, nil, nil, false, nil) |
466 | |
467 | local fruitDesc = FruitUtil.fruitIndexToDesc[fruitType] |
468 | if fruitDesc ~= nil then |
469 | for fruitTypeSrc,_ in pairs(fruitDesc.forageWagonConversionSources) do |
470 | local fillType = FruitUtil.fruitTypeToWindrowFillType[fruitTypeSrc] |
471 | liters = liters - TipUtil.tipToGroundAroundLine(self, -math.huge, fillType, sx,sy,sz, ex,ey,ez, hLength_2, nil, nil, false, nil) |
472 | end |
473 | end |
474 | else |
475 | for fillType, enabled in pairs(fillTypes) do |
476 | -- Note: we count both grass and dry grass as grass (ignore dry grass in the loop, and pickup dry grass when cutting normal grass) |
477 | -- and we do the same with barley and wheat windrows |
478 | -- This is generalized with the forageWagonConversionTarget and forageWagonConversionSources attributes of the fruitTypeDesc |
479 | local localFruitType = FruitUtil.fillTypeToFruitType[fillType] |
480 | local fruitDesc |
481 | if localFruitType ~= nil then |
482 | fruitDesc = FruitUtil.fruitIndexToDesc[localFruitType] |
483 | end |
484 | if enabled and fruitDesc ~= nil then |
485 | liters = -TipUtil.tipToGroundAroundLine(self, -math.huge, fillType, sx,sy,sz, ex,ey,ez, hLength_2, nil, nil, false, nil) |
486 | |
487 | if fruitDesc ~= nil and FruitUtil.fillTypeIsWindrow[fillType] and fruitDesc.forageWagonConversionTarget == nil then |
488 | for fruitTypeSrc,_ in pairs(fruitDesc.forageWagonConversionSources) do |
489 | local fillType = FruitUtil.fruitTypeToWindrowFillType[fruitTypeSrc] |
490 | liters = liters - TipUtil.tipToGroundAroundLine(self, -math.huge, fillType, sx,sy,sz, ex,ey,ez, hLength_2, nil, nil, false, nil) |
491 | end |
492 | end |
493 | if liters > 0 then |
494 | fruitTypeFix = true |
495 | fruitType = localFruitType; |
496 | break |
497 | end |
498 | end |
499 | end |
500 | end |
501 | if liters > 0 then |
502 | -- now that we removed the windrow, maybe there is some hidden drygrass to grow (set it to growth state 1 if there is some) |
503 | if fruitType == FruitUtil.FRUITTYPE_GRASS then |
504 | Utils.switchFruitTypeArea(FruitUtil.FRUITTYPE_GRASS, FruitUtil.FRUITTYPE_DRYGRASS, x0, z0, x1, z1, x2, z2, 2) |
505 | end |
506 | totalLiters = totalLiters + liters |
507 | end |
508 | end |
509 | return totalLiters, fruitType |
510 | end |