58 | function LoadTrigger:load(components, xmlFile, xmlNode, i3dMappings, rootNode) |
59 | self.rootNode = rootNode or xmlFile:getValue(xmlNode .. "#node", nil, components, i3dMappings) |
60 | if self.rootNode == nil then |
61 | Logging.xmlError(xmlFile, "Missing node '%s#node'", xmlNode) |
62 | return false |
63 | end |
64 | |
65 | -- load triggers |
66 | self.objectsInTriggers = {} |
67 | |
68 | XMLUtil.checkDeprecatedXMLElements(xmlFile, xmlNode .. "#scrollerIndex", xmlNode .. "#scrollerNode") |
69 | |
70 | XMLUtil.checkDeprecatedUserAttribute(self.rootNode, "triggerNode", xmlFile, xmlNode .. "#triggerNode") |
71 | XMLUtil.checkDeprecatedUserAttribute(self.rootNode, "triggerIndex", xmlFile, xmlNode .. "#triggerNode") |
72 | XMLUtil.checkDeprecatedUserAttribute(self.rootNode, "fillLitersPerSecond", xmlFile, xmlNode .. "#fillLitersPerSecond") |
73 | XMLUtil.checkDeprecatedUserAttribute(self.rootNode, "dischargeNode", xmlFile, xmlNode .. "#dischargeNode") |
74 | XMLUtil.checkDeprecatedUserAttribute(self.rootNode, "fillSoundIdentifier", xmlFile, xmlNode .. "#fillSoundIdentifier") |
75 | XMLUtil.checkDeprecatedUserAttribute(self.rootNode, "fillSoundNode", xmlFile, xmlNode .. "#fillSoundNode") |
76 | XMLUtil.checkDeprecatedUserAttribute(self.rootNode, "scrollerIndex", xmlFile, xmlNode .. "#scrollerNode") |
77 | XMLUtil.checkDeprecatedUserAttribute(self.rootNode, "shaderParameterName", xmlFile, xmlNode .. "#shaderParameterName") |
78 | XMLUtil.checkDeprecatedUserAttribute(self.rootNode, "scrollerScrollSpeed", xmlFile, xmlNode .. "#scrollerScrollSpeed") |
79 | XMLUtil.checkDeprecatedUserAttribute(self.rootNode, "fillTypeCategories", xmlFile, xmlNode .. "#fillTypeCategories") |
80 | XMLUtil.checkDeprecatedUserAttribute(self.rootNode, "fillTypes", xmlFile, xmlNode .. "#fillTypes") |
81 | XMLUtil.checkDeprecatedUserAttribute(self.rootNode, "autoStart", xmlFile, xmlNode .. "#autoStart") |
82 | XMLUtil.checkDeprecatedUserAttribute(self.rootNode, "infiniteCapacity", xmlFile, xmlNode .. "#infiniteCapacity") |
83 | |
84 | local triggerNode = xmlFile:getValue(xmlNode .. "#triggerNode", nil, components, i3dMappings) |
85 | if triggerNode == nil then |
86 | Logging.xmlError(xmlFile, "Missing triggerNode defined in '%s'", xmlNode) |
87 | return false |
88 | end |
89 | |
90 | self.triggerNode = triggerNode |
91 | addTrigger(triggerNode, "loadTriggerCallback", self) |
92 | g_currentMission:addNodeObject(triggerNode, self) |
93 | |
94 | self.fillLitersPerMS = xmlFile:getValue(xmlNode .. "#fillLitersPerSecond", 1000) / 1000 |
95 | |
96 | |
97 | self.aiNode = xmlFile:getValue(xmlNode .. "#aiNode", nil, components, i3dMappings) |
98 | self.supportsAILoading = self.aiNode ~= nil |
99 | |
100 | local dischargeNode = xmlFile:getValue(xmlNode .. "#dischargeNode", nil, components, i3dMappings) |
101 | if dischargeNode ~= nil then |
102 | XMLUtil.checkDeprecatedUserAttribute(dischargeNode, "width", xmlFile, xmlNode .. "#dischargeWidth") |
103 | XMLUtil.checkDeprecatedUserAttribute(dischargeNode, "length", xmlFile, xmlNode .. "#dischargeLength") |
104 | |
105 | self.dischargeInfo = {} |
106 | self.dischargeInfo.name = "fillVolumeDischargeInfo" |
107 | self.dischargeInfo.nodes = {} |
108 | local width = xmlFile:getValue(xmlNode .. "#dischargeWidth", 0.5) |
109 | local length = xmlFile:getValue(xmlNode .. "#dischargeLength", 0.5) |
110 | table.insert(self.dischargeInfo.nodes, {node=dischargeNode, width=width, length=length, priority=1}) |
111 | end |
112 | |
113 | -- place sound at the same position as the trigger or the discharge node |
114 | self.soundNode = createTransformGroup("loadTriggerSoundNode") |
115 | link(dischargeNode or self.triggerNode, self.soundNode) |
116 | |
117 | if self.isClient then |
118 | self.effects = g_effectManager:loadEffect(xmlFile, xmlNode, components, self, i3dMappings) |
119 | |
120 | self.samples = {} |
121 | |
122 | local fillSoundIdentifier = xmlFile:getValue(xmlNode .. "#fillSoundIdentifier") |
123 | local fillSoundNode = xmlFile:getValue(xmlNode .. "#fillSoundNode", nil, components, i3dMappings) |
124 | |
125 | if fillSoundNode == nil then |
126 | fillSoundNode = self.rootNode |
127 | end |
128 | |
129 | local xmlSoundFile = loadXMLFile("mapXML", g_currentMission.missionInfo.mapSoundXmlFilename) |
130 | if xmlSoundFile ~= nil and xmlSoundFile ~= 0 then |
131 | local directory = g_currentMission.baseDirectory |
132 | local modName, baseDirectory = Utils.getModNameAndBaseDirectory(g_currentMission.missionInfo.mapSoundXmlFilename) |
133 | if modName ~= nil then |
134 | directory = baseDirectory .. modName |
135 | end |
136 | if fillSoundIdentifier ~= nil then |
137 | self.samples.load = g_soundManager:loadSampleFromXML(xmlSoundFile, "sound.object", fillSoundIdentifier, directory, getRootNode(), 0, AudioGroup.ENVIRONMENT, nil, nil) |
138 | if self.samples.load ~= nil then |
139 | link(fillSoundNode, self.samples.load.soundNode) |
140 | setTranslation(self.samples.load.soundNode, 0,0,0) |
141 | end |
142 | end |
143 | delete(xmlSoundFile) |
144 | end |
145 | |
146 | self.scroller = xmlFile:getValue(xmlNode .. "#scrollerNode", nil, components, i3dMappings) |
147 | if self.scroller ~= nil then |
148 | self.scrollerShaderParameterName = xmlFile:getValue(xmlNode .. "#shaderParameterName", "uvScrollSpeed") |
149 | self.scrollerSpeedX, self.scrollerSpeedY = xmlFile:getValue(xmlNode .. "#scrollerScrollSpeed", "0 -0.75") |
150 | |
151 | setShaderParameter(self.scroller, self.scrollerShaderParameterName, 0, 0, 0, 0, false) |
152 | end |
153 | end |
154 | |
155 | self.fillTypes = {} |
156 | local fillTypeCategories = XMLUtil.getValueFromXMLFileOrUserAttribute(xmlFile, xmlNode, "fillTypeCategories", self.rootNode) |
157 | local fillTypeNames = XMLUtil.getValueFromXMLFileOrUserAttribute(xmlFile, xmlNode, "fillTypes", self.rootNode) |
158 | |
159 | local fillTypes = nil |
160 | if fillTypeCategories ~= nil and fillTypeNames == nil then |
161 | fillTypes = g_fillTypeManager:getFillTypesByCategoryNames(fillTypeCategories, "Warning: UnloadTrigger has invalid fillTypeCategory '%s'.") |
162 | elseif fillTypeCategories == nil and fillTypeNames ~= nil then |
163 | fillTypes = g_fillTypeManager:getFillTypesByNames(fillTypeNames, "Warning: UnloadTrigger has invalid fillType '%s'.") |
164 | end |
165 | if fillTypes ~= nil then |
166 | for _,fillType in pairs(fillTypes) do |
167 | self.fillTypes[fillType] = true |
168 | end |
169 | else |
170 | self.fillTypes = nil |
171 | end |
172 | |
173 | self.autoStart = xmlFile:getValue(xmlNode .. "#autoStart", false) |
174 | self.hasInfiniteCapacity = xmlFile:getValue(xmlNode .. "#infiniteCapacity", false) |
175 | |
176 | self.startFillText = g_i18n:convertText(xmlFile:getValue(xmlNode .. "#startFillText", "$l10n_action_siloStartFilling")) |
177 | self.stopFillText = g_i18n:convertText(xmlFile:getValue(xmlNode .. "#stopFillText", "$l10n_action_siloStopFilling" )) |
178 | |
179 | self.activatable = LoadTriggerActivatable.new(self) |
180 | self.activatable:setText(self.startFillText) |
181 | |
182 | self.isLoading = false |
183 | self.selectedFillType = FillType.UNKNOWN |
184 | |
185 | self.automaticFilling = Platform.gameplay.automaticFilling |
186 | self.requiresActiveVehicle = not self.automaticFilling |
187 | self.automaticFillingTimer = 0 |
188 | |
189 | return true |
190 | end |
222 | function LoadTrigger:loadTriggerCallback(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId) |
223 | local fillableObject = g_currentMission:getNodeObject(otherId) |
224 | if fillableObject ~= nil then |
225 | if fillableObject ~= self.source and fillableObject.getRootVehicle ~= nil and fillableObject.getFillUnitIndexFromNode ~= nil then |
226 | local fillTypes = self.source:getSupportedFillTypes() |
227 | |
228 | if fillTypes ~= nil then |
229 | local foundFillUnitIndex = fillableObject:getFillUnitIndexFromNode(otherId) |
230 | |
231 | if foundFillUnitIndex ~= nil then |
232 | local found = false |
233 | for fillTypeIndex, state in pairs(fillTypes) do |
234 | if state and (self.fillTypes == nil or self.fillTypes[fillTypeIndex]) then |
235 | if fillableObject:getFillUnitSupportsFillType(foundFillUnitIndex, fillTypeIndex) then |
236 | if fillableObject:getFillUnitAllowsFillType(foundFillUnitIndex, fillTypeIndex) then |
237 | found = true |
238 | break |
239 | end |
240 | end |
241 | end |
242 | end |
243 | |
244 | -- ignore fillUnitIndex if does not support or allow one of the provided filltypes |
245 | if not found then |
246 | foundFillUnitIndex = nil |
247 | end |
248 | end |
249 | |
250 | if foundFillUnitIndex == nil then |
251 | for fillTypeIndex, state in pairs(fillTypes) do |
252 | if state and (self.fillTypes == nil or self.fillTypes[fillTypeIndex]) then |
253 | local fillUnits = fillableObject:getFillUnits() |
254 | for fillUnitIndex, fillUnit in ipairs(fillUnits) do |
255 | -- only check fill units without exactFillRootNodes |
256 | if fillUnit.exactFillRootNode == nil then |
257 | if fillableObject:getFillUnitSupportsFillType(fillUnitIndex, fillTypeIndex) then |
258 | if fillableObject:getFillUnitAllowsFillType(fillUnitIndex, fillTypeIndex) then |
259 | foundFillUnitIndex = fillUnitIndex |
260 | break |
261 | end |
262 | end |
263 | end |
264 | end |
265 | end |
266 | end |
267 | end |
268 | |
269 | if foundFillUnitIndex ~= nil then |
270 | if onEnter then |
271 | self.fillableObjects[otherId] = {object=fillableObject, fillUnitIndex=foundFillUnitIndex} |
272 | fillableObject:addDeleteListener(self) |
273 | elseif onLeave then |
274 | self.fillableObjects[otherId] = nil |
275 | fillableObject:removeDeleteListener(self) |
276 | |
277 | if self.isLoading and self.currentFillableObject == fillableObject then |
278 | self:setIsLoading(false) |
279 | end |
280 | |
281 | if fillableObject == self.validFillableObject then |
282 | self.validFillableObject = nil |
283 | self.validFillableFillUnitIndex = nil |
284 | end |
285 | end |
286 | |
287 | if self.automaticFilling then |
288 | if not self.isLoading then |
289 | if next(self.fillableObjects) ~= nil then |
290 | if self:getIsFillableObjectAvailable() then |
291 | self:toggleLoading() |
292 | end |
293 | end |
294 | end |
295 | else |
296 | if next(self.fillableObjects) ~= nil then |
297 | g_currentMission.activatableObjectsSystem:addActivatable(self.activatable) |
298 | else |
299 | g_currentMission.activatableObjectsSystem:removeActivatable(self.activatable) |
300 | end |
301 | end |
302 | end |
303 | end |
304 | end |
305 | end |
306 | end |
19 | function LoadTrigger.registerXMLPaths(schema, basePath) |
20 | schema:register(XMLValueType.NODE_INDEX, basePath .. "#triggerNode", "Trigger node") |
21 | schema:register(XMLValueType.FLOAT, basePath .. "#fillLitersPerSecond", "Fill liters per second") |
22 | schema:register(XMLValueType.NODE_INDEX, basePath .. "#dischargeNode", "Discharge node") |
23 | schema:register(XMLValueType.FLOAT, basePath .. "#dischargeWidth", "Discharge width", 0.5) |
24 | schema:register(XMLValueType.FLOAT, basePath .. "#dischargeLength", "Discharge length", 0.5) |
25 | |
26 | schema:register(XMLValueType.STRING, basePath .. "#fillSoundIdentifier", "Fill sound identifier in map sound xml") |
27 | schema:register(XMLValueType.NODE_INDEX, basePath .. "#fillSoundNode", "Fill sound link node") |
28 | |
29 | EffectManager.registerEffectXMLPaths(schema, basePath) |
30 | |
31 | schema:register(XMLValueType.NODE_INDEX, basePath .. "#scrollerNode", "Scroller node") |
32 | schema:register(XMLValueType.STRING, basePath .. "#shaderParameterName", "Scroller shader parameter name", "uvScrollSpeed") |
33 | schema:register(XMLValueType.VECTOR_2, basePath .. "#scrollerScrollSpeed", "Scroller speed scale", "0 -0.75") |
34 | |
35 | schema:register(XMLValueType.STRING, basePath .. "#fillTypeCategories", "Supported fill type categories") |
36 | schema:register(XMLValueType.STRING, basePath .. "#fillTypes", "Supported fill types") |
37 | |
38 | schema:register(XMLValueType.BOOL, basePath .. "#autoStart", "Auto start loading", false) |
39 | schema:register(XMLValueType.BOOL, basePath .. "#infiniteCapacity", "Has infinite capacity", false) |
40 | schema:register(XMLValueType.STRING, basePath .. "#startFillText", "Start fill text") |
41 | schema:register(XMLValueType.STRING, basePath .. "#stopFillText", "Stop fill text") |
42 | |
43 | schema:register(XMLValueType.NODE_INDEX, basePath .. "#aiNode", "AI target node, required for the station to support AI. AI drives to the node in positive Z direction. Height is not relevant.") |
44 | end |
373 | function LoadTrigger:toggleLoading() |
374 | if not self.isLoading then |
375 | local fillLevels = self.source:getAllFillLevels(g_currentMission:getFarmId()) |
376 | |
377 | local fillableObject = self.validFillableObject |
378 | local fillUnitIndex = self.validFillableFillUnitIndex |
379 | |
380 | local firstFillType = nil |
381 | local validFillLevels = {} |
382 | local numFillTypes = 0 |
383 | for fillTypeIndex, fillLevel in pairs(fillLevels) do |
384 | if self.fillTypes == nil or self.fillTypes[fillTypeIndex] then |
385 | if fillableObject:getFillUnitAllowsFillType(fillUnitIndex, fillTypeIndex) then |
386 | validFillLevels[fillTypeIndex] = fillLevel |
387 | |
388 | if firstFillType == nil then |
389 | firstFillType = fillTypeIndex |
390 | end |
391 | |
392 | numFillTypes = numFillTypes + 1 |
393 | end |
394 | end |
395 | end |
396 | |
397 | if not self.autoStart and numFillTypes > 1 then |
398 | local startAllowed = true |
399 | local controlledVehicle = g_currentMission.controlledVehicle |
400 | if controlledVehicle.getIsActiveForInput ~= nil then |
401 | startAllowed = controlledVehicle:getIsActiveForInput(true) |
402 | end |
403 | |
404 | -- allow popup only for the vehicle that controlled by the player |
405 | if startAllowed then |
406 | local text = string.format("%s", self.source:getName()) |
407 | |
408 | g_gui:showSiloDialog({title=text, fillLevels=validFillLevels, callback=self.onFillTypeSelection, target=self, hasInfiniteCapacity = self.hasInfiniteCapacity}) |
409 | |
410 | if GS_IS_MOBILE_VERSION then |
411 | local rootVehicle = fillableObject.rootVehicle |
412 | if rootVehicle.brakeToStop ~= nil then |
413 | rootVehicle:brakeToStop() |
414 | end |
415 | end |
416 | end |
417 | else |
418 | self:onFillTypeSelection(firstFillType) |
419 | end |
420 | else |
421 | self:setIsLoading(false) |
422 | end |
423 | end |