LUADOC - Farming Simulator 22

Script v1_7_1_0

Engine v1_7_1_0

Foundation Reference

PlaceableSilo

Description
Specialization for placeables
Functions

canBeSold

Description
Definition
canBeSold()
Code
336function PlaceableSilo:canBeSold(superFunc)
337 local spec = self.spec_silo
338 -- We do not support selling silos used by more than one farm because of the gameplay complexity. (What do to with contents, when to allow)
339 if spec.storagePerFarm then
340 return false, nil
341 end
342
343 local warning = spec.sellWarningText .. "\n"
344 local totalFillLevel = 0
345
346 spec.totalFillTypeSellPrice = 0
347 for fillTypeIndex, fillLevel in pairs(spec.storages[1].fillLevels) do
348 totalFillLevel = totalFillLevel + fillLevel
349
350 if fillLevel > 0 then
351 local lowestSellPrice = math.huge
352
353 for _, unloadingStation in pairs(g_currentMission.storageSystem:getUnloadingStations()) do
354 if unloadingStation.owningPlaceable ~= nil
355 and unloadingStation.isSellingPoint
356 and unloadingStation.acceptedFillTypes[fillTypeIndex] then
357 local price = unloadingStation:getEffectiveFillTypePrice(fillTypeIndex)
358
359 if price > 0 then
360 lowestSellPrice = math.min(lowestSellPrice, price)
361 end
362 end
363 end
364
365 if lowestSellPrice == math.huge then
366 lowestSellPrice = 0.5
367 end
368
369 local price = fillLevel * lowestSellPrice * PlaceableSilo.PRICE_SELL_FACTOR
370 local fillType = g_fillTypeManager:getFillTypeByIndex(fillTypeIndex)
371 warning = string.format("%s%s (%s) - %s: %s\n", warning, fillType.title, g_i18n:formatVolume(fillLevel), g_i18n:getText("ui_sellValue"), g_i18n:formatMoney(price, 0, true, true))
372 spec.totalFillTypeSellPrice = spec.totalFillTypeSellPrice + price
373 end
374 end
375
376 if totalFillLevel > 0 then
377 return true, warning
378 end
379
380 return true, nil
381end

collectPickObjects

Description
Definition
collectPickObjects()
Code
309function PlaceableSilo:collectPickObjects(superFunc, node)
310 local spec = self.spec_silo
311
312 local foundNode = false
313 for _, unloadTrigger in ipairs(spec.unloadingStation.unloadTriggers) do
314 if node == unloadTrigger.exactFillRootNode then
315 foundNode = true
316 break
317 end
318 end
319
320 if not foundNode then
321 for _, loadTrigger in ipairs(spec.loadingStation.loadTriggers) do
322 if node == loadTrigger.triggerNode then
323 foundNode = true
324 break
325 end
326 end
327 end
328
329 if not foundNode then
330 superFunc(self, node)
331 end
332end

getFillLevels

Description
Definition
getFillLevels()
Code
485function PlaceableSilo:getFillLevels()
486 local spec = self.spec_silo
487
488 local validFillLevels = {}
489 for _, storage in ipairs(spec.storages) do
490 for fillTypeIndex, fillLevel in pairs(storage:getFillLevels()) do
491 if self.fillTypes == nil or self.fillTypes[fillTypeIndex] then
492 validFillLevels[fillTypeIndex] = fillLevel
493 end
494 end
495 end
496 return validFillLevels
497end

getSpecValueVolume

Description
Definition
getSpecValueVolume()
Code
572function PlaceableSilo.getSpecValueVolume(storeItem, realItem)
573 if storeItem.specs.siloVolume == nil then
574 return nil
575 end
576
577 return g_i18n:formatVolume(storeItem.specs.siloVolume)
578end

initSpecialization

Description
Definition
initSpecialization()
Code
80function PlaceableSilo.initSpecialization()
81 g_storeManager:addSpecType("siloVolume", "shopListAttributeIconCapacity", PlaceableSilo.loadSpecValueVolume, PlaceableSilo.getSpecValueVolume, "placeable")
82end

loadFromXMLFile

Description
Definition
loadFromXMLFile()
Code
385function PlaceableSilo:loadFromXMLFile(xmlFile, key)
386 local spec = self.spec_silo
387
388 xmlFile:iterate(key .. ".storage", function(_, storageKey)
389 local index = xmlFile:getValue(storageKey.."#index")
390
391 if index ~= nil then
392 if spec.storages[index] ~= nil then
393 if not spec.storages[index]:loadFromXMLFile(xmlFile, storageKey) then
394 return false
395 end
396 end
397 end
398 end)
399end

loadSpecValueVolume

Description
Definition
loadSpecValueVolume()
Code
566function PlaceableSilo.loadSpecValueVolume(xmlFile, customEnvironment, baseDir)
567 return xmlFile:getValue("placeable.silo.storages.storage(0)#capacity")
568end

onDelete

Description
Definition
onDelete()
Code
144function PlaceableSilo:onDelete()
145 local spec = self.spec_silo
146
147 local storageSystem = g_currentMission.storageSystem
148 if spec.storages ~= nil then
149 for _, storage in ipairs(spec.storages) do
150 if spec.unloadingStation ~= nil then
151 storageSystem:removeStorageFromUnloadingStations(storage, {spec.unloadingStation})
152 end
153 if spec.loadingStation ~= nil then
154 storageSystem:removeStorageFromLoadingStations(storage, {spec.loadingStation})
155 end
156
157 storage:removeFillLevelChangedListeners(spec.storageFilLLevelChangedCallback)
158 storageSystem:removeStorage(storage)
159 end
160
161 -- delete storages later to avoid access to already deleted storages
162 for _, storage in ipairs(spec.storages) do
163 storage:delete()
164 end
165 end
166
167 if spec.unloadingStation ~= nil then
168 storageSystem:removeUnloadingStation(spec.unloadingStation, self)
169 spec.unloadingStation:delete()
170 end
171
172 if spec.loadingStation ~= nil then
173 if spec.loadingStation:getIsFillTypeSupported(FillType.LIQUIDMANURE) then
174 g_currentMission:removeLiquidManureLoadingStation(spec.loadingStation)
175 end
176
177 storageSystem:removeLoadingStation(spec.loadingStation, self)
178 spec.loadingStation:delete()
179 end
180
181 g_currentMission.activatableObjectsSystem:removeActivatable(spec.activatable)
182
183 if spec.playerActionTrigger ~= nil then
184 removeTrigger(spec.playerActionTrigger)
185 end
186end

onFinalizePlacement

Description
Definition
onFinalizePlacement()
Code
190function PlaceableSilo:onFinalizePlacement()
191 local spec = self.spec_silo
192
193 local storageSystem = g_currentMission.storageSystem
194
195 spec.unloadingStation:register(true)
196 storageSystem:addUnloadingStation(spec.unloadingStation, self)
197
198 if spec.loadingStation ~= nil then
199 spec.loadingStation:register(true)
200 storageSystem:addLoadingStation(spec.loadingStation, self)
201
202 if spec.loadingStation:getIsFillTypeSupported(FillType.LIQUIDMANURE) then
203 g_currentMission:addLiquidManureLoadingStation(spec.loadingStation)
204 end
205 end
206
207 for _, storage in ipairs(spec.storages) do
208 if not spec.storagePerFarm then
209 storage:setOwnerFarmId(self:getOwnerFarmId(), true)
210 end
211
212 storageSystem:addStorage(storage)
213
214 storage:register(true)
215
216 storageSystem:addStorageToUnloadingStation(storage, spec.unloadingStation)
217 storageSystem:addStorageToLoadingStation(storage, spec.loadingStation)
218 end
219
220 -- now check if there are some storages in range which can also be used
221 local storagesInRange = storageSystem:getStorageExtensionsInRange(spec.unloadingStation, self:getOwnerFarmId())
222 if storagesInRange ~= nil then
223 for _, storage in ipairs(storagesInRange) do
224 if spec.unloadingStation.targetStorages[storage] == nil then
225 storageSystem:addStorageToUnloadingStation(storage, spec.unloadingStation)
226 end
227 end
228 end
229
230 storagesInRange = storageSystem:getStorageExtensionsInRange(spec.loadingStation, self:getOwnerFarmId())
231 if storagesInRange ~= nil then
232 for _, storage in ipairs(storagesInRange) do
233 if spec.loadingStation.sourceStorages[storage] == nil then
234 storageSystem:addStorageToLoadingStation(storage, spec.loadingStation)
235 end
236 end
237 end
238
239 if not spec.storagePerFarm then
240 -- For the very first silo on easy, fill it. The startSiloAmounts are only set on game creation.
241 -- In case of no silo on the map this code is used for the first silo placed in new savegame.
242 local num = 0
243 for _, placeable in pairs(g_currentMission.placeables) do
244 if placeable:getOwnerFarmId() == self:getOwnerFarmId() and placeable.spec_silo ~= nil then
245 num = num + 1
246 end
247 end
248
249 if num == 1 and g_currentMission.missionInfo.difficulty == 1 and g_currentMission.missionInfo.startSiloAmounts ~= nil and not g_currentMission.missionInfo:getIsLoadedFromSavegame() and not g_currentMission.missionInfo.hasLoadedFirstFilledSilo then
250 -- This is to circumvent a cheat: load new easy game, sell silo, place silo (it is filled now), sell silo, etc.
251 -- No need to save it as this code does not run on savegames
252 g_currentMission.missionInfo.hasLoadedFirstFilledSilo = true
253
254 for fillTypeName, amount in pairs(g_currentMission.missionInfo.startSiloAmounts) do
255 local fillTypeIndex = g_fillTypeManager:getFillTypeIndexByName(fillTypeName)
256 self:setAmount(fillTypeIndex, amount)
257 end
258 end
259 end
260
261 if spec.playerActionTrigger ~= nil then
262 addTrigger(spec.playerActionTrigger, "onPlayerActionTriggerCallback", self)
263 end
264
265end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
87function PlaceableSilo:onLoad(savegame)
88 local spec = self.spec_silo
89 local xmlFile = self.xmlFile
90
91 spec.playerActionTrigger = xmlFile:getValue("placeable.silo#playerActionTrigger", nil, self.components, self.i3dMappings)
92
93 if spec.playerActionTrigger ~= nil then
94 spec.activatable = PlaceableSiloActivatable.new(self)
95 end
96
97 spec.storagePerFarm = xmlFile:getValue("placeable.silo.storages#perFarm", false)
98 spec.foreignSilo = xmlFile:getValue("placeable.silo.storages#foreignSilo", spec.storagePerFarm) -- Shows as foreign silo in the menu
99
100 spec.unloadingStation = UnloadingStation.new(self.isServer, self.isClient)
101 spec.unloadingStation:load(self.components, xmlFile, "placeable.silo.unloadingStation", self.customEnvironment, self.i3dMappings, self.components[1].node)
102 spec.unloadingStation.owningPlaceable = self
103 spec.unloadingStation.hasStoragePerFarm = spec.storagePerFarm
104
105 spec.loadingStation = LoadingStation.new(self.isServer, self.isClient)
106 spec.loadingStation:load(self.components, xmlFile, "placeable.silo.loadingStation", self.customEnvironment, self.i3dMappings, self.components[1].node)
107 spec.loadingStation.owningPlaceable = self
108 spec.loadingStation.hasStoragePerFarm = spec.storagePerFarm
109
110 spec.fillTypesAndLevelsAuxiliary = {}
111 spec.fillTypeToFillTypeStorageTable = {}
112 spec.infoTriggerFillTypesAndLevels = {}
113
114 local numStorageSets = spec.storagePerFarm and FarmManager.MAX_NUM_FARMS or 1
115 if not g_currentMission.missionDynamicInfo.isMultiplayer then
116 numStorageSets = 1
117 end
118
119 spec.storages = {}
120 local i = 0
121 while true do
122 local storageKey = string.format("placeable.silo.storages.storage(%d)", i)
123 if not xmlFile:hasProperty(storageKey) then
124 break
125 end
126
127 for j = 1, numStorageSets do
128 local storage = Storage.new(self.isServer, self.isClient)
129 if storage:load(self.components, xmlFile, storageKey, self.i3dMappings) then
130 storage.ownerFarmId = j
131 storage.foreignSilo = spec.foreignSilo -- Pass along for usage by prices menu
132 table.insert(spec.storages, storage)
133 end
134 end
135
136 i = i + 1
137 end
138
139 spec.sellWarningText = g_i18n:convertText(xmlFile:getValue("placeable.silo#sellWarningText", "$l10n_info_siloExtensionNotEmpty"))
140end

onPlayerActionTriggerCallback

Description
Definition
onPlayerActionTriggerCallback()
Code
513function PlaceableSilo:onPlayerActionTriggerCallback(triggerId, otherId, onEnter, onLeave, onStay)
514 local spec = self.spec_silo
515 if self:getOwnerFarmId() == g_currentMission:getFarmId() then
516 if g_currentMission.player ~= nil and otherId == g_currentMission.player.rootNode then
517 if onEnter then
518 g_currentMission.activatableObjectsSystem:addActivatable(spec.activatable)
519 else
520 g_currentMission.activatableObjectsSystem:removeActivatable(spec.activatable)
521 end
522 end
523 end
524end

onReadStream

Description
Definition
onReadStream()
Code
269function PlaceableSilo:onReadStream(streamId, connection)
270 local spec = self.spec_silo
271
272 local unloadingStationId = NetworkUtil.readNodeObjectId(streamId)
273 spec.unloadingStation:readStream(streamId, connection)
274 g_client:finishRegisterObject(spec.unloadingStation, unloadingStationId)
275
276 local loadingStationId = NetworkUtil.readNodeObjectId(streamId)
277 spec.loadingStation:readStream(streamId, connection)
278 g_client:finishRegisterObject(spec.loadingStation, loadingStationId)
279
280 for _, storage in ipairs(spec.storages) do
281 local storageId = NetworkUtil.readNodeObjectId(streamId)
282 storage:readStream(streamId, connection)
283 g_client:finishRegisterObject(storage, storageId)
284 end
285end

onSell

Description
Definition
onSell()
Code
501function PlaceableSilo:onSell()
502 local spec = self.spec_silo
503
504 if self.isServer then
505 if spec.totalFillTypeSellPrice > 0 then
506 g_currentMission:addMoney(spec.totalFillTypeSellPrice, self:getOwnerFarmId(), MoneyType.HARVEST_INCOME, true, true)
507 end
508 end
509end

onWriteStream

Description
Definition
onWriteStream()
Code
289function PlaceableSilo:onWriteStream(streamId, connection)
290 local spec = self.spec_silo
291
292 NetworkUtil.writeNodeObjectId(streamId, NetworkUtil.getObjectId(spec.unloadingStation))
293 spec.unloadingStation:writeStream(streamId, connection)
294 g_server:registerObjectInStream(connection, spec.unloadingStation)
295
296 NetworkUtil.writeNodeObjectId(streamId, NetworkUtil.getObjectId(spec.loadingStation))
297 spec.loadingStation:writeStream(streamId, connection)
298 g_server:registerObjectInStream(connection, spec.loadingStation)
299
300 for _, storage in ipairs(spec.storages) do
301 NetworkUtil.writeNodeObjectId(streamId, NetworkUtil.getObjectId(storage))
302 storage:writeStream(streamId, connection)
303 g_server:registerObjectInStream(connection, storage)
304 end
305end

prerequisitesPresent

Description
Checks if all prerequisite specializations are loaded
Definition
prerequisitesPresent(table specializations)
Arguments
tablespecializationsspecializations
Return Values
booleanhasPrerequisitetrue if all prerequisite specializations are loaded
Code
21function PlaceableSilo.prerequisitesPresent(specializations)
22 return true
23end

refillAmount

Description
Definition
refillAmount()
Code
451function PlaceableSilo:refillAmount(fillTypeIndex, amount, price)
452 if fillTypeIndex == nil or amount == nil or price == nil then
453 return
454 end
455
456 if not self.isServer then
457 g_client:getServerConnection():sendEvent(PlaceableSiloRefillEvent.new(self, fillTypeIndex, amount, price))
458 return
459 end
460
461 local spec = self.spec_silo
462 for _, storage in ipairs(spec.storages) do
463 local freeCapacity = storage:getFreeCapacity(fillTypeIndex)
464 if freeCapacity > 0 then
465 local moved = math.min(amount, freeCapacity)
466 local fillLevel = storage:getFillLevel(fillTypeIndex)
467 storage:setFillLevel(fillLevel + moved, fillTypeIndex)
468
469 amount = amount - moved
470 end
471
472 if amount <= 0.001 then
473 break
474 end
475 end
476
477 if self.isServer then
478 g_currentMission:addMoney(-price, self:getOwnerFarmId(), MoneyType.BOUGHT_MATERIALS, true)
479 end
480 g_currentMission:showMoneyChange(MoneyType.BOUGHT_MATERIALS)
481end

registerEventListeners

Description
Definition
registerEventListeners()
Code
45function PlaceableSilo.registerEventListeners(placeableType)
46 SpecializationUtil.registerEventListener(placeableType, "onLoad", PlaceableSilo)
47 SpecializationUtil.registerEventListener(placeableType, "onDelete", PlaceableSilo)
48 SpecializationUtil.registerEventListener(placeableType, "onFinalizePlacement", PlaceableSilo)
49 SpecializationUtil.registerEventListener(placeableType, "onReadStream", PlaceableSilo)
50 SpecializationUtil.registerEventListener(placeableType, "onWriteStream", PlaceableSilo)
51 SpecializationUtil.registerEventListener(placeableType, "onSell", PlaceableSilo)
52end

registerFunctions

Description
Definition
registerFunctions()
Code
36function PlaceableSilo.registerFunctions(placeableType)
37 SpecializationUtil.registerFunction(placeableType, "setAmount", PlaceableSilo.setAmount)
38 SpecializationUtil.registerFunction(placeableType, "refillAmount", PlaceableSilo.refillAmount)
39 SpecializationUtil.registerFunction(placeableType, "getFillLevels", PlaceableSilo.getFillLevels)
40 SpecializationUtil.registerFunction(placeableType, "onPlayerActionTriggerCallback", PlaceableSilo.onPlayerActionTriggerCallback)
41end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
27function PlaceableSilo.registerOverwrittenFunctions(placeableType)
28 SpecializationUtil.registerOverwrittenFunction(placeableType, "collectPickObjects", PlaceableSilo.collectPickObjects)
29 SpecializationUtil.registerOverwrittenFunction(placeableType, "setOwnerFarmId", PlaceableSilo.setOwnerFarmId)
30 SpecializationUtil.registerOverwrittenFunction(placeableType, "canBeSold", PlaceableSilo.canBeSold)
31 SpecializationUtil.registerOverwrittenFunction(placeableType, "updateInfo", PlaceableSilo.updateInfo)
32end

registerSavegameXMLPaths

Description
Definition
registerSavegameXMLPaths()
Code
71function PlaceableSilo.registerSavegameXMLPaths(schema, basePath)
72 schema:setXMLSpecializationType("Silo")
73 schema:register(XMLValueType.INT, basePath .. ".storage(?)#index", "Storage index")
74 Storage.registerSavegameXMLPaths(schema, basePath .. ".storage(?)")
75 schema:setXMLSpecializationType()
76end

registerXMLPaths

Description
Definition
registerXMLPaths()
Code
56function PlaceableSilo.registerXMLPaths(schema, basePath)
57 schema:setXMLSpecializationType("Silo")
58 schema:register(XMLValueType.STRING, basePath .. ".silo#sellWarningText", "Sell warning text")
59 schema:register(XMLValueType.NODE_INDEX, basePath .. ".silo#playerActionTrigger", "Trigger for player interaction")
60 schema:register(XMLValueType.BOOL, basePath .. ".silo.storages#perFarm", "Silo is per farm", false)
61 schema:register(XMLValueType.BOOL, basePath .. ".silo.storages#foreignSilo", "Shows as foreign silo in the menu", false)
62 UnloadingStation.registerXMLPaths(schema, basePath .. ".silo.unloadingStation")
63 LoadingStation.registerXMLPaths(schema, basePath .. ".silo.loadingStation")
64 schema:register(XMLValueType.NODE_INDEX, basePath .. ".silo.storages.storage(?)#node", "Storage node")
65 Storage.registerXMLPaths(schema, basePath .. ".silo.storages.storage(?)")
66 schema:setXMLSpecializationType()
67end

saveToXMLFile

Description
Definition
saveToXMLFile()
Code
403function PlaceableSilo:saveToXMLFile(xmlFile, key, usedModNames)
404 local spec = self.spec_silo
405
406 for k, storage in ipairs(spec.storages) do
407 local storageKey = string.format("%s.storage(%d)", key, k-1)
408 xmlFile:setValue(storageKey .. "#index", k)
409 storage:saveToXMLFile(xmlFile, storageKey, usedModNames)
410 end
411end

setAmount

Description
Definition
setAmount()
Code
431function PlaceableSilo:setAmount(fillType, amount)
432 local spec = self.spec_silo
433
434 for _, storage in ipairs(spec.storages) do
435 local capacity = storage:getFreeCapacity(fillType)
436 if capacity > 0 then
437 local moved = math.min(amount, capacity)
438 storage:setFillLevel(moved, fillType)
439
440 amount = amount - moved
441 end
442
443 if amount <= 0.001 then
444 break
445 end
446 end
447end

setOwnerFarmId

Description
Definition
setOwnerFarmId()
Code
415function PlaceableSilo:setOwnerFarmId(superFunc, farmId, noEventSend)
416 local spec = self.spec_silo
417
418 superFunc(self, farmId, noEventSend)
419
420 if self.isServer and not spec.storagePerFarm then
421 if spec.storages ~= nil then
422 for _, storage in ipairs(spec.storages) do
423 storage:setOwnerFarmId(farmId, true)
424 end
425 end
426 end
427end

updateInfo

Description
Definition
updateInfo()
Code
528function PlaceableSilo:updateInfo(superFunc, infoTable)
529 superFunc(self, infoTable)
530 local spec = self.spec_silo
531
532 -- collect all fillTypes and levels from storage
533
534 local farmId = g_currentMission:getFarmId()
535 for fillType, fillLevel in pairs(spec.loadingStation:getAllFillLevels(farmId)) do
536 spec.fillTypesAndLevelsAuxiliary[fillType] = (spec.fillTypesAndLevelsAuxiliary[fillType] or 0) + fillLevel
537 end
538
539 -- filter empty fillType, merge to index table for sorting
540 table.clear(spec.infoTriggerFillTypesAndLevels)
541 for fillType, fillLevel in pairs(spec.fillTypesAndLevelsAuxiliary) do
542 if fillLevel > 0.1 then
543 spec.fillTypeToFillTypeStorageTable[fillType] = spec.fillTypeToFillTypeStorageTable[fillType] or {fillType=fillType, fillLevel=fillLevel}
544 spec.fillTypeToFillTypeStorageTable[fillType].fillLevel = fillLevel
545 table.insert(spec.infoTriggerFillTypesAndLevels, spec.fillTypeToFillTypeStorageTable[fillType])
546 end
547 end
548
549 table.clear(spec.fillTypesAndLevelsAuxiliary)
550
551 table.sort(spec.infoTriggerFillTypesAndLevels, function(a, b) return a.fillLevel > b.fillLevel end)
552
553 local numEntries = math.min(#spec.infoTriggerFillTypesAndLevels, PlaceableSilo.INFO_TRIGGER_NUM_DISPLAYED_FILLTYPES)
554 if numEntries > 0 then
555 for i=1, numEntries do
556 local fillTypeAndLevel = spec.infoTriggerFillTypesAndLevels[i]
557 table.insert(infoTable, {title=g_fillTypeManager:getFillTypeTitleByIndex(fillTypeAndLevel.fillType), text=g_i18n:formatVolume(fillTypeAndLevel.fillLevel, 0)})
558 end
559 else
560 table.insert(infoTable, {title=g_i18n:getText("infohud_siloEmpty"), text=""})
561 end
562end