22 | function PlowPacker.initSpecialization() |
23 | local schema = Vehicle.xmlSchema |
24 | schema:setXMLSpecializationType("PlowPacker") |
25 | |
26 | schema:register(XMLValueType.STRING, "vehicle.plow.packer#inputAction", "Input action name for packer toggeling", "IMPLEMENT_EXTRA4") |
27 | |
28 | schema:register(XMLValueType.STRING, "vehicle.plow.packer#deactivateLeft", "Packer deactivate animation left side") |
29 | schema:register(XMLValueType.STRING, "vehicle.plow.packer#deactivateRight", "Packer deactivate animation left side") |
30 | schema:register(XMLValueType.FLOAT, "vehicle.plow.packer#animationSpeed", "Packer animation speed", 1) |
31 | schema:register(XMLValueType.INT, "vehicle.plow.packer#foldingConfig", "Folding configuration with available packer", 1) |
32 | |
33 | schema:register(XMLValueType.BOOL, "vehicle.plow.packer#partialDeactivated", "Only some parts of the packer are deactivated", false) |
34 | |
35 | schema:register(XMLValueType.STRING, "vehicle.plow.packer.lowerAnimation#name", "Lower animation that is played while packer is active") |
36 | schema:register(XMLValueType.FLOAT, "vehicle.plow.packer.lowerAnimation#speed", "Lower animation speed", 1) |
37 | |
38 | schema:setXMLSpecializationType() |
39 | |
40 | local schemaSavegame = Vehicle.xmlSchemaSavegame |
41 | schemaSavegame:register(XMLValueType.BOOL, "vehicles.vehicle(?).plowPacker#packerState", "Packer state") |
42 | schemaSavegame:register(XMLValueType.BOOL, "vehicles.vehicle(?).plowPacker#lastPackerState", "Last packer state while turning") |
43 | end |
85 | function PlowPacker:onLoad(savegame) |
86 | local spec = self.spec_plowPacker |
87 | |
88 | local actionName = self.xmlFile:getValue("vehicle.plow.packer#inputAction", "IMPLEMENT_EXTRA4") |
89 | if actionName ~= nil then |
90 | spec.packerInputActionIndex = InputAction[actionName] |
91 | end |
92 | |
93 | spec.packerDeactivateLeftAnimation = self.xmlFile:getValue("vehicle.plow.packer#deactivateLeft") |
94 | spec.packerDeactivateRightAnimation = self.xmlFile:getValue("vehicle.plow.packer#deactivateRight") |
95 | spec.packerDeactivateAnimSpeed = self.xmlFile:getValue("vehicle.plow.packer#animationSpeed", 1) |
96 | |
97 | spec.packerFoldingConfiguration = self.xmlFile:getValue("vehicle.plow.packer#foldingConfig", 1) |
98 | spec.packerAvailable = self.configurations["folding"] == spec.packerFoldingConfiguration and spec.packerDeactivateLeftAnimation ~= nil and spec.packerDeactivateRightAnimation ~= nil |
99 | |
100 | spec.partialDeactivated = self.xmlFile:getValue("vehicle.plow.packer#partialDeactivated", false) |
101 | |
102 | spec.lowerAnimation = self.xmlFile:getValue("vehicle.plow.packer.lowerAnimation#name") |
103 | spec.lowerAnimationSpeed = self.xmlFile:getValue("vehicle.plow.packer.lowerAnimation#speed", 1) |
104 | |
105 | spec.packerActivateText = g_i18n:getText("action_activatePacker", self.customEnvironment) |
106 | spec.packerDeactivateText = g_i18n:getText("action_deactivatePacker", self.customEnvironment) |
107 | |
108 | spec.packerState = true |
109 | |
110 | spec.delayedFoldStateChange = nil |
111 | spec.delayedLowerAnimationUpdate = false |
112 | end |
116 | function PlowPacker:onPostLoad(savegame) |
117 | local spec = self.spec_plowPacker |
118 | self:setPlowAIRequirements() |
119 | |
120 | if savegame ~= nil and not savegame.resetVehicles then |
121 | if spec.packerAvailable then |
122 | local packerState = savegame.xmlFile:getValue(savegame.key..".plowPacker#packerState") |
123 | if packerState ~= nil then |
124 | self:setPackerState(packerState, true, true) |
125 | AnimatedVehicle.updateAnimations(self, 99999999, true) |
126 | end |
127 | |
128 | spec.lastPackerState = savegame.xmlFile:getValue(savegame.key..".plowPacker#lastPackerState") |
129 | end |
130 | end |
131 | end |
413 | function PlowPacker:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection) |
414 | if self.isClient then |
415 | local spec = self.spec_plowPacker |
416 | if spec.packerAvailable then |
417 | self:clearActionEventsTable(spec.actionEvents) |
418 | |
419 | if isActiveForInput and spec.packerInputActionIndex ~= nil then |
420 | local _, actionEventId = self:addPoweredActionEvent(spec.actionEvents, spec.packerInputActionIndex, self, PlowPacker.actionEventPackerDeactivate, false, true, false, true) |
421 | g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_NORMAL) |
422 | PlowPacker.updateActionEventText(self) |
423 | end |
424 | end |
425 | end |
426 | end |
178 | function PlowPacker:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
179 | if self.isServer then |
180 | local spec = self.spec_plowPacker |
181 | if spec.packerAvailable then |
182 | if spec.lastPackerState ~= nil then |
183 | if self:getIsPackerAllowed() then |
184 | if spec.lastPackerState == false then |
185 | self:setPackerState(false, true) |
186 | end |
187 | |
188 | spec.lastPackerState = nil |
189 | end |
190 | end |
191 | |
192 | if spec.delayedFoldStateChange ~= nil then |
193 | if not self:getIsAnimationPlaying(spec.packerDeactivateLeftAnimation) |
194 | and not self:getIsAnimationPlaying(spec.packerDeactivateRightAnimation) then |
195 | local data = spec.delayedFoldStateChange |
196 | data.superFunc(self, data.direction, data.moveToMiddle, false) |
197 | spec.delayedFoldStateChange = nil |
198 | end |
199 | end |
200 | |
201 | if spec.delayedLowerAnimationUpdate then |
202 | if not self:getIsAnimationPlaying(spec.packerDeactivateLeftAnimation) |
203 | and not self:getIsAnimationPlaying(spec.packerDeactivateRightAnimation) then |
204 | local isLowered = self:getIsLowered() |
205 | local animationTime = self:getAnimationTime(spec.lowerAnimation) |
206 | if (isLowered and animationTime <= 0.5) or (not isLowered and animationTime > 0.5) then |
207 | self:playAnimation(spec.lowerAnimation, isLowered and spec.lowerAnimationSpeed or -spec.lowerAnimationSpeed, nil, true) |
208 | end |
209 | |
210 | spec.delayedLowerAnimationUpdate = false |
211 | end |
212 | end |
213 | end |
214 | end |
215 | end |
300 | function PlowPacker:processCultivatorArea(superFunc, workArea, dt) |
301 | local spec = self.spec_cultivator |
302 | |
303 | local xs,_,zs = getWorldTranslation(workArea.start) |
304 | local xw,_,zw = getWorldTranslation(workArea.width) |
305 | local xh,_,zh = getWorldTranslation(workArea.height) |
306 | |
307 | local params = spec.workAreaParameters |
308 | |
309 | local realArea, area = FSDensityMapUtil.updatePlowPackerArea(xs, zs, xw, zw, xh, zh, params.angle) |
310 | |
311 | params.lastChangedArea = params.lastChangedArea + realArea |
312 | params.lastStatsArea = params.lastStatsArea + realArea |
313 | params.lastTotalArea = params.lastTotalArea + area |
314 | |
315 | FSDensityMapUtil.eraseTireTrack(xs, zs, xw, zw, xh, zh) |
316 | |
317 | spec.isWorking = self:getLastSpeed() > 0.5 |
318 | |
319 | return realArea, area |
320 | end |
72 | function PlowPacker.registerEventListeners(vehicleType) |
73 | SpecializationUtil.registerEventListener(vehicleType, "onLoad", PlowPacker) |
74 | SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", PlowPacker) |
75 | SpecializationUtil.registerEventListener(vehicleType, "onReadStream", PlowPacker) |
76 | SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", PlowPacker) |
77 | SpecializationUtil.registerEventListener(vehicleType, "onUpdate", PlowPacker) |
78 | SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", PlowPacker) |
79 | SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", PlowPacker) |
80 | SpecializationUtil.registerEventListener(vehicleType, "onSetLowered", PlowPacker) |
81 | end |
62 | function PlowPacker.registerOverwrittenFunctions(vehicleType) |
63 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "setRotationMax", PlowPacker.setRotationMax) |
64 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "setPlowAIRequirements", PlowPacker.setPlowAIRequirements) |
65 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "setFoldState", PlowPacker.setFoldState) |
66 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "processCultivatorArea", PlowPacker.processCultivatorArea) |
67 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getUseCultivatorAIRequirements", PlowPacker.getUseCultivatorAIRequirements) |
68 | end |
263 | function PlowPacker:setFoldState(superFunc, direction, moveToMiddle, noEventSend) |
264 | local spec = self.spec_plowPacker |
265 | if spec.packerAvailable then |
266 | if direction ~= 0 and direction ~= self.spec_foldable.turnOnFoldDirection and self:getIsPackerAllowed() and not spec.packerState then |
267 | if self.isServer then |
268 | if spec.lastPackerState == nil then |
269 | spec.lastPackerState = spec.packerState |
270 | self:setPackerState(true, true) |
271 | |
272 | spec.delayedFoldStateChange = {superFunc=superFunc, direction=direction, moveToMiddle=moveToMiddle} |
273 | end |
274 | end |
275 | |
276 | -- sync the event to the server / client to they can set the 'lastPackerState' correctly |
277 | local specFoldable = self.spec_foldable |
278 | if specFoldable.foldMiddleAnimTime == nil then |
279 | moveToMiddle = false |
280 | end |
281 | if specFoldable.foldMoveDirection ~= direction or specFoldable.moveToMiddle ~= moveToMiddle then |
282 | if noEventSend == nil or noEventSend == false then |
283 | if g_server ~= nil then |
284 | g_server:broadcastEvent(FoldableSetFoldDirectionEvent.new(self, direction, moveToMiddle), nil, nil, self) |
285 | else |
286 | g_client:getServerConnection():sendEvent(FoldableSetFoldDirectionEvent.new(self, direction, moveToMiddle)) |
287 | end |
288 | end |
289 | end |
290 | |
291 | return |
292 | end |
293 | end |
294 | |
295 | superFunc(self, direction, moveToMiddle, noEventSend) |
296 | end |
331 | function PlowPacker:setPackerState(newState, updateAnimations, noEventSend) |
332 | local spec = self.spec_plowPacker |
333 | |
334 | if newState == nil then |
335 | newState = not spec.packerState |
336 | end |
337 | |
338 | if updateAnimations == nil then |
339 | updateAnimations = true |
340 | end |
341 | |
342 | if newState ~= spec.packerState then |
343 | spec.packerState = newState |
344 | |
345 | if updateAnimations then |
346 | local direction = newState and -1 or 1 |
347 | if self.spec_plow.rotationMax then |
348 | self:playAnimation(spec.packerDeactivateLeftAnimation, spec.packerDeactivateAnimSpeed * direction, nil, true) |
349 | else |
350 | self:playAnimation(spec.packerDeactivateRightAnimation, spec.packerDeactivateAnimSpeed * direction, nil, true) |
351 | end |
352 | end |
353 | |
354 | -- if packer is activated we update the lowering animation after the packer has been lowered |
355 | -- so we sync the lowering state in case it has been changed while the packer was lifted |
356 | if newState then |
357 | if spec.lowerAnimation ~= nil then |
358 | local isLowered = self:getIsLowered() |
359 | local animationTime = self:getAnimationTime(spec.lowerAnimation) |
360 | if (isLowered and animationTime <= 0.5) or (not isLowered and animationTime > 0.5) then |
361 | spec.delayedLowerAnimationUpdate = true |
362 | end |
363 | end |
364 | end |
365 | |
366 | self:setPlowAIRequirements() |
367 | |
368 | PlowPackerStateEvent.sendEvent(self, newState, updateAnimations, noEventSend) |
369 | end |
370 | |
371 | PlowPacker.updateActionEventText(self) |
372 | end |
232 | function PlowPacker:setRotationMax(superFunc, rotationMax, noEventSend, turnAnimationTime) |
233 | if self.isServer then |
234 | if self.spec_plow.rotationMax ~= rotationMax then |
235 | local spec = self.spec_plowPacker |
236 | if spec.packerAvailable then |
237 | if spec.lastPackerState == nil then |
238 | spec.lastPackerState = spec.packerState |
239 | self:setPackerState(true, true) |
240 | end |
241 | end |
242 | end |
243 | end |
244 | |
245 | superFunc(self, rotationMax, noEventSend, turnAnimationTime) |
246 | end |
430 | function PlowPacker.updateActionEventText(self) |
431 | local spec = self.spec_plowPacker |
432 | |
433 | local actionEvent = spec.actionEvents[spec.packerInputActionIndex] |
434 | if actionEvent ~= nil then |
435 | if spec.packerState then |
436 | g_inputBinding:setActionEventText(actionEvent.actionEventId, spec.packerDeactivateText) |
437 | else |
438 | g_inputBinding:setActionEventText(actionEvent.actionEventId, spec.packerActivateText) |
439 | end |
440 | |
441 | g_inputBinding:setActionEventActive(actionEvent.actionEventId, self:getIsPackerAllowed()) |
442 | end |
443 | end |