LUADOC - Farming Simulator 17

Printable Version

Script v1.4.4.0

Engine v7.0.0.2

Foundation Reference

FillVolume

Description
Class for vehicles with fill volumes
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
17function FillVolume.prerequisitesPresent(specializations)
18 return SpecializationUtil.hasSpecialization(Fillable, specializations);
19end

load

Description
Called on loading
Definition
load(table savegame)
Arguments
tablesavegamesavegame
Code
24function FillVolume:load(savegame)
25
26 self.getDischargeInfos = FillVolume.getDischargeInfos;
27
28 self.setUnitFillLevel = Utils.overwrittenFunction(self.setUnitFillLevel, FillVolume.setUnitFillLevel);
29
30 self.alsoUseFillVolumeLoadInfoForDischarge = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.alsoUseFillVolumeLoadInfoForDischarge"), false);
31
32 if self.isClient then
33 self.fillVolumes = {};
34 self.fillVolumeDeformers = {};
35 local i = 0;
36 while true do
37 local key = string.format("vehicle.fillVolumes.volumes.volume(%d)", i);
38 if not hasXMLProperty(self.xmlFile, key) then
39 break;
40 end
41
42 local fillVolume = {};
43
44 fillVolume.baseNode = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key.."#index"));
45 fillVolume.allSidePlanes = Utils.getNoNil(getXMLBool(self.xmlFile, key.."#allSidePlanes"), true);
46
47 local defaultFillType = getXMLString(self.xmlFile, key.."#defaultFillType");
48 if defaultFillType ~= nil then
49
50 local fillType = FillUtil.fillTypeNameToInt[defaultFillType];
51 if fillType ~= nil then
52 fillVolume.defaultFillType = fillType;
53 else
54 print("Warning: Invalid defaultFillType '"..tostring(defaultFillType).."' in '"..self.configFileName.."'");
55 end
56 end
57
58 fillVolume.maxDelta = Utils.getNoNil(getXMLFloat(self.xmlFile, key.."#maxDelta"), 1.0);
59 fillVolume.maxSurfaceAngle = math.rad( Utils.getNoNil(getXMLFloat(self.xmlFile, key.."#maxAllowedHeapAngle"), 35) );
60
61 local maxPhysicalSurfaceAngle = math.rad(35);
62 fillVolume.maxSubDivEdgeLength = Utils.getNoNil(getXMLFloat(self.xmlFile, key.."#maxSubDivEdgeLength"), 0.9);
63
64 local fillUnitIndex = Utils.getNoNil(getXMLInt(self.xmlFile, key.."#fillUnitIndex"), i+1);
65 if self.fillUnits == nil or self.fillUnits[fillUnitIndex] == nil then
66 print("Warning: '"..self.configFileName.. "' could not determine capacity for fillVolume!");
67 end
68 local capacity = self.fillUnits[fillUnitIndex].capacity;
69
70 fillVolume.volume = createFillPlaneShape(fillVolume.baseNode, "fillPlane", capacity, fillVolume.maxDelta, fillVolume.maxSurfaceAngle, maxPhysicalSurfaceAngle, fillVolume.maxSubDivEdgeLength, fillVolume.allSidePlanes);
71 setVisibility(fillVolume.volume, false);
72
73 fillVolume.deformers = {};
74 if fillVolume.volume ~= nil then
75 local j = 0;
76 while true do
77 local node = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key..".deformNode("..j..")#index"));
78 if node == nil then
79 break;
80 end
81 local initPos = { localToLocal(node, fillVolume.baseNode, 0,0,0) };
82 local polyline = findPolyline(fillVolume.volume, initPos[1],initPos[3]);
83 self.fillVolumeDeformers[node] = {node=node, initPos=initPos, posX=initPos[1], posZ=initPos[3], polyline=polyline, volume=fillVolume.volume, baseNode=fillVolume.baseNode};
84 j = j + 1;
85 end
86 end
87
88 fillVolume.scrollSpeedDischarge = { Utils.getVectorFromString(Utils.getNoNil(getXMLString(self.xmlFile, key.."#scrollSpeedDischarge"), "0 0 0")) };
89 fillVolume.scrollSpeedLoad = { Utils.getVectorFromString(Utils.getNoNil(getXMLString(self.xmlFile, key.."#scrollSpeedLoad"), "0 0 0")) };
90 for i=1,3 do
91 fillVolume.scrollSpeedDischarge[i] = fillVolume.scrollSpeedDischarge[i] / 1000;
92 fillVolume.scrollSpeedLoad[i] = fillVolume.scrollSpeedLoad[i] / 1000;
93 end
94 fillVolume.uvPosition = {0, 0, 0};
95
96 if fillVolume.volume ~= nil and fillVolume.volume ~= 0 then
97 link(fillVolume.baseNode, fillVolume.volume);
98 table.insert(self.fillVolumes, fillVolume);
99 end
100
101 i = i + 1;
102 end
103
104 self.fillVolumeHeights = {};
105 self.fillVolumeHeightRefNodeToFillVolumeHeight = {};
106 local i=0;
107 while true do
108 local key = string.format("vehicle.fillVolumes.heights.height(%d)", i);
109 if not hasXMLProperty(self.xmlFile, key) then
110 break;
111 end
112 local volumeHeight = {};
113 volumeHeight.fillVolumeIndex = getXMLInt(self.xmlFile, key.."#fillVolumeIndex");
114 volumeHeight.volumeHeightIsDirty = false;
115
116 volumeHeight.refNodes = {};
117 local j=0;
118 while true do
119 local refNode = Utils.indexToObject(self.components, getXMLString(self.xmlFile, string.format("%s.refNode(%d)#index", key, j)));
120 if refNode == nil then
121 break;
122 end
123 table.insert(volumeHeight.refNodes, {refNode=refNode});
124 self.fillVolumeHeightRefNodeToFillVolumeHeight[refNode] = volumeHeight;
125 j=j+1;
126 end
127
128 volumeHeight.nodes = {};
129 local j=0;
130 while true do
131 local node = Utils.indexToObject(self.components, getXMLString(self.xmlFile, string.format("%s.node(%d)#index", key, j)));
132 if node == nil then
133 break;
134 end
135 if node ~= nil then
136 local baseScale = { Utils.getVectorFromString(Utils.getNoNil(getXMLString(self.xmlFile, string.format("%s.node(%d)#baseScale", key, j)), "1 1 1")) };
137 local scaleAxis = { Utils.getVectorFromString(Utils.getNoNil(getXMLString(self.xmlFile, string.format("%s.node(%d)#scaleAxis", key, j)), "0 0 0")) };
138 local scaleMax = { Utils.getVectorFromString(Utils.getNoNil(getXMLString(self.xmlFile, string.format("%s.node(%d)#scaleMax", key, j)), "0 0 0")) };
139 local basePosition = { getTranslation(node) };
140 local transAxis = { Utils.getVectorFromString(Utils.getNoNil(getXMLString(self.xmlFile, string.format("%s.node(%d)#transAxis", key, j)), "0 0 0")) };
141 local transMax = { Utils.getVectorFromString(Utils.getNoNil(getXMLString(self.xmlFile, string.format("%s.node(%d)#transMax", key, j)), "0 0 0")) };
142 local orientateToWorldY = Utils.getNoNil(getXMLBool(self.xmlFile, string.format("%s.node(%d)#orientateToWorldY", key, j)), false);
143 table.insert(volumeHeight.nodes, {node=node, baseScale=baseScale, scaleAxis=scaleAxis, scaleMax=scaleMax, basePosition=basePosition, transAxis=transAxis, transMax=transMax, orientateToWorldY=orientateToWorldY});
144 end
145 j=j+1;
146 end
147
148 table.insert(self.fillVolumeHeights, volumeHeight);
149 i=i+1;
150 end
151
152 self.fillVolumeLoadInfos = {};
153 self.fillVolumeLoadInfos.name = "loadInfo";
154
155 self.fillVolumeUnloadInfos = {};
156 self.fillVolumeUnloadInfos.name = "unloadInfo";
157
158 self.fillVolumeDischargeInfos = {};
159 self.fillVolumeDischargeInfos.name = "dischargeInfo";
160
161 for _,tbl in pairs( {self.fillVolumeLoadInfos, self.fillVolumeUnloadInfos, self.fillVolumeDischargeInfos} ) do
162 local i=0;
163 while true do
164 if not hasXMLProperty(self.xmlFile, string.format("vehicle.fillVolumes."..tbl.name.."s."..tbl.name.."(%d)", i)) then
165 break;
166 end
167 local entry = {};
168 entry.fillVolumeIndex = Utils.getNoNil(getXMLInt(self.xmlFile, string.format("vehicle.fillVolumes."..tbl.name.."s."..tbl.name.."(%d)#fillVolumeIndex", 1)), 1);
169 entry.nodes = {};
170 local j=0;
171 while true do
172 local key = string.format("vehicle.fillVolumes."..tbl.name.."s."..tbl.name.."(%d).node(%d)", i, j);
173 if not hasXMLProperty(self.xmlFile, key) then
174 break;
175 end
176
177 local nodeEntry = {};
178 nodeEntry.node = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key .. "#index"));
179 nodeEntry.width = Utils.getNoNil(getXMLFloat(self.xmlFile, key .. "#width"), 1.0);
180 nodeEntry.length = Utils.getNoNil(getXMLFloat(self.xmlFile, key .. "#length"), 1.0);
181
182 nodeEntry.fillVolumeHeightIndex = getXMLInt(self.xmlFile, key .. "#fillVolumeHeightIndex");
183 nodeEntry.priority = Utils.getNoNil(getXMLInt(self.xmlFile, key .. "#priority"), 1);
184 nodeEntry.minHeight = getXMLFloat(self.xmlFile, key .. "#minHeight");
185 nodeEntry.maxHeight = getXMLFloat(self.xmlFile, key .. "#maxHeight");
186 nodeEntry.minFillLevelPercentage = getXMLFloat(self.xmlFile, key .. "#minFillLevelPercentage");
187 nodeEntry.maxFillLevelPercentage = getXMLFloat(self.xmlFile, key .. "#maxFillLevelPercentage");
188
189 nodeEntry.heightForTranslation = getXMLFloat(self.xmlFile, key .. "#heightForTranslation");
190 nodeEntry.translationStart = Utils.getVectorNFromString(getXMLString(self.xmlFile, key .. "#translationStart"), 3);
191 nodeEntry.translationEnd = Utils.getVectorNFromString(getXMLString(self.xmlFile, key .. "#translationEnd"), 3);
192 nodeEntry.translationAlpha = 0;
193
194 table.insert(entry.nodes, nodeEntry);
195
196 j=j+1;
197 end
198 table.sort(entry.nodes, function(a, b) return a.priority > b.priority end);
199 table.insert(tbl, entry);
200 i=i+1;
201 end
202 end
203
204 end
205
206 self.fillVolumeDirtyFlag = self:getNextDirtyFlag();
207end

delete

Description
Called on deleting
Definition
delete()
Code
210function FillVolume:delete()
211 for _, fillVolume in pairs(self.fillVolumes) do
212 if fillVolume.volume ~= nil then
213 delete(fillVolume.volume);
214 end
215 fillVolume.volume = nil;
216 end
217end

update

Description
Called on update
Definition
update(float dt)
Arguments
floatdttime since last call in ms
Code
248function FillVolume:update(dt)
249 if self.isClient then
250 for _,deformer in pairs(self.fillVolumeDeformers) do
251 if deformer.deformerIsDirty and deformer.polyline ~= nil and deformer.polyline ~= -1 then
252 deformer.deformerIsDirty = false;
253 local posX, _, posZ = localToLocal(deformer.node, deformer.baseNode, 0,0,0);
254 if math.abs(posX - deformer.posX) > 0.0001 or math.abs(posZ - deformer.posZ) > 0.0001 then
255 deformer.lastPosX = posX;
256 deformer.lastPosZ = posZ;
257 local dx = posX - deformer.initPos[1];
258 local dz = posZ - deformer.initPos[3];
259 setPolylineTranslation(deformer.volume, deformer.polyline, dx,dz);
260 end
261 end
262 end
263
264 for _,fillVolumeHeight in pairs(self.fillVolumeHeights) do
265 if fillVolumeHeight.volumeHeightIsDirty == true and self.fillVolumes[fillVolumeHeight.fillVolumeIndex] ~= nil then
266 fillVolumeHeight.volumeHeightIsDirty = false;
267
268 local baseNode = self.fillVolumes[fillVolumeHeight.fillVolumeIndex].baseNode;
269 local volumeNode = self.fillVolumes[fillVolumeHeight.fillVolumeIndex].volume;
270
271 if baseNode ~= nil and volumeNode ~= nil then
272
273 local minHeight = math.huge;
274 local maxHeight = -math.huge;
275 local maxHeightWorld = -math.huge;
276 for _,refNode in pairs(fillVolumeHeight.refNodes) do
277 local x,_,z = localToLocal(refNode.refNode, baseNode, 0,0,0);
278 local height = getFillPlaneHeightAtLocalPos(volumeNode, x,z);
279 minHeight = math.min(minHeight, height);
280 maxHeight = math.max(maxHeight, height);
281 local _,yw,_ = localToWorld(baseNode, x,height,z);
282 maxHeightWorld = math.max(maxHeightWorld, yw);
283 end
284 fillVolumeHeight.currentMinHeight = minHeight;
285 fillVolumeHeight.currentMaxHeight = maxHeight;
286 fillVolumeHeight.currentMaxHeightWorld = maxHeightWorld;
287
288 for _,node in pairs(fillVolumeHeight.nodes) do
289 local sx = node.scaleAxis[1]*minHeight;
290 local sy = node.scaleAxis[2]*minHeight;
291 local sz = node.scaleAxis[3]*minHeight;
292 if node.scaleMax[1] > 0 then
293 sx = math.min(node.scaleMax[1], sx);
294 end
295 if node.scaleMax[2] > 0 then
296 sy = math.min(node.scaleMax[2], sy);
297 end
298 if node.scaleMax[3] > 0 then
299 sz = math.min(node.scaleMax[3], sz);
300 end
301 local tx = node.transAxis[1]*minHeight;
302 local ty = node.transAxis[2]*minHeight;
303 local tz = node.transAxis[3]*minHeight;
304 if node.transMax[1] > 0 then
305 tx = math.min(node.transMax[1], tx);
306 end
307 if node.transMax[2] > 0 then
308 ty = math.min(node.transMax[2], ty);
309 end
310 if node.transMax[3] > 0 then
311 tz = math.min(node.transMax[3], tz);
312 end
313
314 setScale(node.node, node.baseScale[1]+sx, node.baseScale[2]+sy, node.baseScale[3]+sz);
315 setTranslation(node.node, node.basePosition[1]+tx, node.basePosition[2]+ty, node.basePosition[3]+tz);
316
317 if node.orientateToWorldY then
318 local _,dy,_ = localDirectionToWorld(getParent(node.node), 0,1,0);
319 local alpha = math.acos(dy);
320 setRotation(node.node, alpha,0,0);
321 end
322 end
323 end
324 end
325 end
326 end
327end

setMovingToolDirty

Description
Set moving tool dirty
Definition
setMovingToolDirty(integer node)
Arguments
integernodenode id
Code
332function FillVolume:setMovingToolDirty(node)
333 if self.fillVolumeDeformers ~= nil and self.fillVolumeDeformers[node] ~= nil then
334 self.fillVolumeDeformers[node].deformerIsDirty = true;
335 end
336 if self.fillVolumeHeightRefNodeToFillVolumeHeight ~= nil and self.fillVolumeHeightRefNodeToFillVolumeHeight[node] ~= nil then
337 self.fillVolumeHeightRefNodeToFillVolumeHeight[node].volumeHeightIsDirty = true;
338 end
339end

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
354function FillVolume:setUnitFillLevel(superFunc, fillUnitIndex, fillLevel, fillType, force, fillInfo)
355 local fillUnit = self.fillUnits[fillUnitIndex];
356 if fillUnit == nil then
357 return;
358 end
359
360 local lastFillType = fillUnit.currentFillType;
361 local oldFillLevel = fillUnit.fillLevel;
362 superFunc(self, fillUnitIndex, fillLevel, fillType, force, fillInfo);
363 local delta = fillUnit.fillLevel - oldFillLevel;
364
365 if self.isClient then
366
367 local fillVolume = self.fillVolumes[fillUnit.fillVolumeIndex];
368 if fillVolume == nil then
369 return;
370 end
371
372 if fillType ~= fillUnit.currentFillType then
373 local maxPhysicalSurfaceAngle;
374 if FillUtil.fillTypeIntToName[fillType] ~= nil then
375 maxPhysicalSurfaceAngle = FillUtil.fillTypeIntToName[fillType].maxPhysicalSurfaceAngle;
376 end
377 if maxPhysicalSurfaceAngle ~= nil then
378 if fillVolume.volume ~= nil then
379 setFillPlaneMaxPhysicalSurfaceAngle(fillVolume.volume, maxPhysicalSurfaceAngle);
380 end
381 end
382 end
383
384 setVisibility(fillVolume.volume, fillUnit.fillLevel > 0);
385
386 local material = nil;
387 if fillUnit.currentFillType ~= FillUtil.FILLTYPE_UNKNOWN and fillUnit.currentFillType ~= lastFillType then
388 local usedFillType = fillUnit.currentFillType;
389 if fillUnit.forcedFillPlaneType ~= nil then
390 usedFillType = fillUnit.forcedFillPlaneType;
391 end
392 material = MaterialUtil.getMaterial(usedFillType, "fillplane", 1);
393 end
394
395 if fillUnit.currentFillType ~= FillUtil.FILLTYPE_UNKNOWN and fillUnit.currentFillType ~= lastFillType then
396 if material == nil and fillVolume.defaultFillType ~= nil then
397 material = MaterialUtil.getMaterial(fillVolume.defaultFillType, "fillplane", 1);
398 end
399 if material ~= nil then
400 setMaterial(fillVolume.volume, material, 0);
401 end
402 end
403
404 if fillInfo ~= nil and fillInfo.nodes ~= nil then
405
406 local availableFillNodes = {};
407 local neededPriority = fillInfo.nodes[1].priority;
408
409 while table.getn(availableFillNodes) == 0 and neededPriority >= 1 do
410
411 for _,node in pairs(fillInfo.nodes) do
412 if node.priority >= neededPriority then
413 local doInsert = true;
414
415 if node.minHeight ~= nil or node.maxHeight ~= nil and fillInfo.fillVolumeIndex ~= nil and self.fillVolumes[fillInfo.fillVolumeIndex].baseNode ~= nil and self.fillVolumes[fillInfo.fillVolumeIndex].volume ~= nil then
416
417 local baseNode = self.fillVolumes[fillInfo.fillVolumeIndex].baseNode;
418 local volumeNode = self.fillVolumes[fillInfo.fillVolumeIndex].volume;
419
420 local height = -math.huge;
421 if node.fillVolumeHeightIndex ~= nil and self.fillVolumeHeights[node.fillVolumeHeightIndex] ~= nil then
422 for _,refNode in pairs(self.fillVolumeHeights[node.fillVolumeHeightIndex].refNodes) do
423 local x,_,z = localToLocal(refNode.refNode, baseNode, 0,0,0);
424 height = math.max(height, getFillPlaneHeightAtLocalPos(volumeNode, x,z));
425 end
426 else
427 local x,_,z = localToLocal(node.node, baseNode, 0,0,0);
428 height = math.max(height, getFillPlaneHeightAtLocalPos(volumeNode, x,z));
429 end
430
431 if node.minHeight ~= nil and height < node.minHeight then
432 doInsert = false;
433 end
434 if node.maxHeight ~= nil and height > node.maxHeight then
435 doInsert = false;
436 end
437
438 if node.heightForTranslation ~= nil then
439 if height > node.heightForTranslation then
440 node.translationAlpha = node.translationAlpha + 0.01;
441 local x,y,z = Utils.vector3ArrayLerp(node.translationStart, node.translationEnd, node.translationAlpha);
442 setTranslation(node.node, x,y,z);
443 else
444 node.translationAlpha = node.translationAlpha - 0.01;
445 end
446 node.translationAlpha = Utils.clamp(node.translationAlpha, 0, 1);
447 end
448
449 end
450
451 if node.minFillLevelPercentage ~= nil or node.maxFillLevelPercentage ~= nil then
452 local percentage = self:getUnitFillLevel(fillUnitIndex) / self:getUnitCapacity(fillUnitIndex);
453
454 if node.minFillLevelPercentage ~= nil and percentage < node.minFillLevelPercentage then
455 doInsert = false;
456 end
457 if node.maxFillLevelPercentage ~= nil and percentage > node.maxFillLevelPercentage then
458 doInsert = false;
459 end
460 end
461
462 if doInsert then
463 table.insert(availableFillNodes, node);
464 end
465 end
466 end
467 if table.getn(availableFillNodes) > 0 then
468 break;
469 end
470 neededPriority = neededPriority - 1;
471 end
472
473 local numFillNodes = table.getn(availableFillNodes);
474 for i=1,numFillNodes do
475 local node = availableFillNodes[i];
476
477 local x0,y0,z0 = getWorldTranslation(node.node);
478 local d1x,d1y,d1z = localDirectionToWorld(node.node, node.width,0,0);
479 local d2x,d2y,d2z = localDirectionToWorld(node.node, 0,0,node.length);
480
481 if Vehicle.debugRendering then
482 drawDebugLine( x0,y0,z0, 1,0,0, x0+d1x, y0+d1y, z0+d1z, 1,0,0 );
483 drawDebugLine( x0,y0,z0, 0,0,1, x0+d2x, y0+d2y, z0+d2z, 0,0,1 );
484 drawDebugPoint( x0,y0,z0, 1,1,1,1 );
485 drawDebugPoint( x0+d1x, y0+d1y, z0+d1z, 1,0,0,1 );
486 drawDebugPoint( x0+d2x, y0+d2y, z0+d2z, 0,0,1,1 );
487 end
488 x0 = x0 - (d1x + d2x) / 2;
489 y0 = y0 - (d1y + d2y) / 2;
490 z0 = z0 - (d1z + d2z) / 2;
491 fillPlaneAdd(fillVolume.volume, delta/numFillNodes, x0,y0,z0, d1x,d1y,d1z, d2x,d2y,d2z);
492 end
493 else
494 local x,y,z = localToWorld(fillVolume.volume, 0,100,0);
495 local d1x,d1y,d1z = localDirectionToWorld(fillVolume.volume, 5,0,0);
496 local d2x,d2y,d2z = localDirectionToWorld(fillVolume.volume, 0,0,5);
497 x = x - (d1x+d2x)/2;
498 y = y - (d1y+d2y)/2;
499 z = z - (d1z+d2z)/2;
500 fillPlaneAdd(fillVolume.volume, delta, x,y,z, d1x,d1y,d1z, d2x,d2y,d2z);
501 end
502
503 end
504
505
506end

getDischargeInfos

Description
Returns discharge infos by index
Definition
getDischargeInfos(integer index)
Arguments
integerindexindex
Return Values
tabledischargeInfodischarge info
Code
512function FillVolume:getDischargeInfos(index)
513 local infos;
514 if self.fillVolumeDischargeInfos[index] ~= nil then
515 infos = self.fillVolumeDischargeInfos[index];
516 else
517 if self.fillVolumeUnloadInfos[index] ~= nil then
518 infos = self.fillVolumeUnloadInfos[index];
519 end
520 end
521 return infos;
522end