222 | function Cover:loadCoverFromXML(xmlFile, key, cover) |
223 | cover.openAnimation = getXMLString(xmlFile, key.."#openAnimation") |
224 | cover.openAnimationStopTime = getXMLFloat(xmlFile, key.."#openAnimationStopTime") |
225 | |
226 | if cover.openAnimation == nil then |
227 | g_logManager:xmlWarning(self.configFileName, "Missing 'openAnimation' for cover '%s'!", key) |
228 | return false |
229 | end |
230 | |
231 | cover.closeAnimation = getXMLString(xmlFile, key.."#closeAnimation") |
232 | cover.closeAnimationStopTime = getXMLFloat(xmlFile, key.."#closeAnimationStopTime") |
233 | |
234 | cover.startOpenState = Utils.getNoNil(getXMLBool(xmlFile, key.."#openOnBuy"), false) |
235 | cover.forceOpenOnTip = Utils.getNoNil(getXMLBool(xmlFile, key.."#forceOpenOnTip"), true) |
236 | cover.autoReactToTrigger = Utils.getNoNil(getXMLBool(xmlFile, key.."#autoReactToTrigger"), true) |
237 | |
238 | local indices = getXMLString(xmlFile, key.."#fillUnitIndices") |
239 | if indices == nil then |
240 | g_logManager:xmlWarning(self.configFileName, "Missing 'fillUnitIndices' for cover '%s'!", key) |
241 | return false |
242 | end |
243 | |
244 | cover.fillUnitIndices = {StringUtil.getVectorFromString(indices)} |
245 | cover.blockedToolTypes = {} |
246 | |
247 | local strBlockedToolTypes = Utils.getNoNil(getXMLString(xmlFile, key.."#blockedToolTypes"), "dischargeable bale trigger") |
248 | strBlockedToolTypes = StringUtil.splitString(" ", StringUtil.trim(strBlockedToolTypes)) |
249 | for _, toolType in ipairs(strBlockedToolTypes) do |
250 | local index = g_toolTypeManager:getToolTypeIndexByName(toolType) |
251 | if index ~= ToolType.UNDEFINED then |
252 | cover.blockedToolTypes[index] = true |
253 | end |
254 | end |
255 | |
256 | return true |
257 | end |
350 | function Cover:loadPipeNodes(superFunc, pipeNodes, xmlFile, baseKey) |
351 | superFunc(self, pipeNodes, xmlFile, baseKey) |
352 | |
353 | local spec = self.spec_pipe |
354 | spec.coverMinState = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.pipe#coverMinState"), 0) |
355 | spec.coverMaxState = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.pipe#coverMaxState"), #self.spec_cover.covers) |
356 | end |
407 | function Cover:onAddedFillUnitTrigger(fillTypeIndex, fillUnitIndex, numTriggers) |
408 | local spec = self.spec_cover |
409 | if spec.hasCovers then |
410 | local cover = spec.fillUnitIndexToCover[fillUnitIndex] |
411 | if cover ~= nil then |
412 | local isDifferentState = spec.state ~= cover.index |
413 | local isStateChangedAllowed = self:getIsNextCoverStateAllowed(cover.index) |
414 | if cover.autoReactToTrigger and isDifferentState and isStateChangedAllowed then |
415 | self:setCoverState(cover.index, true) |
416 | spec.isStateSetAutomatically = true |
417 | end |
418 | end |
419 | end |
420 | end |
64 | function Cover:onLoad(savegame) |
65 | local spec = self.spec_cover |
66 | |
67 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cover#animationName", "vehicle.cover.coverConfigurations.coverConfiguration.cover#openAnimation") --FS17 to FS19 |
68 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.foldable.foldingParts#closeCoverOnFold", "vehicle.cover.coverConfigurations.coverConfiguration.cover#closeCoverIfNotAllowed") --FS17 to FS19 |
69 | |
70 | local coverConfigurationId = Utils.getNoNil(self.configurations["cover"], 1) |
71 | local configKey = string.format("vehicle.cover.coverConfigurations.coverConfiguration(%d)", coverConfigurationId -1) |
72 | ObjectChangeUtil.updateObjectChanges(self.xmlFile, "vehicle.cover.coverConfigurations.coverConfiguration", coverConfigurationId , self.components, self) |
73 | |
74 | spec.state = 0 |
75 | spec.runningAnimations = {} |
76 | spec.covers = {} |
77 | spec.fillUnitIndexToCover = {} |
78 | spec.isStateSetAutomatically = false |
79 | local i = 0 |
80 | while true do |
81 | local key = string.format("%s.cover(%d)", configKey, i) |
82 | if not hasXMLProperty(self.xmlFile, key) then |
83 | break |
84 | end |
85 | |
86 | local cover = {} |
87 | if self:loadCoverFromXML(self.xmlFile, key, cover) then |
88 | for j=#cover.fillUnitIndices, 1, -1 do |
89 | local index = cover.fillUnitIndices[j] |
90 | |
91 | if spec.fillUnitIndexToCover[index] == nil then |
92 | spec.fillUnitIndexToCover[index] = cover |
93 | else |
94 | table.remove(cover.fillUnitIndices, j) |
95 | g_logManager:xmlWarning(self.configFileName, "FillUnit '%d' for cover '%s' is already used by another cover. Only one cover per fillUnit is allowed. Ignoring it!", i, key) |
96 | end |
97 | end |
98 | |
99 | table.insert(spec.covers, cover) |
100 | cover.index = #spec.covers |
101 | end |
102 | |
103 | i = i + 1 |
104 | end |
105 | |
106 | spec.closeCoverIfNotAllowed = Utils.getNoNil(getXMLBool(self.xmlFile, configKey.."#closeCoverIfNotAllowed"), false) |
107 | spec.openCoverWhileTipping = Utils.getNoNil(getXMLBool(self.xmlFile, configKey.."#openCoverWhileTipping"), false) |
108 | |
109 | spec.hasCovers = #spec.covers > 0 |
110 | spec.isDirty = false |
111 | end |
115 | function Cover:onPostLoad(savegame) |
116 | local spec = self.spec_cover |
117 | if spec.hasCovers then |
118 | local state = 0 |
119 | if savegame ~= nil then |
120 | state = getXMLInt(savegame.xmlFile, savegame.key..".cover#state") or state |
121 | end |
122 | |
123 | if state == 0 then |
124 | -- set last state to max cover state to run the close animation of the last state. So we make sure the cover animations are at the currect time |
125 | spec.state = table.getn(spec.covers) |
126 | end |
127 | |
128 | self:setCoverState(state, true) |
129 | for i=#spec.runningAnimations, 1, -1 do |
130 | local animation = spec.runningAnimations[i] |
131 | AnimatedVehicle.updateAnimationByName(self, animation.name, 9999999) |
132 | table.remove(spec.runningAnimations, i) |
133 | end |
134 | spec.isDirty = false |
135 | end |
136 | end |
150 | function Cover:onReadStream(streamId, connection) |
151 | if connection:getIsServer() then |
152 | local spec = self.spec_cover |
153 | if spec.hasCovers then |
154 | local state = streamReadUIntN(streamId, Cover.SEND_NUM_BITS) |
155 | self:setCoverState(state, true) |
156 | |
157 | for i=#spec.runningAnimations, 1, -1 do |
158 | local animation = spec.runningAnimations[i] |
159 | AnimatedVehicle.updateAnimationByName(self, animation.name, 9999999) |
160 | table.remove(spec.runningAnimations, i) |
161 | end |
162 | spec.isDirty = false |
163 | end |
164 | end |
165 | end |
376 | function Cover:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection) |
377 | if self.isClient then |
378 | local spec = self.spec_cover |
379 | self:clearActionEventsTable(spec.actionEvents) |
380 | |
381 | if isActiveForInputIgnoreSelection and spec.hasCovers then |
382 | local _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.TOGGLE_COVER, self, Cover.actionEventToggleCover, false, true, false, true, nil) |
383 | g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_NORMAL) |
384 | Cover.updateActionText(self) |
385 | end |
386 | end |
387 | end |
180 | function Cover:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
181 | local spec = self.spec_cover |
182 | if spec.isDirty then |
183 | local animation = spec.runningAnimations[1] |
184 | if animation ~= nil then |
185 | local nextAnim = spec.runningAnimations[2] |
186 | -- if next animation is same as current animation, we stop the current animation and play the next |
187 | if nextAnim ~= nil and nextAnim.name == animation.name then |
188 | table.remove(spec.runningAnimations, 1) |
189 | self:stopAnimation(animation.name, true) |
190 | self:playCoverAnimation(nextAnim) |
191 | end |
192 | |
193 | -- check if current animation is playing. if not play next |
194 | if not self:getIsAnimationPlaying(animation.name) then |
195 | table.remove(spec.runningAnimations, 1) |
196 | local nextAnimation = spec.runningAnimations[1] |
197 | if nextAnimation ~= nil then |
198 | self:playCoverAnimation(nextAnimation) |
199 | else |
200 | spec.isDirty = false |
201 | end |
202 | end |
203 | end |
204 | end |
205 | |
206 | if spec.closeCoverIfNotAllowed then |
207 | if spec.state ~= 0 then |
208 | local newState = spec.state + 1 |
209 | if newState > #spec.covers then |
210 | newState = 0 |
211 | end |
212 | |
213 | if not self:getIsNextCoverStateAllowed(newState) then |
214 | self:setCoverState(0, true) |
215 | end |
216 | end |
217 | end |
218 | end |
44 | function Cover.registerEventListeners(vehicleType) |
45 | SpecializationUtil.registerEventListener(vehicleType, "onLoad", Cover) |
46 | SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", Cover) |
47 | SpecializationUtil.registerEventListener(vehicleType, "onReadStream", Cover) |
48 | SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", Cover) |
49 | SpecializationUtil.registerEventListener(vehicleType, "onUpdate", Cover) |
50 | SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", Cover) |
51 | SpecializationUtil.registerEventListener(vehicleType, "onStartTipping", Cover) |
52 | SpecializationUtil.registerEventListener(vehicleType, "onAddedFillUnitTrigger", Cover) |
53 | SpecializationUtil.registerEventListener(vehicleType, "onRemovedFillUnitTrigger", Cover) |
54 | end |
25 | function Cover.registerFunctions(vehicleType) |
26 | SpecializationUtil.registerFunction(vehicleType, "loadCoverFromXML", Cover.loadCoverFromXML) |
27 | SpecializationUtil.registerFunction(vehicleType, "getIsNextCoverStateAllowed", Cover.getIsNextCoverStateAllowed) |
28 | SpecializationUtil.registerFunction(vehicleType, "setCoverState", Cover.setCoverState) |
29 | SpecializationUtil.registerFunction(vehicleType, "playCoverAnimation", Cover.playCoverAnimation) |
30 | SpecializationUtil.registerFunction(vehicleType, "getCoverByFillUnitIndex", Cover.getCoverByFillUnitIndex) |
31 | end |
261 | function Cover:setCoverState(state, noEventSend) |
262 | local spec = self.spec_cover |
263 | |
264 | if spec.hasCovers and state >= 0 and state <= #spec.covers then |
265 | |
266 | SetCoverStateEvent.sendEvent(self, state, noEventSend) |
267 | |
268 | local startAnim = #spec.runningAnimations == 0 |
269 | |
270 | -- check if we need to close previous cover |
271 | if spec.state > 0 then |
272 | local cover = spec.covers[spec.state] |
273 | local animation = cover.closeAnimation |
274 | local stopTime = cover.closeAnimationStopTime or 1 |
275 | |
276 | if animation == nil then |
277 | animation = cover.openAnimation |
278 | stopTime = cover.openAnimationStopTime or 0 |
279 | end |
280 | |
281 | if self:getAnimationExists(animation) then |
282 | table.insert(spec.runningAnimations, {name=animation, stopTime=stopTime}) |
283 | end |
284 | end |
285 | |
286 | -- open next cover if state is not 'All-closed' (0) |
287 | if state > 0 then |
288 | local cover = spec.covers[state] |
289 | table.insert(spec.runningAnimations, {name=cover.openAnimation, stopTime=cover.openAnimationStopTime or 1}) |
290 | end |
291 | |
292 | spec.state = state |
293 | spec.isDirty = #spec.runningAnimations > 0 |
294 | |
295 | if startAnim and #spec.runningAnimations > 0 then |
296 | self:playCoverAnimation(spec.runningAnimations[1]) |
297 | end |
298 | |
299 | Cover.updateActionText(self) |
300 | end |
301 | end |
437 | function Cover.updateActionText(self) |
438 | local spec = self.spec_cover |
439 | local actionEvent = spec.actionEvents[InputAction.TOGGLE_COVER] |
440 | |
441 | if actionEvent ~= nil then |
442 | local text = g_i18n:getText("action_nextCover") |
443 | if spec.state == #spec.covers then |
444 | text = g_i18n:getText("action_closeCover") |
445 | elseif spec.state == 0 then |
446 | text = g_i18n:getText("action_openCover") |
447 | end |
448 | |
449 | g_inputBinding:setActionEventText(actionEvent.actionEventId, text) |
450 | end |
451 | end |