LUADOC - Farming Simulator 17

Printable Version

Script v1.4.4.0

Engine v7.0.0.2

Foundation Reference

Fillable

Description
This is the specialization for fillable vehicles, such as trailers or sprayers
Functions

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
19function Fillable.prerequisitesPresent(specializations)
20 return true;
21end

preLoad

Description
Called before loading
Definition
preLoad(table savegame)
Arguments
tablesavegamesavegame
Code
26function Fillable:preLoad(savegame)
27 self.getAllowFillFromAir = Fillable.getAllowFillFromAir;
28 self.getDrawFirstFillText = Utils.overwrittenFunction(self.getDrawFirstFillText, Fillable.getDrawFirstFillText);
29end

load

Description
Called on loading
Definition
load(table savegame)
Arguments
tablesavegamesavegame
Code
34function Fillable:load(savegame)
35
36 Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.capacity", "vehicle.fillUnits.fillUnit#capacity")
37 Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.fillTypes", "vehicle.fillUnits.fillUnit#fillTypes")
38 Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.fruitTypes", "vehicle.fillUnits.fillUnit#fillTypes")
39
40 self.allowFillType = Fillable.allowFillType;
41 self.getFillUnitsWithFillType = Fillable.getFillUnitsWithFillType;
42 self.resetFillLevelIfNeeded = Fillable.resetFillLevelIfNeeded;
43
44 self.setFillLevel = Fillable.setFillLevel;
45 self.getFillLevel = Fillable.getFillLevel;
46 self.getCurrentFillTypes = Fillable.getCurrentFillTypes;
47 self.getCapacity = Fillable.getCapacity;
48 self.getFreeCapacity = Fillable.getFreeCapacity;
49 self.resetUnitFillLevelIfNeeded = Fillable.resetUnitFillLevelIfNeeded;
50
51 self.allowUnitFillType = Fillable.allowUnitFillType;
52 self.getUnitFillTypes = Fillable.getUnitFillTypes;
53 self.getUnitFillType = Fillable.getUnitFillType;
54 self.getUnitLastValidFillType = Fillable.getUnitLastValidFillType;
55 self.setUnitLastValidFillType = Fillable.setUnitLastValidFillType;
56 self.getUnitFillLevel = Fillable.getUnitFillLevel;
57 self.setUnitFillLevel = Fillable.setUnitFillLevel;
58 self.getUnitCapacity = Fillable.getUnitCapacity;
59 self.setUnitCapacity = Fillable.setUnitCapacity;
60
61 self.getFirstEnabledFillType = Fillable.getFirstEnabledFillType;
62 self.setLastValidFillType = SpecializationUtil.callSpecializationsFunction("setLastValidFillType");
63 self.updateMeasurementNode = Fillable.updateMeasurementNode;
64 self.attachPipe = Fillable.attachPipe;
65 self.detachPipe = Fillable.detachPipe;
66
67 self.supportsFillTriggers = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.supportsFillTriggers#value"), self.supportsFillTriggers);
68
69 if self.supportsFillTriggers then
70 assert(self.setIsFilling == nil, "Fillable needs to be the first specialization which implements setIsFilling");
71 self.setIsFilling = Fillable.setIsFilling;
72 self.addFillTrigger = Fillable.addFillTrigger;
73 self.removeFillTrigger = Fillable.removeFillTrigger;
74 self.fillLitersPerSecond = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.fillLitersPerSecond"), 500);
75 local unitFillTime = getXMLFloat(self.xmlFile, "vehicle.unitFillTime");
76 if unitFillTime ~= nil then
77 self.unitFillTime = unitFillTime * 1000;
78 end
79 self.currentFillTime = 0;
80 self.fillTriggers = {};
81 self.fillActivatable = FillActivatable:new(self);
82 self.isFilling = false;
83 end
84
85 self.fillTypeChangeThreshold = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.fillTypeChangeThreshold"), 0.05); -- fill level percentage that still allows overriding with another fill type
86
87 self.fillUnits = {};
88 local i=0;
89 while true do
90 local key = string.format("vehicle.fillUnits.fillUnit(%d)", i);
91 if not hasXMLProperty(self.xmlFile, key) then
92 break;
93 end
94 local entry = {};
95
96 entry.fillUnitIndex = i+1;
97 entry.fillVolumeIndex = Utils.getNoNil(getXMLInt(self.xmlFile, key .. "#fillVolumeIndex"), entry.fillUnitIndex);
98
99 entry.currentFillType = FillUtil.FILLTYPE_UNKNOWN;
100 entry.lastValidFillType = FillUtil.FILLTYPE_UNKNOWN;
101 entry.fillLevel = 0;
102
103 if self.isServer then
104 entry.sentFillType = entry.currentFillType;
105 entry.sentFillLevel = entry.fillLevel;
106 end
107
108 entry.capacity = getXMLFloat(self.xmlFile, key .. "#capacity");
109 entry.unit = getXMLString(self.xmlFile, key .. "#unit");
110 entry.showOnHud = Utils.getNoNil(getXMLBool(self.xmlFile, key .. "#showOnHud"), true);
111
112 entry.fillTypes = {};
113 local fillTypes = {};
114 local fillTypeCategories = getXMLString(self.xmlFile, key .. "#fillTypeCategories");
115 local fillTypeNames = getXMLString(self.xmlFile, key .. "#fillTypes");
116 if fillTypeCategories ~= nil and fillTypeNames == nil then
117 fillTypes = FillUtil.getFillTypeByCategoryName(fillTypeCategories, "Warning: '"..self.configFileName.. "' has invalid fillTypeCategory '%s'.")
118 elseif fillTypeCategories == nil and fillTypeNames ~= nil then
119 fillTypes = FillUtil.getFillTypesByNames(fillTypeNames, "Warning: '"..self.configFileName.. "' has invalid fillType '%s'.")
120 else
121 print("Warning: '"..self.configFileName.. "' a fillUnit entry needs either the 'fillTypeCategories' or 'fillTypes' attribute.")
122 end
123
124 if fillTypes ~= nil then
125 for _,fillType in pairs(fillTypes) do
126 entry.fillTypes[fillType] = true;
127 end
128 end
129
130 entry.lastFillLevel = 0;
131 entry.fillLevelHud = VehicleHudUtils.loadHud(self, self.xmlFile, "fillLevel", nil, i);
132
133 table.insert(self.fillUnits, entry);
134 i=i+1;
135 end
136
137
138 -- fallback
139 if self.fillUnits == nil or table.getn(self.fillUnits) == 0 then
140 local entry = {};
141
142 entry.fillVolumeIndex = 1;
143
144 entry.currentFillType = FillUtil.FILLTYPE_UNKNOWN;
145 entry.lastValidFillType = FillUtil.FILLTYPE_UNKNOWN;
146 entry.fillLevel = 0;
147
148 if self.isServer then
149 entry.sentFillType = entry.currentFillType;
150 entry.sentFillLevel = entry.fillLevel;
151 end
152
153 entry.capacity = getXMLFloat(self.xmlFile, "vehicle.capacity");
154 entry.unit = getXMLString(self.xmlFile, "vehicle.capacity#unit");
155
156 entry.fillTypes = {};
157 local fillTypes = {};
158 local fillTypeCategories = getXMLString(self.xmlFile, "vehicle.fillTypeCategories");
159 local fillTypeNames = getXMLString(self.xmlFile, "vehicle.fillTypes");
160 if fillTypeCategories ~= nil and fillTypeNames == nil then
161 fillTypes = FillUtil.getFillTypeByCategoryName(fillTypeCategories, "Warning: '"..self.configFileName.. "' has invalid fillTypeCategory '%s'.")
162 elseif fillTypeCategories == nil and fillTypeNames ~= nil then
163 fillTypes = FillUtil.getFillTypesByNames(fillTypeNames, "Warning: '"..self.configFileName.. "' has invalid fillType '%s'.")
164 end
165
166 if fillTypes ~= nil then
167 for _,fillType in pairs(fillTypes) do
168 entry.fillTypes[fillType] = true;
169 end
170 end
171
172 entry.lastFillLevel = 0;
173 entry.fillLevelHud = VehicleHudUtils.loadHud(self, self.xmlFile, "fillLevel", nil, 0);
174
175 table.insert(self.fillUnits, entry);
176 end
177
178
179 self.synchronizeFillLevels = true;
180 self.synchronizeFullFillLevel = false;
181
182 self.fillRootNode = Utils.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.fillRootNode#index"));
183 if self.fillRootNode == nil then
184 self.fillRootNode = self.components[1].node;
185 end
186
187 self.fillMassNode = Utils.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.fillMassNode#index"));
188 local updateFillLevelMass = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.fillMassNode#updateFillLevelMass"), true);
189 if self.fillMassNode == nil and updateFillLevelMass then
190 self.fillMassNode = self.components[1].node;
191 end
192
193 self.exactFillRootNode = Utils.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.exactFillRootNode#index"));
194 if self.exactFillRootNode == nil then
195 self.exactFillRootNode = self.fillRootNode;
196 end
197
198 self.fillAutoAimTarget = {};
199 self.fillAutoAimTarget.node = Utils.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.fillAutoAimTargetNode#index"));
200 if self.fillAutoAimTarget.node == nil then
201 self.fillAutoAimTarget.node = self.exactFillRootNode;
202 end
203 self.fillAutoAimTarget.baseTrans = {getTranslation(self.fillAutoAimTarget.node)};
204 self.fillAutoAimTarget.startZ = getXMLFloat(self.xmlFile, "vehicle.fillAutoAimTargetNode#startZ");
205 self.fillAutoAimTarget.endZ = getXMLFloat(self.xmlFile, "vehicle.fillAutoAimTargetNode#endZ");
206 self.fillAutoAimTarget.fillUnitIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.fillAutoAimTargetNode#fillUnitIndex"), 1);
207 self.fillAutoAimTarget.startPercentage = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.fillAutoAimTargetNode#startPercentage"), 25)/100;
208 self.fillAutoAimTarget.invert = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.fillAutoAimTargetNode#invert"), false);
209 if self.fillAutoAimTarget.startZ ~= nil and self.fillAutoAimTarget.endZ ~= nil then
210 local startZ = self.fillAutoAimTarget.startZ;
211 if self.fillAutoAimTarget.invert then
212 startZ = self.fillAutoAimTarget.endZ;
213 end;
214
215 setTranslation(self.fillAutoAimTarget.node, self.fillAutoAimTarget.baseTrans[1], self.fillAutoAimTarget.baseTrans[2], startZ);
216 end;
217
218 self.attacherPipeRef = Utils.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.attacherPipe#refIndex"));
219 self.attacherPipeRefVehicle = nil;
220
221 self.attacherPipe = Utils.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.attacherPipe#index"));
222 self.attacherPipeAnimation = getXMLString(self.xmlFile, "vehicle.attacherPipe#animationName");
223 self.attacherPipeVehicle = nil;
224
225 self.allowFillFromAir = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.allowFillFromAir#value"), true);
226
227 local unloadTriggerNode = Utils.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.unloadTrigger#index"));
228 if unloadTriggerNode ~= nil then
229 self.unloadTrigger = FillTrigger:new();
230 self.unloadTrigger:load(unloadTriggerNode, nil, self);
231 end
232 self.unloadTriggerFillUnitIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.unloadTrigger#fillUnitIndex"), 1);
233
234 if self.isClient then
235
236 local fillPlanesRotDeg = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.fillPlanes#rotationDegrees"), false);
237 local i = 0;
238 while true do
239 local key = string.format("vehicle.fillPlanes.fillPlane(%d)", i);
240 if not hasXMLProperty(self.xmlFile, key) then
241 break;
242 end
243 local fillUnitIndex = getXMLInt(self.xmlFile, key.."#fillUnitIndex");
244 if self.fillUnits[fillUnitIndex] == nil then
245 print("Warning: fillUnitIndex '"..tostring(fillUnitIndex).."' in fillPlane("..i..") does not point to a valid fillUnit!");
246 end
247 if self.fillUnits[fillUnitIndex].fillPlanes == nil then
248 self.fillUnits[fillUnitIndex].fillPlanes = {};
249 end
250 local fillPlane = {};
251 fillPlane.nodes = {};
252 local fillTypeName = getXMLString(self.xmlFile, key.."#fillType")
253 local fillType = Utils.getNoNil(FillUtil.fillTypeNameToInt[fillTypeName], FillUtil.FILLTYPE_UNKNOWN);
254
255 if fillType ~= nil then
256 local nodeI = 0;
257 while true do
258 local nodeKey = key..string.format(".node(%d)", nodeI);
259 if not hasXMLProperty(self.xmlFile, nodeKey) then
260 break;
261 end
262 local node = Utils.indexToObject(self.components, getXMLString(self.xmlFile, nodeKey.."#index"));
263 if node ~= nil then
264 local defaultX, defaultY, defaultZ = getTranslation(node);
265 local defaultRX, defaultRY, defaultRZ = getRotation(node);
266
267 local animCurve = AnimCurve:new(linearInterpolatorTransRotScale);
268 local keyI = 0;
269 while true do
270 local animKey = nodeKey..string.format(".key(%d)", keyI);
271 local keyTime = getXMLFloat(self.xmlFile, animKey.."#time");
272 local x,y,z = Utils.getVectorFromString(getXMLString(self.xmlFile, animKey.."#translation"));
273 if y == nil then
274 y = getXMLFloat(self.xmlFile, animKey.."#y");
275 end
276 local rx,ry,rz = Utils.getVectorFromString(getXMLString(self.xmlFile, animKey.."#rotation"));
277 local sx,sy,sz = Utils.getVectorFromString(getXMLString(self.xmlFile, animKey.."#scale"));
278 if keyTime == nil then
279 break;
280 end
281 local x = Utils.getNoNil(x, defaultX);
282 local y = Utils.getNoNil(y, defaultY);
283 local z = Utils.getNoNil(z, defaultZ);
284 if fillPlanesRotDeg then
285 rx = Utils.getNoNilRad(rx, defaultRX);
286 ry = Utils.getNoNilRad(ry, defaultRY);
287 rz = Utils.getNoNilRad(rz, defaultRZ);
288 else
289 rx = Utils.getNoNil(rx, defaultRX);
290 ry = Utils.getNoNil(ry, defaultRY);
291 rz = Utils.getNoNil(rz, defaultRZ);
292 end
293 local sx = Utils.getNoNil(sx, 1);
294 local sy = Utils.getNoNil(sy, 1);
295 local sz = Utils.getNoNil(sz, 1);
296 animCurve:addKeyframe({x=x, y=y, z=z, rx=rx, ry=ry, rz=rz, sx=sx, sy=sy, sz=sz, time = keyTime});
297 keyI = keyI +1;
298 end
299 if keyI == 0 then
300 local minY, maxY = Utils.getVectorFromString(getXMLString(self.xmlFile, nodeKey.."#minMaxY"));
301 local minY = Utils.getNoNil(minY, defaultY);
302 local maxY = Utils.getNoNil(maxY, defaultY);
303 animCurve:addKeyframe({x=defaultX, y=minY, z=defaultZ, rx=defaultRX, ry=defaultRY, rz=defaultRZ, sx=1, sy=1, sz=1, time = 0});
304 animCurve:addKeyframe({x=defaultX, y=maxY, z=defaultZ, rx=defaultRX, ry=defaultRY, rz=defaultRZ, sx=1, sy=1, sz=1, time = 1});
305 end
306 local alwaysVisible = Utils.getNoNil(getXMLBool(self.xmlFile, nodeKey.."#alwaysVisible"), false);
307 setVisibility(node, alwaysVisible);
308 table.insert(fillPlane.nodes, {node=node, animCurve = animCurve, alwaysVisible=alwaysVisible});
309 end
310 nodeI = nodeI +1;
311 end
312 if table.getn(fillPlane.nodes) > 0 then
313 if self.fillUnits[fillUnitIndex].defaultFillPlane == nil then
314 self.fillUnits[fillUnitIndex].defaultFillPlane = fillPlane;
315 end
316 self.fillUnits[fillUnitIndex].fillPlanes[fillType] = fillPlane;
317 end
318 end
319 i = i +1;
320 end
321
322 self.measurementNodes = {};
323 local i=0;
324 while true do
325 local key = string.format("vehicle.measurementNodes.measurementNode(%d)", i);
326 if not hasXMLProperty(self.xmlFile, key) then
327 break;
328 end
329 local node = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key .. "#index"));
330 local fillUnitIndex = getXMLInt(self.xmlFile, key.."#fillUnitIndex");
331 if self.fillUnits[fillUnitIndex] == nil then
332 print("Warning: fillUnitIndex '"..tostring(fillUnitIndex).."' in measurementNode("..i..") does not point to a valid fillUnit!");
333 break;
334 end
335 if self.fillUnits[fillUnitIndex].measurementNodes == nil then
336 self.fillUnits[fillUnitIndex].measurementNodes = {};
337 end
338 table.insert(self.fillUnits[fillUnitIndex].measurementNodes, node);
339 i=i+1;
340 end
341 self.measurementTime = 0;
342 end
343
344 self:setFillLevel(0, FillUtil.FILLTYPE_UNKNOWN);
345
346 self.fillableDirtyFlag = self:getNextDirtyFlag();
347 self.lastFillLevelChangeTime = 0;
348end

postLoad

Description
Called after loading
Definition
postLoad(table savegame)
Arguments
tablesavegamesavegame
Code
353function Fillable:postLoad(savegame)
354 local startFillLevel = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.startFillLevel"), 0);
355 if startFillLevel > 0 then
356 local firstFillType = self:getFirstEnabledFillType();
357
358 if firstFillType ~= FillUtil.FILLTYPE_UNKNOWN then
359 self:setFillLevel(startFillLevel, firstFillType, true);
360 end
361 end
362
363 if savegame ~= nil and not savegame.resetVehicles and self.synchronizeFillLevels then
364 if hasXMLProperty(savegame.xmlFile, savegame.key.."#fillLevels") and hasXMLProperty(savegame.xmlFile, savegame.key.."#fillTypes") then
365 local fillLevels = { Utils.getVectorFromString(Utils.getNoNil(getXMLString(savegame.xmlFile, savegame.key.."#fillLevels"), "")) };
366 local fillTypes = Utils.splitString(" ", Utils.getNoNil(getXMLString(savegame.xmlFile, savegame.key.."#fillTypes"), ""));
367
368 for i,fillType in pairs(fillTypes) do
369 if fillLevels[i] ~= nil then
370 local fillTypeInt = FillUtil.fillTypeNameToInt[fillType];
371 self:setUnitFillLevel(i, fillLevels[i], fillTypeInt, false);
372 end
373 end
374 end
375 end
376end

delete

Description
Called on deleting
Definition
delete()
Code
380function Fillable:delete()
381 if self.unloadTrigger ~= nil then
382 self.unloadTrigger:delete();
383 self.unloadTrigger = nil;
384 end
385
386 if self.fillActivatable ~= nil then
387 g_currentMission:removeActivatableObject(self.fillActivatable);
388 end
389end

getSaveAttributesAndNodes

Description
Returns attributes and nodes to save
Definition
getSaveAttributesAndNodes(table nodeIdent)
Arguments
tablenodeIdentnode ident
Return Values
stringattributesattributes
stringnodesnodes
Code
396function Fillable:getSaveAttributesAndNodes(nodeIdent)
397 if self.synchronizeFillLevels then
398 local fillTypes = 'fillTypes="';
399 local fillLevels = 'fillLevels="';
400 local numFillUnits = table.getn(self.fillUnits);
401 for i,fillUnit in pairs(self.fillUnits) do
402 local fillTypeName = FillUtil.fillTypeIntToName[fillUnit.currentFillType];
403 if fillTypeName == nil then
404 fillTypeName = "unknown";
405 end
406 fillTypes = fillTypes .. fillTypeName;
407 fillLevels = fillLevels .. fillUnit.fillLevel;
408 if numFillUnits > 1 and i ~= numFillUnits then
409 fillTypes = fillTypes .. ' ';
410 fillLevels = fillLevels .. ' ';
411 end
412 end
413 fillTypes = fillTypes .. '"';
414 fillLevels = fillLevels .. '"';
415 return fillTypes .. " " .. fillLevels, nil;
416 end
417 return nil;
418end

getXMLStatsAttributes

Description
Returns string with fillLevels and fillTypes for game stats xml
Definition
getXMLStatsAttributes()
Return Values
stringstatesAttributesstates attributes
Code
423function Fillable:getXMLStatsAttributes()
424 local fillTypes = 'fillTypes="';
425 local fillLevels = 'fillLevels="';
426 local numFillUnits = table.getn(self.fillUnits);
427 for i,fillUnit in pairs(self.fillUnits) do
428 local fillTypeName = FillUtil.fillTypeIntToName[fillUnit.currentFillType];
429 if fillTypeName == nil then
430 fillTypeName = "unknown";
431 end
432 fillTypes = fillTypes .. Utils.encodeToHTML(tostring(fillTypeName));
433 fillLevels = fillLevels .. string.format("%.3f", fillUnit.fillLevel);
434 if numFillUnits > 1 and i ~= numFillUnits then
435 fillTypes = fillTypes .. ' ';
436 fillLevels = fillLevels .. ' ';
437 end
438 end
439 return fillLevels .. '" '.. fillTypes..'"';
440end

addNodeVehicleMapping

Description
Add fillRootNode and exactFillRootNode to 'nodeToVehicle' mapping
Definition
addNodeVehicleMapping(table list)
Arguments
tablelistlist
Code
445function Fillable:addNodeVehicleMapping(list)
446 list[self.fillRootNode] = self;
447 list[self.exactFillRootNode] = self;
448end

removeNodeVehicleMapping

Description
Remove fillRootNode and exactFillRootNode from 'nodeToVehicle' mapping
Definition
removeNodeVehicleMapping(table list)
Arguments
tablelistlist
Code
453function Fillable:removeNodeVehicleMapping(list)
454 list[self.fillRootNode] = nil;
455 list[self.exactFillRootNode] = nil;
456end

readStream

Description
Called on client side on join
Definition
readStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
468function Fillable:readStream(streamId, connection)
469 if connection:getIsServer() then
470 if self.synchronizeFillLevels then
471 for i=1,table.getn(self.fillUnits) do
472 local fillLevel = streamReadFloat32(streamId);
473 local fillType = streamReadUIntN(streamId, FillUtil.sendNumBits);
474 self:setUnitFillLevel(i, fillLevel, fillType);
475
476 local lastValidFillType = streamReadUIntN(streamId, FillUtil.sendNumBits);
477 self:setUnitLastValidFillType(i, lastValidFillType, true);
478 end
479 end
480 end
481 if self.supportsFillTriggers then
482 local isFilling = streamReadBool(streamId);
483 self:setIsFilling(isFilling, true);
484 end
485end

writeStream

Description
Called on server side on join
Definition
writeStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
491function Fillable:writeStream(streamId, connection)
492 if not connection:getIsServer() then
493 if self.synchronizeFillLevels then
494 for i=1,table.getn(self.fillUnits) do
495 local fillUnit = self.fillUnits[i];
496 streamWriteFloat32(streamId, fillUnit.fillLevel);
497 streamWriteUIntN(streamId, fillUnit.currentFillType, FillUtil.sendNumBits);
498 streamWriteUIntN(streamId, fillUnit.lastValidFillType, FillUtil.sendNumBits);
499 end
500 end
501 end
502 if self.supportsFillTriggers then
503 streamWriteBool(streamId, self.isFilling);
504 end
505end

readUpdateStream

Description
Called on on update
Definition
readUpdateStream(integer streamId, integer timestamp, table connection)
Arguments
integerstreamIdstream ID
integertimestamptimestamp
tableconnectionconnection
Code
512function Fillable:readUpdateStream(streamId, timestamp, connection)
513 if connection:getIsServer() then
514 if self.synchronizeFillLevels then
515 if streamReadBool(streamId) then
516 for i=1,table.getn(self.fillUnits) do
517 local fillUnit = self.fillUnits[i];
518 local fillLevel;
519 if self.synchronizeFullFillLevel then
520 fillLevel = streamReadFloat32(streamId);
521 else
522 fillLevel = streamReadUInt16(streamId)/65535*fillUnit.capacity
523 end
524 local fillType = streamReadUIntN(streamId, FillUtil.sendNumBits);
525
526 self:setUnitFillLevel(i, fillLevel, fillType, true);
527
528 local lastValidFillType = streamReadUIntN(streamId, FillUtil.sendNumBits);
529 self:setUnitLastValidFillType(i, lastValidFillType, lastValidFillType ~= fillUnit.lastValidFillType)
530 end
531 end
532 end
533 end
534end

writeUpdateStream

Description
Called on on update
Definition
writeUpdateStream(integer streamId, table connection, integer dirtyMask)
Arguments
integerstreamIdstream ID
tableconnectionconnection
integerdirtyMaskdirty mask
Code
541function Fillable:writeUpdateStream(streamId, connection, dirtyMask)
542 if not connection:getIsServer() then
543 if self.synchronizeFillLevels then
544 if streamWriteBool(streamId, bitAND(dirtyMask, self.fillableDirtyFlag) ~= 0) then
545 for i=1,table.getn(self.fillUnits) do
546 local fillUnit = self.fillUnits[i];
547 if self.synchronizeFullFillLevel then
548 streamWriteFloat32(streamId, fillUnit.fillLevel);
549 else
550 local percent = 0;
551 if fillUnit.capacity > 0 then
552 percent = Utils.clamp(fillUnit.fillLevel / fillUnit.capacity, 0, 1);
553 end
554 streamWriteUInt16(streamId, math.floor(percent*65535));
555 end
556 streamWriteUIntN(streamId, fillUnit.currentFillType, FillUtil.sendNumBits);
557 streamWriteUIntN(streamId, fillUnit.lastValidFillType, FillUtil.sendNumBits);
558 end
559 end
560 end
561 end
562end

update

Description
Called on update
Definition
update(float dt)
Arguments
floatdttime since last call in ms
Code
567function Fillable:update(dt)
568 if self.firstTimeRun then
569 if self.isServer then
570 if self.fillMassNode ~= nil then
571 if self.emptyMass == nil then
572 self.emptyMass = getMass(self.fillMassNode);
573 self.currentMass = self.emptyMass;
574 end
575 local newMass = 0;
576 for i,fillUnit in pairs(self.fillUnits) do
577 if fillUnit.currentFillType ~= nil and fillUnit.currentFillType ~= FillUtil.FILLTYPE_UNKNOWN then
578 local desc = FillUtil.fillTypeIndexToDesc[fillUnit.currentFillType];
579 newMass = newMass + (fillUnit.fillLevel * desc.massPerLiter);
580 end
581 end
582 newMass = newMass + self.emptyMass;
583 if newMass ~= self.currentMass then
584 setMass(self.fillMassNode, newMass);
585 self.currentMass = newMass;
586 end
587 end;
588 end
589 end
590end

updateTick

Description
Called on update tick
Definition
updateTick(float dt)
Arguments
floatdttime since last call in ms
Code
595function Fillable:updateTick(dt)
596 if self.isServer then
597 if self.synchronizeFillLevels then
598 local hasChanged = false;
599 for i,fillUnit in pairs(self.fillUnits) do
600 if fillUnit.sentLastValidFillType ~= fillUnit.lastValidFillType or fillUnit.sentFillLevel ~= fillUnit.fillLevel or fillUnit.sentFillType ~= fillUnit.currentFillType then
601 hasChanged = true;
602 fillUnit.sentLastValidFillType = fillUnit.lastValidFillType;
603 fillUnit.sentFillLevel = fillUnit.fillLevel
604 fillUnit.sentFillType = fillUnit.currentFillType;
605 end
606 end
607 if hasChanged then
608 self:raiseDirtyFlags(self.fillableDirtyFlag);
609 end
610 end
611
612 if self.isFilling then
613 local delta = 0;
614 local doFill = false;
615 if self.fillTrigger ~= nil then
616 if self.unitFillTime ~= nil then
617 self.currentFillTime = self.currentFillTime - dt;
618 if self.currentFillTime <= 0 then
619 doFill = true;
620 delta = self.fillTrigger:fill(self, 1);
621 self.currentFillTime = self.unitFillTime;
622 end
623 else
624 delta = self.fillLitersPerSecond*dt*0.001;
625 delta = self.fillTrigger:fill(self, delta);
626 doFill = true;
627 end
628 end
629
630 if delta <= 0 and doFill then
631 self:setIsFilling(false);
632 end
633 end
634 end
635
636 if self.isClient then
637 if self.measurementTime > 0 then
638 self.measurementTime = self.measurementTime - dt
639
640 for _, fillUnit in pairs(self.fillUnits) do
641 if fillUnit.measurementNodes ~= nil then
642 for _, measurementNode in pairs(fillUnit.measurementNodes) do
643 local isWorking = 1;
644 if self.measurementTime <= 0 or fillUnit.fillLevel <= 0 then
645 isWorking = 0;
646 end;
647
648 setShaderParameter(measurementNode, "fillLevel", fillUnit.fillLevel / fillUnit.capacity, isWorking, 0, 0, false);
649 end
650 end
651 end
652 end
653 end
654end

draw

Description
Called on draw
Definition
draw()
Code
658function Fillable:draw()
659 if self:getDrawFirstFillText() then
660 g_currentMission:addExtraPrintText(g_i18n:getText("info_firstFillTheTool"));
661 end;
662end

getDrawFirstFillText

Description
Returns if 'first fill tool' text should be drawed
Definition
getDrawFirstFillText()
Return Values
booleandrawdraw text
Code
667function Fillable:getDrawFirstFillText(superFunc)
668 if superFunc ~= nil then
669 return superFunc(self);
670 end;
671
672 return false;
673end;

getAdditiveClientMass

Description
Returns additive mass of filled goods
Definition
getAdditiveClientMass()
Return Values
floatmassmass in t
Code
678function Fillable:getAdditiveClientMass()
679 local mass = 0;
680 if self.fillUnits ~= nil then
681 for i,fillUnit in pairs(self.fillUnits) do
682 if fillUnit.currentFillType ~= nil and fillUnit.currentFillType ~= FillUtil.FILLTYPE_UNKNOWN then
683 local desc = FillUtil.fillTypeIndexToDesc[fillUnit.currentFillType];
684 mass = mass + (fillUnit.fillLevel * desc.massPerLiter);
685 end
686 end
687 end
688 return mass;
689end

getFillUnitsWithFillType

Description
Returns a table with fill units that allow given fill type
Definition
getFillUnitsWithFillType(integer fillType)
Arguments
integerfillTypefill type
Return Values
tablefillUnitsfill units
Code
695function Fillable:getFillUnitsWithFillType(fillType)
696 local tbl = {};
697 for i,fillUnit in pairs(self.fillUnits) do
698 if fillUnit.fillTypes[fillType] then
699 table.insert(tbl, fillUnit);
700 end
701 end
702 return tbl;
703end

resetFillLevelIfNeeded

Description
Resets fill level if given fillType is different than the current fill type
Definition
resetFillLevelIfNeeded(integer fillType)
Arguments
integerfillTypefill type
Return Values
booleansuccessreturns false if reset failed
Code
709function Fillable:resetFillLevelIfNeeded(fillType)
710 if self.lastFillLevelChangeTime + 500 > g_currentMission.time then
711 return false;
712 end;
713
714 for i,fillUnit in pairs(self.fillUnits) do
715 if fillUnit.fillTypes[fillType] then
716 if fillUnit.currentFillType ~= fillType then
717 self:setUnitFillLevel(i, 0, FillUtil.FILLTYPE_UNKNOWN, true);
718 end
719 end
720 end
721end

allowFillType

Description
Returns if fill type is allowed
Definition
allowFillType(integer fillType, boolean allowEmptying)
Arguments
integerfillTypefill type
booleanallowEmptyingallow emptying
Return Values
booleanallowallow fill type
Code
728function Fillable:allowFillType(fillType, allowEmptying)
729 if fillType == FillUtil.FILLTYPE_UNKNOWN then
730 return true;
731 end
732 for i,fillUnit in pairs(self.fillUnits) do
733 if fillUnit.fillTypes[fillType] then
734 if fillUnit.currentFillType ~= FillUtil.FILLTYPE_UNKNOWN then
735 if fillUnit.fillLevel <= fillUnit.capacity*self.fillTypeChangeThreshold then
736 if allowEmptying then
737 self:setUnitFillLevel(i, 0, FillUtil.FILLTYPE_UNKNOWN, true);
738 end
739 return true;
740 else
741 if fillType == fillUnit.currentFillType then
742 return true;
743 end
744 end
745 else
746 return true;
747 end
748 end
749 end
750 return false;
751end

getCurrentFillTypes

Description
Returns table filled with current filltypes of all fill units
Definition
getCurrentFillTypes()
Return Values
tablefillTypesfill types
Code
756function Fillable:getCurrentFillTypes()
757 local tbl = {};
758 for _,fillUnit in pairs(self.fillUnits) do
759 if fillUnit.currentFillType ~= FillUtil.FILLTYPE_UNKNOWN and fillUnit.fillLevel > 0 then
760 table.insert(tbl, fillUnit.currentFillType);
761 end
762 end
763 return tbl;
764end

getFillLevel

Description
Returns fill level of given fill type on all fill units
Definition
getFillLevel(integer fillType)
Arguments
integerfillTypefill type
Return Values
floatfillLevelfill level
Code
770function Fillable:getFillLevel(fillType)
771 local fillLevel = 0;
772 for i,fillUnit in pairs(self.fillUnits) do
773 if fillType == nil or fillUnit.fillTypes[fillType] then
774 fillLevel = fillLevel + fillUnit.fillLevel;
775 end
776 end
777 return fillLevel;
778end

setFillLevel

Description
Set fill level (filling all fill units that allow given fill type)
Definition
setFillLevel(float filllevel, integer fillType, boolean force, table fillInfo)
Arguments
floatfilllevelnew fill level
integerfillTypefill type
booleanforceforce action
tablefillInfofill info for fill volume
Code
786function Fillable:setFillLevel(fillLevel, fillType, force, fillInfo)
787
788 if (force == nil or force == false) and not self:allowFillType(fillType, false) then
789 return;
790 end
791
792 local availableFillUnits = self:getFillUnitsWithFillType(fillType);
793 local delta = fillLevel - self:getFillLevel(fillType);
794
795 if availableFillUnits ~= nil then
796 for _,fillUnit in pairs(availableFillUnits) do
797 local oldFillLevel = self:getUnitFillLevel(fillUnit.fillUnitIndex);
798 self:setUnitFillLevel(fillUnit.fillUnitIndex, oldFillLevel + delta, fillType, force, fillInfo);
799 delta = delta - (self:getUnitFillLevel(fillUnit.fillUnitIndex) - oldFillLevel);
800 if math.abs(delta) < 0.0001 then
801 break;
802 end
803 end
804 end
805
806 if self.unloadTrigger ~= nil then
807 if self.fillUnits[self.unloadTriggerFillUnitIndex] ~= nil then
808 self.unloadTrigger.fillType = self.fillUnits[self.unloadTriggerFillUnitIndex].currentFillType;
809 end
810 end
811end

getCapacity

Description
Returns the capacity of all fill units that support the given fill type
Definition
getCapacity(integer fillType)
Arguments
integerfillTypefill type
Return Values
floatcapacitycapacity
Code
817function Fillable:getCapacity(fillType)
818 local capacity = 0;
819 for i,fillUnit in pairs(self.fillUnits) do
820 if fillType == nil or fillType == FillUtil.FILLTYPE_UNKNOWN or fillUnit.fillTypes[fillType] then
821 capacity = capacity + fillUnit.capacity;
822 end
823 end
824 return capacity;
825end

getFreeCapacity

Description
Returns the free capacity of all fill units that support the given fill type
Definition
getFreeCapacity(integer fillType)
Arguments
integerfillTypefill type
Return Values
floatfreeCapacityfree capacity
Code
831function Fillable:getFreeCapacity(fillType)
832 local freeCapacity = 0;
833 for i,fillUnit in pairs(self.fillUnits) do
834 if fillType == nil or fillType == FillUtil.FILLTYPE_UNKNOWN or fillUnit.fillTypes[fillType] then
835 freeCapacity = freeCapacity + (fillUnit.capacity - fillUnit.fillLevel);
836 end
837 end
838 return freeCapacity;
839end

resetUnitFillLevelIfNeeded

Description
Resets fill level of fill unit if given fillType is different than the current fill type
Definition
resetUnitFillLevelIfNeeded(integer fillUnitIndex, integer fillType)
Arguments
integerfillUnitIndexindex of fill unit
integerfillTypefill type
Return Values
booleansuccessreturns false if reset failed
Code
846function Fillable:resetUnitFillLevelIfNeeded(fillUnitIndex, fillType)
847 if self.fillUnits == nil or self.fillUnits[fillUnitIndex] == nil or self.lastFillLevelChangeTime + 500 > g_currentMission.time then
848 return;
849 end
850 local fillUnit = self.fillUnits[fillUnitIndex];
851 if fillUnit.fillTypes[fillType] then
852 if fillUnit.currentFillType ~= fillType then
853 self:setUnitFillLevel(fillUnitIndex, 0, FillUtil.FILLTYPE_UNKNOWN, true);
854 end
855 end
856end

allowUnitFillType

Description
Returns if fill type is allowed by fill unit
Definition
allowUnitFillType(integer fillUnitIndex, integer fillType, boolean allowEmptying)
Arguments
integerfillUnitIndexindex of fill unit
integerfillTypefill type
booleanallowEmptyingallow emptying
Return Values
booleanallowallow fill type
Code
864function Fillable:allowUnitFillType(fillUnitIndex, fillType, allowEmptying)
865 if self.fillUnits == nil or self.fillUnits[fillUnitIndex] == nil then
866 return false;
867 end
868 local fillUnit = self.fillUnits[fillUnitIndex];
869 if fillUnit.fillTypes[fillType] then
870 if fillUnit.currentFillType ~= FillUtil.FILLTYPE_UNKNOWN then
871 if fillUnit.fillLevel <= fillUnit.capacity*self.fillTypeChangeThreshold then
872 if allowEmptying then
873 self:setUnitFillLevel(fillUnitIndex, 0, FillUtil.FILLTYPE_UNKNOWN, true);
874 end
875 return true;
876 else
877 if fillType == fillUnit.currentFillType then
878 return true;
879 end
880 end
881 else
882 return true;
883 end
884 end
885 return false;
886end

getUnitFillTypes

Description
Returns a table with supported fill types of the given fill unit
Definition
getUnitFillTypes(integer fillUnitIndex)
Arguments
integerfillUnitIndexindex of fill unit
Return Values
tablefillTypesfill types
Code
892function Fillable:getUnitFillTypes(fillUnitIndex)
893 if self.fillUnits == nil or self.fillUnits[fillUnitIndex] == nil then
894 return {FillUtil.FILLTYPE_UNKNOWN};
895 else
896 return self.fillUnits[fillUnitIndex].fillTypes;
897 end
898end

getUnitFillType

Description
Returns current fill type of fill unit
Definition
getUnitFillType(integer fillUnitIndex)
Arguments
integerfillUnitIndexindex of fill unit
Return Values
integerfillTypefill type
Code
904function Fillable:getUnitFillType(fillUnitIndex)
905 if self.fillUnits == nil or self.fillUnits[fillUnitIndex] == nil then
906 return FillUtil.FILLTYPE_UNKNOWN;
907 else
908 local fillUnit = self.fillUnits[fillUnitIndex];
909 if fillUnit.fillLevel > 0 then
910 return fillUnit.currentFillType;
911 else
912 return FillUtil.FILLTYPE_UNKNOWN;
913 end
914 end
915end

getUnitLastValidFillType

Description
Returns last valid fill type of fill unit
Definition
getUnitLastValidFillType(integer fillUnitIndex)
Arguments
integerfillUnitIndexindex of fill unit
Return Values
integerlastValidFillTypelast valid fill type
Code
921function Fillable:getUnitLastValidFillType(fillUnitIndex)
922 if self.fillUnits == nil or self.fillUnits[fillUnitIndex] == nil then
923 return FillUtil.FILLTYPE_UNKNOWN;
924 else
925 return self.fillUnits[fillUnitIndex].lastValidFillType;
926 end
927end

setUnitLastValidFillType

Description
Set unit last valid fill type
Definition
setUnitLastValidFillType(integer fillUnitIndex, integer lastValidFillType, boolean hasChanged)
Arguments
integerfillUnitIndexindex of fill unit
integerlastValidFillTypeindex new last valid fill type
booleanhasChangedfill type has changed
Code
934function Fillable:setUnitLastValidFillType(fillUnitIndex, lastValidFillType, hasChanged)
935 if self.fillUnits == nil or self.fillUnits[fillUnitIndex] == nil then
936 return;
937 else
938 if self.fillUnits[fillUnitIndex].lastValidFillType ~= lastValidFillType then
939 self.fillUnits[fillUnitIndex].lastValidFillType = lastValidFillType;
940 end
941 end
942end

getUnitFillLevel

Description
Returns fill level of fill unit
Definition
getUnitFillLevel(integer fillUnitIndex)
Arguments
integerfillUnitIndexfill unit index
Return Values
floatfillLevelfill level of fill unit
Code
948function Fillable:getUnitFillLevel(fillUnitIndex)
949 if self.fillUnits == nil or self.fillUnits[fillUnitIndex] == nil then
950 return 0;
951 end
952 return self.fillUnits[fillUnitIndex].fillLevel;
953end

setUnitFillLevel

Description
Set unit fill level
Definition
setUnitFillLevel(integer fillUnitIndex, float fillLevel, integer fillType, boolean force, table fillInfo)
Arguments
integerfillUnitIndexindex of fill unit
floatfillLevelnew fill level
integerfillTypefill type
booleanforceforce action
tablefillInfofill info for fill volume
Code
962function Fillable:setUnitFillLevel(fillUnitIndex, fillLevel, fillType, force, fillInfo)
963 if self.fillUnits == nil or self.fillUnits[fillUnitIndex] == nil then
964 return false;
965 end
966
967 if (force == nil or force == false) and not self:allowUnitFillType(fillUnitIndex, fillType, false) then
968 return false;
969 end
970
971 local fillUnit = self.fillUnits[fillUnitIndex];
972
973 if fillLevel < fillUnit.fillLevel and fillLevel < 0.0000001 then
974 fillLevel = 0;
975 end
976
977 fillUnit.currentFillType = fillType;
978 fillUnit.fillLevel = fillLevel;
979
980 if fillUnit.capacity == 0 then
981 fillUnit.fillLevel = math.max(fillLevel, 0);
982 else
983 fillUnit.fillLevel = Utils.clamp(fillLevel, 0, fillUnit.capacity);
984 end
985
986 if fillUnit.fillLevel <= 0 then
987 fillUnit.fillLevel = 0;
988 fillUnit.currentFillType = FillUtil.FILLTYPE_UNKNOWN;
989 end
990
991 if fillUnit.currentFillType ~= FillUtil.FILLTYPE_UNKNOWN and fillUnit.fillLevel > 0 then
992 self:setUnitLastValidFillType(fillUnitIndex, fillUnit.currentFillType);
993 end
994
995 if fillUnit.fillLevelHud ~= nil and math.abs(fillUnit.lastFillLevel-fillUnit.fillLevel) > 1 then
996 fillUnit.lastFillLevel = fillUnit.fillLevel;
997 VehicleHudUtils.setHudValue(self, fillUnit.fillLevelHud, fillUnit.fillLevel, fillUnit.capacity);
998 end
999
1000 if fillUnit.currentFillPlane ~= nil then
1001 for _, node in ipairs(fillUnit.currentFillPlane.nodes) do
1002 setVisibility(node.node, false);
1003 end
1004 fillUnit.currentFillPlane = nil;
1005 end
1006 if fillUnit.fillPlanes ~= nil and fillUnit.defaultFillPlane ~= nil then
1007 local fillPlane;
1008 local t = 0;
1009 if fillType ~= FillUtil.FILLTYPE_UNKNOWN then
1010 fillPlane = fillUnit.fillPlanes[fillType];
1011 t = fillUnit.fillLevel/fillUnit.capacity;
1012 end
1013 if fillPlane == nil then
1014 fillPlane = fillUnit.defaultFillPlane
1015 end
1016 for _, node in ipairs(fillPlane.nodes) do
1017 local x,y,z, rx,ry,rz, sx,sy,sz = node.animCurve:get(t);
1018
1019 setTranslation(node.node, x, y, z);
1020 setRotation(node.node, rx, ry, rz);
1021 setScale(node.node, sx, sy, sz);
1022 setVisibility(node.node, fillUnit.fillLevel > 0 or node.alwaysVisible);
1023 end
1024 fillUnit.currentFillPlane = fillPlane;
1025 end
1026
1027 if fillUnit.measurementNodes ~= nil then
1028 if fillUnit.fillLevel > 0 then
1029 self.measurementTime = math.min(self.measurementTime+5000, 5000)
1030 end
1031 end
1032
1033 if self.fillAutoAimTarget.fillUnitIndex == fillUnitIndex then
1034 if self.fillAutoAimTarget.startZ ~= nil and self.fillAutoAimTarget.endZ ~= nil then
1035 local startFillLevel = fillUnit.capacity * self.fillAutoAimTarget.startPercentage;
1036 local percent = Utils.clamp((fillUnit.fillLevel-startFillLevel) / (fillUnit.capacity-startFillLevel), 0, 1);
1037 if self.fillAutoAimTarget.invert then
1038 percent = 1 - percent;
1039 end;
1040 local newZ = (self.fillAutoAimTarget.endZ-self.fillAutoAimTarget.startZ) * percent + self.fillAutoAimTarget.startZ;
1041 setTranslation(self.fillAutoAimTarget.node, self.fillAutoAimTarget.baseTrans[1], self.fillAutoAimTarget.baseTrans[2], newZ);
1042 end;
1043 end;
1044
1045 self.lastFillLevelChangeTime = g_currentMission.time;
1046end

getUnitCapacity

Description
Returns capacity of fill unit
Definition
getUnitCapacity(integer fillUnitIndex)
Arguments
integerfillUnitIndexindex of fill volume
Return Values
floatcapacitycapacity of fill unit
Code
1052function Fillable:getUnitCapacity(fillUnitIndex)
1053 if self.fillUnits == nil or self.fillUnits[fillUnitIndex] == nil then
1054 return 0;
1055 end
1056 return self.fillUnits[fillUnitIndex].capacity;
1057end

setUnitCapacity

Description
Sets unit capacity
Definition
setUnitCapacity(integer fillUnitIndex, float capacity)
Arguments
integerfillUnitIndexfill unit index
floatcapacitynew capacity
Code
1063function Fillable:setUnitCapacity(fillUnitIndex, capacity)
1064 if self.fillUnits == nil or self.fillUnits[fillUnitIndex] == nil then
1065 return;
1066 end
1067 self.fillUnits[fillUnitIndex].capacity = capacity;
1068end

getAllowFillFromAir

Description
Returns if fill from air is allowed
Definition
getAllowFillFromAir()
Return Values
booleanisAllowedfill from air is allowed
Code
1073function Fillable:getAllowFillFromAir()
1074 return self.allowFillFromAir;
1075end

getFirstEnabledFillType

Description
Returns first enabled fill type
Definition
getFirstEnabledFillType()
Return Values
integerfilltypefirst enabled fill type
Code
1080function Fillable:getFirstEnabledFillType()
1081 for _,fillUnit in pairs(self.fillUnits) do
1082 for fillType, enabled in pairs(fillUnit.fillTypes) do
1083 if fillType ~= FillUtil.FILLTYPE_UNKNOWN and enabled then
1084 return fillType;
1085 end
1086 end
1087 end
1088 return FillUtil.FILLTYPE_UNKNOWN;
1089end

setIsFilling

Description
Set is filling
Definition
setIsFilling(boolean isFilling, boolean noEventSend)
Arguments
booleanisFillingis filling
booleannoEventSendno event send
Code
1095function Fillable:setIsFilling(isFilling, noEventSend)
1096 SetIsFillingEvent.sendEvent(self, isFilling, noEventSend)
1097 if self.isFilling ~= isFilling then
1098 self.isFilling = isFilling;
1099
1100 self.fillTrigger = nil;
1101 if isFilling then
1102 -- find the first trigger which is activable
1103 for _, trigger in ipairs(self.fillTriggers) do
1104 if trigger:getIsActivatable(self) then
1105 self.fillTrigger = trigger;
1106 break;
1107 end
1108 end
1109 end
1110 end
1111end

addFillTrigger

Description
Called if vehicle is in fill trigger
Definition
addFillTrigger(table trigger)
Arguments
tabletriggertrigger
Code
1116function Fillable:addFillTrigger(trigger)
1117 if table.getn(self.fillTriggers) == 0 then
1118 g_currentMission:addActivatableObject(self.fillActivatable);
1119 end
1120 table.insert(self.fillTriggers, trigger);
1121end

removeFillTrigger

Description
Called if vehicle leaves fill trigger
Definition
removeFillTrigger(table trigger)
Arguments
tabletriggertrigger
Code
1126function Fillable:removeFillTrigger(trigger)
1127 for i=1, table.getn(self.fillTriggers) do
1128 if self.fillTriggers[i] == trigger then
1129 table.remove(self.fillTriggers, i);
1130 break;
1131 end
1132 end
1133 if self.fillTrigger == trigger then
1134 if self.isServer then
1135 self:setIsFilling(false);
1136 end
1137 end
1138 if table.getn(self.fillTriggers) == 0 then
1139 self:setIsFilling(false);
1140 g_currentMission:removeActivatableObject(self.fillActivatable);
1141 end
1142end

onAttach

Description
Called if vehicle gets attached
Definition
onAttach(table attacherVehicle)
Arguments
tableattacherVehicleattacher vehicle
Code
1147function Fillable:onAttach(attacherVehicle)
1148 if self.attacherPipe ~= nil then
1149 local vehicle = Fillable.findAttacherPipeVehicle(attacherVehicle, self, true, nil);
1150 if vehicle ~= nil then
1151 self:attachPipe(self, vehicle);
1152 end
1153 elseif self.attacherPipeRef ~= nil then
1154 local vehicle = Fillable.findAttacherPipeVehicle(attacherVehicle, self, false, nil);
1155 if vehicle ~= nil then
1156 self:attachPipe(vehicle, self);
1157 end
1158 end
1159end

onDetach

Description
Called if vehicle gets detached
Definition
onDetach()
Code
1163function Fillable:onDetach()
1164 if self.attacherPipe ~= nil then
1165 if self.attacherPipeRefVehicle ~= nil then
1166 self:detachPipe();
1167 end;
1168 elseif self.attacherPipeRef ~= nil then
1169 if self.attacherPipeVehicle ~= nil then
1170 self:detachPipe();
1171 end;
1172 end
1173end

attachPipe

Description
Attach connection pipe between 2 fillables
Definition
attachPipe(table pipeVehicle, table refVehicle)
Arguments
tablepipeVehiclevehicle with pipe
tablerefVehiclevehicle to attach the pipe
Code
1179function Fillable:attachPipe(pipeVehicle, refVehicle)
1180 pipeVehicle.attacherPipeRefVehicle = refVehicle;
1181 refVehicle.attacherPipeVehicle = pipeVehicle;
1182
1183 for _, movingPart in pairs(pipeVehicle.activeDirtyMovingParts) do
1184 if movingPart.node == pipeVehicle.attacherPipe then
1185 movingPart.referenceFrameBackUp = movingPart.referenceFrame;
1186 movingPart.referenceFrame = refVehicle.attacherPipeRef;
1187 movingPart.referenceFrameOffset = {0,0,0};
1188 Cylindered.updateMovingPart(self, movingPart, false);
1189 break;
1190 end
1191 end
1192
1193 if pipeVehicle.attacherPipeAnimation ~= nil and pipeVehicle.attacherPipeAnimation ~= "" then
1194 self:playAnimation(pipeVehicle.attacherPipeAnimation, 1, nil, true);
1195 end
1196end

detachPipe

Description
Detach pipe
Definition
detachPipe()
Code
1200function Fillable:detachPipe()
1201 if self.attacherPipeRefVehicle ~= nil then
1202 for _, movingPart in pairs(self.activeDirtyMovingParts) do
1203 if movingPart.node == self.attacherPipe then
1204 movingPart.referenceFrame = movingPart.referenceFrameBackUp;
1205 break;
1206 end
1207 end
1208 self.attacherPipeRefVehicle.attacherPipeVehicle = nil;
1209 self.attacherPipeRefVehicle = nil;
1210 end
1211
1212 if self.attacherPipeAnimation ~= nil and self.attacherPipeAnimation ~= "" then
1213 self:playAnimation(self.attacherPipeAnimation, -1, nil, true);
1214 end
1215
1216 if self.attacherPipeVehicle ~= nil then
1217
1218 for _, movingPart in pairs(self.attacherPipeVehicle.activeDirtyMovingParts) do
1219 if movingPart.node == self.attacherPipeVehicle.attacherPipe then
1220 movingPart.referenceFrame = self.attacherPipeVehicle.rootNode;
1221 break;
1222 end
1223 end
1224 self.attacherPipeVehicle.attacherPipeRefVehicle = nil;
1225 local attacherPipeVehicle = self.attacherPipeVehicle;
1226 self.attacherPipeVehicle = nil;
1227 -- try to reattach
1228 if attacherPipeVehicle.attacherVehicle ~= nil then
1229 local vehicle = Fillable.findAttacherPipeVehicle(attacherPipeVehicle.attacherVehicle, attacherPipeVehicle, true, self);
1230 if vehicle ~= nil then
1231 attacherPipeVehicle:attachPipe(attacherPipeVehicle, vehicle);
1232 end
1233 end
1234 end
1235end

findAttacherPipeVehicle

Description
Returns pipe vehicle if exists
Definition
findAttacherPipeVehicle(table currentVehicle, table lastVehicle, boolean lookForPipeRef, table ignoreVehicle)
Arguments
tablecurrentVehiclecurrent vehicle to check
tablelastVehiclelast vehicle checked
booleanlookForPipeRefonly search pipe ref vehicles
tableignoreVehicleignore that vehicle on search
Return Values
tablepipeVehiclepipe vehicle
Code
1244function Fillable.findAttacherPipeVehicle(currentVehicle, lastVehicle, lookForPipeRef, ignoreVehicle)
1245 if lookForPipeRef then
1246 if currentVehicle.attacherPipeRef ~= nil and currentVehicle.attacherPipeRefVehicle == nil then
1247 return currentVehicle;
1248 end
1249 else
1250 if currentVehicle.attacherPipe ~= nil and currentVehicle.attacherPipeVehicle == nil then
1251 return currentVehicle;
1252 end
1253 end
1254
1255 for _,implement in pairs(currentVehicle.attachedImplements) do
1256 if implement.object ~= nil and implement.object ~= lastVehicle and (ignoreVehicle == nil or ignoreVehicle ~= implement.object) then
1257 local ret = Fillable.findAttacherPipeVehicle(implement.object, currentVehicle, lookForPipeRef, nil);
1258 if ret ~= nil then
1259 return ret;
1260 end
1261 end
1262 end
1263
1264 if currentVehicle.attacherVehicle ~= nil and currentVehicle.attacherVehicle ~= lastVehicle then
1265 return Fillable.findAttacherPipeVehicle(currentVehicle.attacherVehicle, currentVehicle, lookForPipeRef, nil);
1266 end
1267
1268end

loadSpecValueCapacity

Description
Loads capacity spec value
Definition
loadSpecValueCapacity(integer xmlFile, string customEnvironment)
Arguments
integerxmlFileid of xml object
stringcustomEnvironmentcustom environment
Return Values
tablecapacityAndUnitcapacity and unit
Code
1275function Fillable.loadSpecValueCapacity(xmlFile, customEnvironment)
1276 local capacity = 0
1277 local capacityUnit = nil
1278
1279 local rootName = getXMLRootName(xmlFile)
1280
1281 local i=0;
1282 while true do
1283 local key = string.format(rootName..".fillUnits.fillUnit(%d)", i);
1284 if not hasXMLProperty(xmlFile, key) then
1285 break;
1286 end
1287
1288 local showInShop = getXMLBool(xmlFile, key.."#showInShop")
1289 if showInShop == nil or showInShop then
1290 capacity = capacity + getXMLFloat(xmlFile, key .. "#capacity")
1291 if capacityUnit == nil then
1292 capacityUnit = getXMLString(xmlFile, key .. "#unit")
1293 end
1294 end
1295
1296 i = i + 1
1297 end
1298
1299 -- fallback
1300 capacity = capacity + Utils.getNoNil(getXMLFloat(xmlFile, rootName..".capacity"), 0)
1301 if capacityUnit == nil then
1302 capacityUnit = getXMLString(xmlFile, rootName..".capacity#unit")
1303 end
1304
1305 local storeDataCapacity = getXMLString(xmlFile, rootName..".storeData.specs.capacity")
1306 local storeDataCapacityUnit = getXMLString(xmlFile, rootName..".storeData.specs.capacity#unit")
1307
1308 if storeDataCapacity ~= nil then
1309 capacity = storeDataCapacity
1310 end
1311 if storeDataCapacityUnit ~= nil then
1312 capacityUnit = storeDataCapacityUnit
1313 end
1314
1315 return {value=capacity, unit=capacityUnit}
1316end

getSpecValueCapacity

Description
Returns capacity spec value
Definition
getSpecValueCapacity(table storeItem, table realItem)
Arguments
tablestoreItemstore item
tablerealItemreal item
Return Values
stringl10nl10n text
floatcapacitycapacity
stringunitunit
Code
1325function Fillable.getSpecValueCapacity(storeItem, realItem)
1326 if storeItem.specs.capacity ~= nil then
1327 if storeItem.specs.capacity.value == 0 then
1328 return nil
1329 end
1330 local unit = nil
1331 if storeItem.specs.capacity.unit ~= nil then
1332 if storeItem.specs.capacity.unit:sub(1,6) == "$l10n_" then
1333 unit = g_i18n:getText(storeItem.specs.capacity.unit:sub(7));
1334 end;
1335 end
1336 return string.format(g_i18n:getText("shop_capacityValue"), storeItem.specs.capacity.value, Utils.getNoNil(unit, g_i18n:getText("unit_literShort")))
1337 end
1338 return nil
1339end

loadSpecValueFillTypes

Description
Loads capacity spec value
Definition
loadSpecValueFillTypes(integer xmlFile, string customEnvironment)
Arguments
integerxmlFileid of xml object
stringcustomEnvironmentcustom environment
Return Values
tablespecValue[categoryNames, fillTypes, fruitTypeCategoryNames, useWindrowed]
Code
1346function Fillable.loadSpecValueFillTypes(xmlFile, customEnvironment)
1347 local fillTypeNames = nil
1348 local fillTypeCategoryNames = nil
1349 local fruitTypeCategoryNames = nil
1350 local fillTypes = nil
1351
1352 local rootName = getXMLRootName(xmlFile)
1353
1354 local i=0;
1355 while true do
1356 local key = string.format(rootName..".fillUnits.fillUnit(%d)", i);
1357 if not hasXMLProperty(xmlFile, key) then
1358 break;
1359 end
1360 local currentFillTypes = getXMLString(xmlFile, key .. "#fillTypes");
1361 if currentFillTypes ~= nil then
1362 if fillTypeNames == nil then
1363 fillTypeNames = currentFillTypes
1364 else
1365 fillTypeNames = fillTypeNames .. " " .. currentFillTypes
1366 end
1367 end
1368 local currentFillTypeCategories = getXMLString(xmlFile, key .. "#fillTypeCategories");
1369 if currentFillTypeCategories ~= nil then
1370 if fillTypeCategoryNames == nil then
1371 fillTypeCategoryNames = currentFillTypeCategories
1372 else
1373 fillTypeCategoryNames = fillTypeCategoryNames .. " " .. currentFillTypeCategories
1374 end
1375 end
1376 i=i+1;
1377 end
1378
1379 if fillTypeNames == nil then
1380 fillTypeNames = getXMLString(xmlFile, rootName..".fillTypes");
1381 end
1382
1383 fillTypeNames = Utils.getNoNil(getXMLString(xmlFile, rootName..".storeData.specs.fillTypes"), fillTypeNames)
1384 if fillTypeNames ~= nil then
1385 fillTypes = FillUtil.getFillTypesByNames(fillTypeNames, nil)
1386 fillTypeCategoryNames = nil
1387 end
1388
1389 if fillTypeCategoryNames == nil then
1390 fillTypeCategoryNames = getXMLString(xmlFile, rootName..".fillTypeCategories")
1391 end
1392
1393 if fillTypes == nil then
1394 local fruitTypeNames = getXMLString(xmlFile, rootName..".fruitTypes")
1395 if fruitTypeNames ~= nil then
1396 fillTypes = FillUtil.getFillTypesByFruitTypeNames(fruitTypeNames, nil)
1397 end
1398 end
1399
1400 if fillTypes == nil then
1401 local fruitTypeNames = getXMLString(xmlFile, rootName..".cutter#fruitTypes")
1402 if fruitTypeNames ~= nil then
1403 fillTypes = FillUtil.getFillTypesByFruitTypeNames(fruitTypeNames, nil)
1404 end
1405 end
1406
1407 fruitTypeCategoryNames = getXMLString(xmlFile, rootName..".cutter#fruitTypeCategories")
1408 local useWindrowed = Utils.getNoNil(getXMLBool(xmlFile, rootName..".cutter#useWindrowed"), false)
1409
1410 fillTypeCategoryNames = Utils.getNoNil(getXMLString(xmlFile, rootName..".storeData.specs.fillTypeCategories"), fillTypeCategoryNames)
1411
1412 return {categoryNames=fillTypeCategoryNames, fillTypes=fillTypes, fruitTypeCategoryNames=fruitTypeCategoryNames, useWindrowed=useWindrowed}
1413end

getSpecValueFillTypes

Description
Returns capacity spec value
Definition
getSpecValueFillTypes(table storeItem, table realItem)
Arguments
tablestoreItemstore item
tablerealItemreal item
Return Values
tablefillTypesfill types
Code
1420function Fillable.getSpecValueFillTypes(storeItem, realItem)
1421 if storeItem.specs.fillTypes ~= nil then
1422 if storeItem.specs.fillTypes.categoryNames ~= nil then
1423 return FillUtil.getFillTypeByCategoryName(storeItem.specs.fillTypes.categoryNames, nil)
1424 elseif storeItem.specs.fillTypes.fillTypes ~= nil then
1425 return storeItem.specs.fillTypes.fillTypes
1426 elseif storeItem.specs.fillTypes.fruitTypeCategoryNames ~= nil then
1427 if storeItem.specs.fillTypes.useWindrowed then
1428 local fruitTypes = FruitUtil.getFruitTypeByCategoryName(storeItem.specs.fillTypes.fruitTypeCategoryNames, "Warning: Cutter has invalid fruitTypeCategory '%s'.")
1429 local windrowFillTypes = {};
1430
1431 for _, fruitType in pairs(fruitTypes) do
1432 table.insert(windrowFillTypes, FruitUtil.fruitTypeToWindrowFillType[fruitType]);
1433 end;
1434
1435 return windrowFillTypes;
1436 else
1437 return FillUtil.getFillTypesByFruitTypeCategoryName(storeItem.specs.fillTypes.fruitTypeCategoryNames, nil)
1438 end
1439 end
1440 end
1441 return nil
1442end